diff -ur linux-heretic-0.9.1.orig/AUTHORS linux-heretic-0.9.1/AUTHORS
--- linux-heretic-0.9.1.orig/AUTHORS	Thu Jan 21 00:13:32 1999
+++ linux-heretic-0.9.1/AUTHORS	Thu Jan 21 04:05:20 1999
@@ -7,3 +7,5 @@
 		now !
 
 Nic Bellamy: added SVGAlib code for 0.9.1.
+
+Marcus Sundberg: Working GGI code. Keyboard fixes.
diff -ur linux-heretic-0.9.1.orig/Changelog linux-heretic-0.9.1/Changelog
--- linux-heretic-0.9.1.orig/Changelog	Thu Jan 21 00:16:13 1999
+++ linux-heretic-0.9.1/Changelog	Thu Jan 21 04:08:07 1999
@@ -1,3 +1,13 @@
+0.9.1.1:
+* GGI updates:
+	- Now uses DirectBuffer when available and works properly when it is
+	  not.
+	- Support for scaling by a factor of 2.
+	- Support for 8, 15, 16 and 32 bpp modes (24 can be achieved with the
+	  palemu target)
+* Proper keyboard handling (the cheats work now ;)
+* Simple FPS meter for GGI and X11 versions.
+
 0.9.0 -> 0.9.1:
 It is now possible to compile and run Heretic for X11 under 
 Linux/x86, Linux/m68k and FreeBSD. (Alpha doesn't work now.)
diff -ur linux-heretic-0.9.1.orig/Gamekeys.txt linux-heretic-0.9.1/Gamekeys.txt
--- linux-heretic-0.9.1.orig/Gamekeys.txt	Wed Jan 20 17:26:38 1999
+++ linux-heretic-0.9.1/Gamekeys.txt	Thu Jan 21 03:18:37 1999
@@ -7,18 +7,18 @@
 key-strafe-left:     ','
 key-strafe-right:    '.'
 
-key_fire:            Space-key
-key_use:             'x'
-key_strafe:          'c'
-key_speed:           'y'
+key_fire:            Control-key
+key_use:             Space-key
+key_strafe:          Alt/Meta-key
+key_speed:           Shift-key
 
-key_flyup:           'j'
-key_flydown:         'g'
-key_flycenter:       'h'
+key_flyup:           PageUp-key
+key_flydown:         Insert-key
+key_flycenter:       Home-key
 
-key_lookup:          'm'
-key_lookdown:        'b'
-key_lookcenter:      'n'
+key_lookup:          PageDown-key
+key_lookdown:        Delete-key
+key_lookcenter:      End-key
 
 key_invleft:         'k'
 key_invright:        'l'
diff -ur linux-heretic-0.9.1.orig/README.txt linux-heretic-0.9.1/README.txt
--- linux-heretic-0.9.1.orig/README.txt	Thu Jan 21 00:28:15 1999
+++ linux-heretic-0.9.1/README.txt	Thu Jan 21 04:09:51 1999
@@ -41,8 +41,12 @@
 >) The modifcations to the original source code are free under the GPL
 >) Read Gamekeys.txt for the keys used in the Game.
 >) You need at least the shareware-version of the Heretic WAD !
->) The GGI-version runs only in 8bpp color-mode under X11
->) The X11-version runs under every colordepth above 8bpp, but performs best under 8bpp mode
+>) The GGI-version runs in 8, 15, 16 and 32 bpp. If you want to run it on
+   a 24bpp X display you can use the palemu target
+   (GGI_DISPLAY=palemu ggiheretic). Note that in higher depths GGI-on-X is
+   _much_ faster than the native X11-version, especially on a scaled display.
+>) The X11-version runs under every colordepth above 8bpp, but performs best
+   under 8bpp mode
 >) The SVGAlib-version runs under a console. You must be root to run
    vgaheretic, or set the suid-bit for vgaheretic.
 >) To use a different wadfile than heretic.wad, use the '-file' switch
diff -ur linux-heretic-0.9.1.orig/doomdef.h linux-heretic-0.9.1/doomdef.h
--- linux-heretic-0.9.1.orig/doomdef.h	Wed Jan 20 17:14:15 1999
+++ linux-heretic-0.9.1/doomdef.h	Thu Jan 21 03:29:21 1999
@@ -28,7 +28,7 @@
 #define VERSION_TEXT "v1.3"
 
 /*
- * most key data are simple ascii (uppercased)
+ * most key data are simple ascii (lowercased)
  */
 #define	KEY_RIGHTARROW		        0xae
 #define	KEY_LEFTARROW		        0xac
@@ -49,6 +49,13 @@
 #define	KEY_F10				(0x80+0x44)
 #define	KEY_F11				(0x80+0x57)
 #define	KEY_F12				(0x80+0x58)
+
+#define KEY_INSERT			(0x80+0x59)
+#define KEY_DELETE			(0x80+0x5a)
+#define KEY_HOME			(0x80+0x5b)
+#define KEY_END				(0x80+0x5c)
+#define KEY_PAGEUP			(0x80+0x5d)
+#define KEY_PAGEDOWN			(0x80+0x5f)
 
 #define	KEY_BACKSPACE		        127
 #define	KEY_PAUSE			0xff
diff -ur linux-heretic-0.9.1.orig/heretic.cfg linux-heretic-0.9.1/heretic.cfg
--- linux-heretic-0.9.1.orig/heretic.cfg	Thu Jan 21 00:37:57 1999
+++ linux-heretic-0.9.1/heretic.cfg	Thu Jan 21 04:01:55 1999
@@ -7,16 +7,16 @@
 key_down		175
 key_strafeleft		44
 key_straferight		46
-key_fire		32
-key_use		120
-key_strafe		99
-key_speed		121
-key_flyup		106
-key_flydown		103
-key_flycenter		104
-key_lookup		109
-key_lookdown		98
-key_lookcenter		110
+key_fire		157
+key_use		32
+key_strafe		184
+key_speed		182
+key_flyup		221
+key_flydown		217
+key_flycenter		219
+key_lookup		223
+key_lookdown		218
+key_lookcenter		220
 key_invleft		107
 key_invright		108
 key_useartifact		13
diff -ur linux-heretic-0.9.1.orig/i_ggi.c linux-heretic-0.9.1/i_ggi.c
--- linux-heretic-0.9.1.orig/i_ggi.c	Wed Jan 20 22:12:52 1999
+++ linux-heretic-0.9.1/i_ggi.c	Thu Jan 21 03:50:23 1999
@@ -1,63 +1,182 @@
-
 #include <stdlib.h>
-#include <unistd.h>
-#include <signal.h>
 #include <ggi/ggi.h>
 
 #include "doomdef.h"
 
+#define SHOW_FPS
+
+static ggi_visual_t ggivis=NULL;
+
+#ifdef SHOW_FPS
+#include <unistd.h>
+#include <sys/time.h>
+
+static struct timeval	starttime;
+static long		totalframes;
+static int		showfps = 0;
+
+static void reset_framecounter(void)
+{
+	ggi_color black = { 0x0, 0x0, 0x0 };
+	ggi_color white = { 0xffff, 0xffff, 0xffff };
+
+	/* Set text colors */
+	ggiSetGCForeground(ggivis, ggiMapColor(ggivis, &white));
+	ggiSetGCBackground(ggivis, ggiMapColor(ggivis, &black));
+
+	totalframes = 0;
+	gettimeofday(&starttime, NULL);
+}
+#endif
+
 static int     lastmousex = 0;
 static int     lastmousey = 0;
 boolean        mousemoved = false;
 int            buttonstate=0;
 
-static ggi_visual_t ggivis=NULL;
-
-static int     width;
-static int     height;
+static int     realwidth, realheight;
 static int     db;
+static int     scale;
+static int     stride;
+static int     pixelsize;
+
 static const ggi_directbuffer *dbuf1, *dbuf2;
-static int     usedbuf;
-static uint8  *frameptr = NULL;
+static int     usedbuf, havedbuf;;
+static void   *frameptr[2] = { NULL, NULL };
+static void   *oneline = NULL;
+static void   *palette = NULL;
 static int     curframe = 0;
 static int     modexrefresh=0;
 
-/* #define KEY_DEBUG */
+static inline void
+do_scale8(int xsize, int ysize, uint8 *dest, uint8 *src)
+{
+	int i, j, destinc = stride*2;
+	for (j = 0; j < ysize; j++) {
+		int mul = 0;
+		for (i = 0; i < xsize; /* i is incremented below */) {
+			register uint32 pix1 = src[i++], pix2 = src[i++];
+#ifdef GGI_LITTLE_ENDIAN
+			*((uint32 *) (dest + mul + stride))
+				= *((uint32 *) (dest + mul))
+				= (pix1 | (pix1 << 8)
+				   | (pix2 << 16) | (pix2 << 24));
+#else
+			*((uint32 *) (dest + mul + stride))
+				= *((uint32 *) (dest + mul))
+				= (pix2 | (pix2 << 8)
+				   | (pix1 << 16) | (pix1 << 24));
+#endif
+			mul += 4;
+		}
+		dest += destinc;
+		src += xsize;
+	}
+}
 
-#ifdef KEY_DEBUG
-char str[32];
-char *bits(int a)
+static inline void
+do_scale16(int xsize, int ysize, uint8 *dest, uint8 *src)
 {
-	int i;
-	for (i=0;i<8;i++) str[16-i]=((a & (1<<i))!=0)+'0';
-	str[8]=' ';
-	for (i=8;i<16;i++) str[15-i]=((a & (1<<i))!=0)+'0';
-	return str;
+	int i, j, destinc = stride*2;
+	uint16 *palptr = palette;
+	for (j = 0; j < ysize; j++) {
+		int mul = 0;
+		for (i = 0; i < xsize; /* i is incremented below */) {
+			register uint32 pixel = palptr[src[i++]];
+			*((uint32 *) (dest + mul + stride))
+				= *((uint32 *) (dest + mul))
+				= pixel | (pixel << 16);
+			mul += 4;
+		}
+		dest += destinc;
+		src += xsize;
+	}
+}
+
+static inline void
+do_scale32(int xsize, int ysize, uint8 *dest, uint8 *src)
+{
+	int i, j, destinc = stride*2-xsize*8;
+	uint32 *palptr = palette;
+	for (j = 0; j < ysize; j++) {
+		for (i = 0; i < xsize; /* i is incremented below */) {
+			register uint32 pixel = palptr[src[i++]];
+			*((uint32 *) (dest + stride))
+				= *((uint32 *) (dest)) = pixel;
+			dest += 4;
+			*((uint32 *) (dest + stride))
+				= *((uint32 *) (dest)) = pixel;
+			dest += 4;
+		}
+		dest += destinc;
+		src += xsize;
+	}
+}
+
+
+static inline void
+do_copy8(int xsize, int ysize, uint8 *dest, uint8 *src)
+{
+	int i, j;
+	uint8 *palptr = palette;
+	
+	for (j = 0; j < ysize; j++) {
+		for (i = 0; i < xsize; i++) {
+			dest[i] = palptr[src[i]];
+		}
+		dest += stride;
+		src += xsize;
+	}
+}
+
+static inline void
+do_copy16(int xsize, int ysize, uint16 *dest, uint8 *src)
+{
+	int i, j, destinc = stride/2;
+	uint16 *palptr = palette;
+	
+	for (j = 0; j < ysize; j++) {
+		for (i = 0; i < xsize; i++) {
+			dest[i] = palptr[src[i]];
+		}
+		dest += destinc;
+		src += xsize;
+	}
+}
+
+static inline void
+do_copy32(int xsize, int ysize, uint32 *dest, uint8 *src)
+{
+	int i, j, destinc = stride/4;
+	uint32 *palptr = palette;
+	
+	for (j = 0; j < ysize; j++) {
+		for (i = 0; i < xsize; i++) {
+			dest[i] = palptr[src[i]];
+		}
+		dest += destinc;
+		src += xsize;
+	}
 }
-#endif
+
 
 int key(int label, int sym)
 {
 	int rc=0;
-#ifdef KEY_DEBUG
-	char text[100];
-	ggiSetGCForeground(ggivis,0);
-	ggiDrawBox(ggivis,0,0,320,24);
-	ggiSetGCForeground(ggivis,255);
-	sprintf(text," %c", label);
-	ggiPuts(ggivis,0,0,text);
-	sprintf(text," %i %x %s",label,label,bits(label));
-	ggiPuts(ggivis,0,8,text);
-	sprintf(text," %i %x %s",code,code,bits(code));
-	ggiPuts(ggivis,0,16,text);
-        ggiFlush(ggivis);
-#endif
 	switch(label) {
 	case GIIK_CtrlL:  case GIIK_CtrlR:  rc=KEY_RCTRL; 	break;
 	case GIIK_ShiftL: case GIIK_ShiftR: rc=KEY_RSHIFT;	break;
+	case GIIK_MetaL:  case GIIK_MetaR:
 	case GIIK_AltL:   case GIIK_AltR:   rc=KEY_RALT;	break;
 		
-	case GIIUC_Escape: rc = KEY_ESCAPE;	break;
+	case GIIUC_BackSpace:	rc = KEY_BACKSPACE;	break;
+	case GIIUC_Escape:	rc = KEY_ESCAPE;	break;
+	case GIIK_Delete:	rc = KEY_DELETE;	break;
+	case GIIK_Insert:	rc = KEY_INSERT;	break;
+	case GIIK_PageUp:	rc = KEY_PAGEUP;	break;
+	case GIIK_PageDown:	rc = KEY_PAGEDOWN;	break;
+	case GIIK_Home:	rc = KEY_HOME;		break;
+	case GIIK_End:	rc = KEY_END;		break;
 	case GIIUC_Tab:	rc = KEY_TAB;		break;
 	case GIIK_Up:	rc = KEY_UPARROW;	break;
 	case GIIK_Down:	rc = KEY_DOWNARROW;	break;
@@ -79,7 +198,13 @@
 	case GIIK_Pause:rc = KEY_PAUSE;		break;
 
 	default:
-		if (sym < 256) {
+		if ((label > '0' && label < '9') ||
+		    label == '.' ||
+		    label == ',') {
+			/* Must use label here, or it won't work when whift
+			   is down */
+			rc = label;
+		} else if (sym < 256) {
 			/* ASCII key - we want those */
 			rc = sym;
 			/* We want lowercase */
@@ -87,6 +212,7 @@
 			switch (sym) {
 				/* Some special cases */
 			case '+': rc = KEY_EQUALS;	break;
+			case '-': rc = KEY_MINUS;
 			default:			break;
 			}
 		}
@@ -98,7 +224,15 @@
 {
 	if (ggivis != NULL) {
 		if (!usedbuf) {
-			free(frameptr);
+			free(screen);
+		}
+		if (oneline) {
+			free(oneline);
+			oneline = NULL;
+		}
+		if (palette) {
+			free(palette);
+			palette = NULL;
 		}
 		ggiClose(ggivis);
 		ggivis = NULL;
@@ -115,8 +249,8 @@
 {
 	event_t event;
 	ggi_event ev;
-        ggi_event_mask mask;
-	
+	ggi_event_mask mask;
+
 	while (1) {
 		struct timeval t={0,0};
 		mask = ggiEventPoll(ggivis,emAll,&t);
@@ -128,6 +262,14 @@
 			case evKeyPress:
 				event.type = ev_keydown;
 				event.data1 = key(ev.key.label,ev.key.sym);
+#ifdef SHOW_FPS
+				if (event.data1 == KEY_BACKSPACE &&
+				    gamestate == GS_LEVEL) {
+					/* Toggle and reset the FPS counter */
+					showfps = !showfps;
+					reset_framecounter();
+				}
+#endif
 				D_PostEvent(&event);
 				break;
 			case evKeyRelease:
@@ -220,26 +362,132 @@
 		
 	}
 	if (!usedbuf) {
-		if (!modexrefresh) {
+		if (scale) {
+			switch (pixelsize) {
+			case 1:	if (havedbuf) {
+				do_scale8(screenwidth, screenheight,
+					 frameptr[curframe], screen);
+			} else {
+				uint8 *buf = screen;
+				for (i=0; i < screenheight; i++) {
+					do_scale8(screenwidth, 1, oneline,buf);
+					ggiPutBox(ggivis, 0, i*2, realwidth,
+						  2, oneline);
+					buf += screenwidth;
+				}
+			}
+			break;
+			case 2: if (havedbuf) {
+				do_scale16(screenwidth, screenheight,
+					   frameptr[curframe], screen);
+			} else {
+				uint8 *buf = screen;
+				for (i=0; i < screenheight; i++) {
+					do_scale16(screenwidth, 1,
+						   oneline, buf);
+					ggiPutBox(ggivis, 0, i*2, realwidth,
+						  2, oneline);
+					buf += screenwidth;
+				}
+			}
+			break;
+			case 4: if (havedbuf) {
+				do_scale32(screenwidth, screenheight,
+					   frameptr[curframe], screen);
+			} else {
+				uint8 *buf = screen;
+				for (i=0; i < screenheight; i++) {
+					do_scale32(screenwidth, 1,
+						   oneline, buf);
+					ggiPutBox(ggivis, 0, i*2, realwidth,
+						  2, oneline);
+					buf += screenwidth;
+				}
+			}
+			break;
+			}
+		} else if (palette) {
+			switch (pixelsize) {
+			case 1:	if (havedbuf) {
+				do_copy8(screenwidth, screenheight,
+					 frameptr[curframe], screen);
+			} else {
+				uint8 *buf = screen;
+				for (i=0; i < screenheight; i++) {
+					do_copy8(screenwidth, 1, oneline,buf);
+					ggiPutBox(ggivis, 0, i, realwidth,
+						  1, oneline);
+					buf += screenwidth;
+				}
+			}
+			break;
+			case 2: if (havedbuf) {
+				do_copy16(screenwidth, screenheight,
+					  frameptr[curframe], screen);
+			} else {
+				uint8 *buf = screen;
+				for (i=0; i < screenheight; i++) {
+					do_copy16(screenwidth, 1,
+						   oneline, buf);
+					ggiPutBox(ggivis, 0, i, realwidth,
+						  1, oneline);
+					buf += screenwidth;
+				}
+			}
+			break;
+			case 4: if (havedbuf) {
+				do_copy32(screenwidth, screenheight,
+					   frameptr[curframe], screen);
+			} else {
+				uint8 *buf = screen;
+				for (i=0; i < screenheight; i++) {
+					do_copy32(screenwidth, 1,
+						   oneline, buf);
+					ggiPutBox(ggivis, 0, i, realwidth,
+						  1, oneline);
+					buf += screenwidth;
+				}
+			}
+			break;
+			}
+		} else if (!modexrefresh) {
 			/* faster, but ugly in ModeX modes */
-			ggiPutBox(ggivis,0,0,width,height,screen);
+			ggiPutBox(ggivis, 0, 0, screenwidth, screenheight,
+				  screen);
 		} else {
 			/* slower, but nicer in ModeX modes */
-			unsigned char *buf=screen;
-			for (i=0; i<height; i++) {
-				ggiPutHLine(ggivis,0,i,width,buf);
-				buf += width;
+			uint8 *buf = screen;
+			for (i = 0; i < screenheight; i++) {
+				ggiPutHLine(ggivis, 0, i, screenwidth, buf);
+				buf += screenwidth;
 			}
 		}
 	}
+#ifdef SHOW_FPS
+	if (showfps) {
+		struct timeval curtime;
+		double diff;
+		char str[64];
+		
+		totalframes++;
+		gettimeofday(&curtime, NULL);
+		diff = (curtime.tv_sec - starttime.tv_sec);
+		diff += ((double)curtime.tv_usec - starttime.tv_usec)/1000000;
+		if (diff != 0) {
+			sprintf(str, "FPS: %.1f", totalframes/diff);
+			ggiPuts(ggivis, 1, 1, str);
+		}
+	}
+#endif
 	if (db) {
 		ggiSetDisplayFrame(ggivis, curframe);
 		curframe = !curframe;
-		screen = frameptr;
-		/* This might be needed for palette ops */
+		if (usedbuf) {
+			screen = frameptr[curframe];
+		}
 		ggiSetWriteFrame(ggivis, curframe);
 	}
-		
+	
        	ggiFlush(ggivis);
 	I_GetEvent();
 }
@@ -248,15 +496,18 @@
 {
 	int i;
 	ggi_color col[256];
-	byte *gamma=gammatable[usegamma];
+	byte *gamma = gammatable[usegamma];
 	
-	for (i=0;i<256;i++)
-		{
-		col[i].r=gamma[(*pal++)] << (GGI_COLOR_PRECISION-8);
-		col[i].g=gamma[(*pal++)] << (GGI_COLOR_PRECISION-8);
-		col[i].b=gamma[(*pal++)] << (GGI_COLOR_PRECISION-8);
+	for (i = 0; i < 256; i++) {
+		col[i].r = gamma[(*pal++)] << (GGI_COLOR_PRECISION-8);
+		col[i].g = gamma[(*pal++)] << (GGI_COLOR_PRECISION-8);
+		col[i].b = gamma[(*pal++)] << (GGI_COLOR_PRECISION-8);
+	}
+	if (palette) {
+		ggiPackColors(ggivis, palette, col, 256);
+	} else {
+		ggiSetPalette(ggivis, 0, 256, col);
 	}
-	ggiSetPalette(ggivis,0,256,col);
 }
 
 void I_CheckRes()
@@ -271,8 +522,7 @@
 
 void I_InitGraphics(void)
 {
-	/* Change when we support more modes than 8bpp */
-	int bytes_per_pixel = 1;
+	ggi_mode mode;
 
         fprintf (stderr,"I_InitGraphics: Init GGI-visual.\n");
 
@@ -283,51 +533,81 @@
      	ggiSetFlags(ggivis, GGIFLAG_ASYNC);
 	ggiSetEventMask(ggivis, emKey | emPointer);
 
-	/* The signal stuff is NOT neccesary for LibGGI - at all, it is
-	   just so that doom can save it's config file */
-	signal(SIGINT,  (void (*)(int)) I_Quit);
-	signal(SIGTERM, (void (*)(int)) I_Quit);
-	signal(SIGHUP,  (void (*)(int)) I_Quit);
-	signal(SIGQUIT, (void (*)(int)) I_Quit);
-
         modexrefresh = M_CheckParm("-modex") > 0;
 	db = M_CheckParm("-doublebuffer") > 0;
-	width = screenwidth;
-	height = screenheight;
+	scale = M_CheckParm("-scale") > 0;
 
-	if (!db || ggiSetSimpleMode(ggivis, width, height, 2, GT_8BIT) < 0) {
-		if (ggiSetSimpleMode(ggivis, width, height, GGI_AUTO,
-				     GT_8BIT) < 0) {
-			I_Error("Can't set %ix%ix8bpp mode\n",
-				width, height, db ? 2 : 1);
+	realwidth = screenwidth;
+	realheight = screenheight;
+	if (scale) {
+		realwidth *= 2;
+		realheight *= 2;
+	}
+
+	if (!db || ggiSetSimpleMode(ggivis, realwidth, realheight,
+				    2, GT_8BIT) < 0) {
+		if (ggiSetSimpleMode(ggivis, realwidth, realheight, GGI_AUTO,
+				     GT_8BIT) < 0 &&
+		    ggiSetSimpleMode(ggivis, realwidth, realheight, GGI_AUTO,
+				     GT_AUTO) < 0 ) {
+			I_Error("Can't set %ix%i mode\n", 
+				realwidth, realheight);
+		}
+	}
+	
+	ggiGetMode(ggivis, &mode);
+	pixelsize = (GT_SIZE(mode.graphtype)+7) / 8;
+	if (mode.graphtype != GT_8BIT) {
+		if ((palette = malloc(pixelsize*256)) == NULL) {
+			I_Error("Unable to allocate memory?!\n");
 		}
 	}
+
 	
-	usedbuf = 0;
+	usedbuf = havedbuf = 0;
+	stride = realwidth*pixelsize;
 	if ((dbuf1 = ggiDBGetBuffer(ggivis, 0)) != NULL &&
 	    (dbuf1->type & GGI_DB_SIMPLE_PLB) &&
-	    dbuf1->buffer.plb.stride*bytes_per_pixel == width &&
 	    (db ? ((dbuf2 = ggiDBGetBuffer(ggivis, 1)) != NULL &&
-		   (dbuf2->type & GGI_DB_SIMPLE_PLB) &&
-		   dbuf2->buffer.plb.stride*bytes_per_pixel == width)
-	     : 1))  
-		{
-			if ((frameptr = malloc(bytes_per_pixel*width*height))
-			    == NULL) {
+		   (dbuf2->type & GGI_DB_SIMPLE_PLB)) : 1)) {
+		havedbuf = 1;
+		frameptr[0] = dbuf1->write;
+		if (db) {
+			frameptr[1] = dbuf2->write;
+		}
+		else {
+			frameptr[1] = frameptr[0];
+		}
+		stride = dbuf1->buffer.plb.stride;
+		if (!scale && !palette && stride == pixelsize*realwidth){
+			usedbuf = 1;
+			screen = frameptr[0];
+			fprintf(stderr, "Using DirectBuffer with");
+			if (db)	{
+				fprintf(stderr, " doublebuffering\n");
+			} else {
+				fprintf(stderr, " singlebuffering\n");
+			}
+		}
+	}
+	if (!usedbuf) {
+		if ((screen = malloc(screenwidth*screenheight)) == NULL) {
+			I_Error("Unable to allocate memory?!\n");
+		}
+		if (!havedbuf && (scale || palette)) {
+			int linesize = pixelsize*realwidth;
+			if (scale) linesize *= 4;
+			if ((oneline = malloc(linesize)) == NULL) {
 				I_Error("Unable to allocate memory?!\n");
 			}
-			/* No need for two buffers here */
-			frameptr = frameptr;
-			fprintf(stderr, "Drawing into offscreen memory\n");
 		}
+		fprintf(stderr, "Drawing into offscreen memory\n");
+	}
 	/* We will start drawing to frame 0, and start displaying frame 1 */
 	if (db)	{
 		ggiSetWriteFrame(ggivis, 0);
 		ggiSetDisplayFrame(ggivis, 1);
 	}
-	
-	screen = frameptr;
+
 	curframe = 0;
 }
-
-
diff -ur linux-heretic-0.9.1.orig/i_vga.c linux-heretic-0.9.1/i_vga.c
--- linux-heretic-0.9.1.orig/i_vga.c	Thu Jan 21 00:13:32 1999
+++ linux-heretic-0.9.1/i_vga.c	Thu Jan 21 03:55:15 1999
@@ -114,6 +114,18 @@
 static int keyxlat(int sym)
 {
 	switch (sym) {
+		case SCANCODE_REMOVE:
+			return KEY_DELETE;
+		case SCANCODE_INSERT:
+			return KEY_INSERT;
+		case SCANCODE_PAGEUP:
+			return KEY_PAGEUP;
+		case SCANCODE_PAGEDOWN:
+			return KEY_PAGEDOWN;
+		case SCANCODE_HOME:
+			return KEY_HOME;
+		case SCANCODE_END:
+			return KEY_END;
 		case SCANCODE_ESCAPE:
 			return KEY_ESCAPE;
 		case SCANCODE_1:
@@ -141,7 +153,7 @@
 		case SCANCODE_EQUAL:
 			return '=';
 		case SCANCODE_BACKSPACE:
-			return 127;
+			return KEY_BACKSPACE;
 		case SCANCODE_TAB:
 			return KEY_TAB;
 		case SCANCODE_Q:
diff -ur linux-heretic-0.9.1.orig/i_x11.c linux-heretic-0.9.1/i_x11.c
--- linux-heretic-0.9.1.orig/i_x11.c	Wed Jan 20 20:42:10 1999
+++ linux-heretic-0.9.1/i_x11.c	Thu Jan 21 03:51:00 1999
@@ -28,6 +28,19 @@
 
 #include "doomdef.h"
 
+#define SHOW_FPS
+
+#ifdef SHOW_FPS
+static struct timeval	starttime;
+static long		totalframes;
+static int		showfps = 0;
+
+static void reset_framecounter(void)
+{
+	totalframes = 0;
+	gettimeofday(&starttime, NULL);
+}
+#endif
 
 
 #define POINTER_WARP_COUNTDOWN	1
@@ -120,6 +133,12 @@
     
     switch(rc = XKeycodeToKeysym(X_display, X_event.xkey.keycode, 0))
       {
+      case XK_Delete:	rc = KEY_DELETE;	break;
+      case XK_Insert:	rc = KEY_INSERT;	break;
+      case XK_Page_Up:	rc = KEY_PAGEUP;	break;
+      case XK_Page_Down:rc = KEY_PAGEDOWN;	break;
+      case XK_Home:	rc = KEY_HOME;		break;
+      case XK_End:	rc = KEY_END;		break;
       case XK_Left:	rc = KEY_LEFTARROW;	break;
       case XK_Right:	rc = KEY_RIGHTARROW;	break;
       case XK_Down:	rc = KEY_DOWNARROW;	break;
@@ -140,9 +159,7 @@
       case XK_F11:	rc = KEY_F11;		break;
       case XK_F12:	rc = KEY_F12;		break;
 
-      case XK_BackSpace:
-      case XK_Delete:	rc = KEY_BACKSPACE;	break;
-
+      case XK_BackSpace:rc = KEY_BACKSPACE;	break;
       case XK_Pause:	rc = KEY_PAUSE;		break;
 
       case XK_KP_Add:
@@ -234,6 +251,14 @@
     case KeyPress:
       event.type = ev_keydown;
       event.data1 = xlatekey();
+#ifdef SHOW_FPS
+      if (event.data1 == KEY_BACKSPACE &&
+	  gamestate == GS_LEVEL) {
+	      /* Toggle and reset the FPS counter */
+	      showfps = !showfps;
+	      reset_framecounter();
+      }
+#endif
       D_PostEvent(&event);
       /* fprintf(stderr, "k"); */
       break;
@@ -585,6 +610,24 @@
     /* sync up with server */
     XSync(X_display, False);
   }
+#ifdef SHOW_FPS
+  if (showfps) {
+	  struct timeval curtime;
+	  double diff;
+	  char str[64];
+	  
+	  totalframes++;
+	  gettimeofday(&curtime, NULL);
+	  diff = (curtime.tv_sec - starttime.tv_sec);
+	  diff += ((double)curtime.tv_usec - starttime.tv_usec)/1000000;
+	  if (diff != 0) {
+		  sprintf(str, "FPS: %.1f", totalframes/diff);
+		  XDrawString(X_display, X_mainWindow, X_gc, 0, 16, str,
+			      strlen(str));
+	  }
+  }
+#endif
+
 }
 
 
diff -ur linux-heretic-0.9.1.orig/m_misc.c linux-heretic-0.9.1/m_misc.c
--- linux-heretic-0.9.1.orig/m_misc.c	Thu Jan 21 00:13:32 1999
+++ linux-heretic-0.9.1/m_misc.c	Thu Jan 21 03:32:32 1999
@@ -429,20 +429,20 @@
   { "key_strafeleft", &key_strafeleft, ',' },
   { "key_straferight", &key_straferight, '.' },
 
-  { "key_fire", &key_fire, ' ', 1 },
-  { "key_use", &key_use, 'x', 1 },
-  { "key_strafe", &key_strafe, 'c', 1 },
-  { "key_speed", &key_speed, 'y', 1 },
+  { "key_fire", &key_fire, KEY_RCTRL, 1 },
+  { "key_use", &key_use, ' ', 1 },
+  { "key_strafe", &key_strafe, KEY_RALT, 1 },
+  { "key_speed", &key_speed, KEY_RSHIFT, 1 },
   
-  { "key_flyup", &key_flyup, 'j' },
-  { "key_flydown", &key_flydown, 'g' },
-  { "key_flycenter", &key_flycenter, 'h' },
-  { "key_lookup", &key_lookup, 'm' },
-  { "key_lookdown", &key_lookdown, 'b' },
-  { "key_lookcenter", &key_lookcenter, 'n' },
+  { "key_flyup", &key_flyup, KEY_PAGEUP },
+  { "key_flydown", &key_flydown, KEY_INSERT },
+  { "key_flycenter", &key_flycenter, KEY_HOME },
+  { "key_lookup", &key_lookup, KEY_PAGEDOWN },
+  { "key_lookdown", &key_lookdown, KEY_DELETE },
+  { "key_lookcenter", &key_lookcenter, KEY_END },
   { "key_invleft", &key_invleft, 'k' },
   { "key_invright", &key_invright, 'l' },
-  { "key_useartifact", &key_useartifact, 13 },
+  { "key_useartifact", &key_useartifact, KEY_ENTER },
 
 #ifdef SNDSERV
   {"sndserver", (int *) &sndserver_filename, (long) "sndserver"},
