diff -rup quakeforge-0.5.2-orig/include/QF/GL/qf_funcs_list.h quakeforge-0.5.2/include/QF/GL/qf_funcs_list.h
--- quakeforge-0.5.2-orig/include/QF/GL/qf_funcs_list.h	2002-03-12 01:55:49.000000000 +0200
+++ quakeforge-0.5.2/include/QF/GL/qf_funcs_list.h	2002-12-28 17:28:32.000000000 +0200
@@ -46,7 +46,7 @@ QFGL_DONT_NEED (void, glBitmap, (GLsizei
 QFGL_DONT_NEED (void, glBlendColor, (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha))
 QFGL_DONT_NEED (void, glBlendEquation, (GLenum mode))
 QFGL_NEED (void, glBlendFunc, (GLenum sfactor, GLenum dfactor))
-QFGL_DONT_NEED (void, glCallList, (GLuint list))
+QFGL_NEED (void, glCallList, (GLuint list))
 QFGL_DONT_NEED (void, glCallLists, (GLsizei n, GLenum type, const GLvoid * lists))
 QFGL_NEED (void, glClear, (GLbitfield mask))
 QFGL_NEED (void, glClearAccum, (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha))
@@ -108,10 +108,10 @@ QFGL_DONT_NEED (void, glCopyPixels, (GLi
 QFGL_DONT_NEED (void, glCopyTexImage1D, (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border))
 QFGL_DONT_NEED (void, glCopyTexImage2D, (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border))
 QFGL_DONT_NEED (void, glCopyTexSubImage1D, (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width))
-QFGL_DONT_NEED (void, glCopyTexSubImage2D, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height))
+QFGL_NEED (void, glCopyTexSubImage2D, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height))
 QFGL_DONT_NEED (void, glCopyTexSubImage3D, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height))
 QFGL_NEED (void, glCullFace, (GLenum mode))
-QFGL_DONT_NEED (void, glDeleteLists, (GLuint list, GLsizei range))
+QFGL_NEED (void, glDeleteLists, (GLuint list, GLsizei range))
 QFGL_NEED (void, glDeleteTextures, (GLsizei n, const GLuint * textures))
 QFGL_NEED (void, glDepthFunc, (GLenum func))
 QFGL_NEED (void, glDepthMask, (GLboolean flag))
@@ -151,8 +151,8 @@ QFGL_DONT_NEED (void, glFogi, (GLenum pn
 QFGL_DONT_NEED (void, glFogiv, (GLenum pname, const GLint * params))
 QFGL_DONT_NEED (void, glFrontFace, (GLenum mode))
 QFGL_NEED (void, glFrustum, (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val))
-QFGL_DONT_NEED (GLuint, glGenLists, (GLsizei range))
-QFGL_DONT_NEED (void, glGenTextures, (GLsizei n, GLuint * textures))
+QFGL_NEED (GLuint, glGenLists, (GLsizei range))
+QFGL_NEED (void, glGenTextures, (GLsizei n, GLuint * textures))
 QFGL_DONT_NEED (void, glGetBooleanv, (GLenum pname, GLboolean * params))
 QFGL_DONT_NEED (void, glGetClipPlane, (GLenum plane, GLdouble * equation))
 QFGL_DONT_NEED (void, glGetColorTable, (GLenum target, GLenum format, GLenum type, GLvoid * table))
@@ -162,7 +162,7 @@ QFGL_DONT_NEED (void, glGetConvolutionFi
 QFGL_DONT_NEED (void, glGetConvolutionParameterfv, (GLenum target, GLenum pname, GLfloat * params))
 QFGL_DONT_NEED (void, glGetConvolutionParameteriv, (GLenum target, GLenum pname, GLint * params))
 QFGL_DONT_NEED (void, glGetDoublev, (GLenum pname, GLdouble * params))
-QFGL_DONT_NEED (GLenum, glGetError, (void))
+QFGL_NEED (GLenum, glGetError, (void))
 QFGL_NEED (void, glGetFloatv, (GLenum pname, GLfloat * params))
 QFGL_DONT_NEED (void, glGetHistogram, (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid * values))
 QFGL_DONT_NEED (void, glGetHistogramParameterfv, (GLenum target, GLenum pname, GLfloat * params))
@@ -246,7 +246,7 @@ QFGL_NEED (void, glMatrixMode, (GLenum m
 QFGL_DONT_NEED (void, glMinmax, (GLenum target, GLenum internalformat, GLboolean sink))
 QFGL_DONT_NEED (void, glMultMatrixd, (const GLdouble * m))
 QFGL_DONT_NEED (void, glMultMatrixf, (const GLfloat * m))
-QFGL_DONT_NEED (void, glNewList, (GLuint list, GLenum mode))
+QFGL_NEED (void, glNewList, (GLuint list, GLenum mode))
 QFGL_DONT_NEED (void, glNormal3b, (GLbyte nx, GLbyte ny, GLbyte nz))
 QFGL_DONT_NEED (void, glNormal3bv, (const GLbyte * v))
 QFGL_DONT_NEED (void, glNormal3d, (GLdouble nx, GLdouble ny, GLdouble nz))
@@ -347,7 +347,7 @@ QFGL_DONT_NEED (void, glTexCoord2s, (GLs
 QFGL_DONT_NEED (void, glTexCoord2sv, (const GLshort * v))
 QFGL_DONT_NEED (void, glTexCoord3d, (GLdouble s, GLdouble t, GLdouble r))
 QFGL_DONT_NEED (void, glTexCoord3dv, (const GLdouble * v))
-QFGL_DONT_NEED (void, glTexCoord3f, (GLfloat s, GLfloat t, GLfloat r))
+QFGL_NEED (void, glTexCoord3f, (GLfloat s, GLfloat t, GLfloat r))
 QFGL_DONT_NEED (void, glTexCoord3fv, (const GLfloat * v))
 QFGL_DONT_NEED (void, glTexCoord3i, (GLint s, GLint t, GLint r))
 QFGL_DONT_NEED (void, glTexCoord3iv, (const GLint * v))
@@ -370,14 +370,14 @@ QFGL_DONT_NEED (void, glTexGend, (GLenum
 QFGL_DONT_NEED (void, glTexGendv, (GLenum coord, GLenum pname, const GLdouble * params))
 QFGL_DONT_NEED (void, glTexGenf, (GLenum coord, GLenum pname, GLfloat param))
 QFGL_DONT_NEED (void, glTexGenfv, (GLenum coord, GLenum pname, const GLfloat * params))
-QFGL_DONT_NEED (void, glTexGeni, (GLenum coord, GLenum pname, GLint param))
+QFGL_NEED (void, glTexGeni, (GLenum coord, GLenum pname, GLint param))
 QFGL_DONT_NEED (void, glTexGeniv, (GLenum coord, GLenum pname, const GLint * params))
 QFGL_DONT_NEED (void, glTexImage1D, (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid * pixels))
 QFGL_NEED (void, glTexImage2D, (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid * pixels))
 QFGL_DONT_NEED (void, glTexImage3D, (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid * pixels))
 QFGL_NEED (void, glTexParameterf, (GLenum target, GLenum pname, GLfloat param))
 QFGL_NEED (void, glTexParameterfv, (GLenum target, GLenum pname, const GLfloat * params))
-QFGL_DONT_NEED (void, glTexParameteri, (GLenum target, GLenum pname, GLint param))
+QFGL_NEED (void, glTexParameteri, (GLenum target, GLenum pname, GLint param))
 QFGL_DONT_NEED (void, glTexParameteriv, (GLenum target, GLenum pname, const GLint * params))
 QFGL_DONT_NEED (void, glTexSubImage1D, (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid * pixels))
 QFGL_NEED (void, glTexSubImage2D, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * pixels))
@@ -388,7 +388,7 @@ QFGL_DONT_NEED (void, glVertex2d, (GLdou
 QFGL_DONT_NEED (void, glVertex2dv, (const GLdouble * v))
 QFGL_NEED (void, glVertex2f, (GLfloat x, GLfloat y))
 QFGL_NEED (void, glVertex2fv, (const GLfloat * v))
-QFGL_DONT_NEED (void, glVertex2i, (GLint x, GLint y))
+QFGL_NEED (void, glVertex2i, (GLint x, GLint y))
 QFGL_DONT_NEED (void, glVertex2iv, (const GLint * v))
 QFGL_DONT_NEED (void, glVertex2s, (GLshort x, GLshort y))
 QFGL_DONT_NEED (void, glVertex2sv, (const GLshort * v))
diff -rup quakeforge-0.5.2-orig/include/r_cvar.h quakeforge-0.5.2/include/r_cvar.h
--- quakeforge-0.5.2-orig/include/r_cvar.h	2002-08-24 00:55:59.000000000 +0300
+++ quakeforge-0.5.2/include/r_cvar.h	2002-12-25 19:39:29.000000000 +0200
@@ -90,6 +90,9 @@ extern struct cvar_s     *scr_centertime
 extern struct cvar_s     *scr_consize;
 extern struct cvar_s     *scr_conspeed;
 extern struct cvar_s     *scr_fov;
+extern struct cvar_s     *scr_fisheye;
+extern struct cvar_s     *scr_fviews;
+extern struct cvar_s     *scr_ffov;
 extern struct cvar_s     *scr_printspeed;
 extern struct cvar_s     *scr_showpause;
 extern struct cvar_s     *scr_showram;
diff -rup quakeforge-0.5.2-orig/libs/video/renderer/gl/gl_rmain.c quakeforge-0.5.2/libs/video/renderer/gl/gl_rmain.c
--- quakeforge-0.5.2-orig/libs/video/renderer/gl/gl_rmain.c	2002-08-20 03:48:59.000000000 +0300
+++ quakeforge-0.5.2/libs/video/renderer/gl/gl_rmain.c	2002-12-28 18:31:31.000000000 +0200
@@ -24,7 +24,7 @@
 		Boston, MA  02111-1307, USA
 
 */
-static const char rcsid[] = 
+static const char rcsid[] =
 	"$Id: gl_rmain.c,v 1.53 2002/08/20 00:48:59 despair Exp $";
 
 #ifdef HAVE_CONFIG_H
@@ -64,6 +64,8 @@ static const char rcsid[] = 
 #include "r_local.h"
 #include "view.h"
 
+#include "GL/gl.h"
+
 entity_t    r_worldentity;
 
 qboolean    r_cache_thrash;				// compatability
@@ -308,17 +310,16 @@ MYgluPerspective (GLdouble fovy, GLdoubl
 	xmin = ymin * aspect;
 	xmax = -xmin;
 
+	//printf ("glFrustum (%f, %f, %f, %f)\n", xmin, xmax, ymin, ymax);
 	qfglFrustum (xmin, xmax, ymin, ymax, zNear, zFar);
 }
 
 static void
-R_SetupGL (void)
+R_SetupGL_Viewport_and_Perspective (void)
 {
 	float		screenaspect;
 	int			x, x2, y2, y, w, h;
 
-	R_SetFrustum ();
-
 	// set up viewpoint
 	qfglMatrixMode (GL_PROJECTION);
 	qfglLoadIdentity ();
@@ -346,11 +347,19 @@ R_SetupGL (void)
 		w = x2 - x;
 		h = y - y2;
 	}
-
+	//printf("glViewport(%d, %d, %d, %d)\n", glx + x, gly + y2, w, h);
 	qfglViewport (glx + x, gly + y2, w, h);
 	screenaspect = (float) r_refdef.vrect.width / r_refdef.vrect.height;
 	MYgluPerspective (r_refdef.fov_y, screenaspect, r_nearclip->value,
 					  r_farclip->value);
+}
+
+static void
+R_SetupGL (void)
+{
+	R_SetFrustum ();
+
+	R_SetupGL_Viewport_and_Perspective ();
 
 	if (mirror) {
 		if (mirror_plane->normal[2])
@@ -484,12 +493,12 @@ R_Mirror (void)
 }
 
 /*
-	R_RenderView
+	R_RenderView_
 
 	r_refdef must be set before the first call
 */
 void
-R_RenderView (void)
+R_RenderView_ (void)
 {
 	if (r_norefresh->int_val)
 		return;
@@ -514,3 +523,297 @@ R_RenderView (void)
 	if (r_zgraph->int_val)
 		R_ZGraph ();
 }
+
+// Algorithm:
+// Draw up to six views, one in each direction.
+// Save the picture to cube map texture, use GL_ARB_texture_cube_map.
+// Create FPOLYCNTxFPOLYCNT polygons sized flat grid.
+// Baseing on field of view, tie cube map texture to grid using
+// translation function to map texture coordinates to fixed/regular
+// grid vertices coordinates.
+// Render view. Fisheye is done.
+
+static void R_RenderViewFishEye (void);
+
+void
+R_RenderView (void)
+{
+	if(!scr_fisheye->int_val)
+		R_RenderView_ ();
+	else
+		R_RenderViewFishEye ();
+}
+
+#define BOX_FRONT  0
+#define BOX_RIGHT  1
+#define BOX_BEHIND 2
+#define BOX_LEFT   3
+#define BOX_TOP    4
+#define BOX_BOTTOM 5
+
+#define FPOLYCNT   16
+
+struct xyz {
+	float x, y, z;
+};
+
+static struct xyz FisheyeLookupTbl[FPOLYCNT+1][FPOLYCNT+1];
+static GLuint cube_map_tex;
+static GLint gl_cube_map_size;
+static GLint gl_cube_map_step;
+
+static const GLenum box2cube_map[] = {
+	GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
+	GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
+	GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
+	GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
+	GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
+	GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
+};
+
+static void
+R_BuildFisheyeLookup (int width, int height, float fov)
+{
+	int x, y;
+	struct xyz *v;
+
+	for (y = 0; y <= height; y += gl_cube_map_step) {
+		for (x = 0; x <= width; x += gl_cube_map_step) {
+			float dx = x - width/2;
+			float dy = y - height/2;
+			float yaw = sqrt(dx*dx+dy*dy)*fov/width;
+			float roll = atan2(dy, dx);
+			// X is a first index and Y is a second, because later
+			// when we draw QUAD_STRIPes we need next Y vertix coordinate.
+			v = &FisheyeLookupTbl[x/gl_cube_map_step][y/gl_cube_map_step];
+			v->x = sin(yaw) * cos(roll);
+			v->y = -sin(yaw) * sin(roll);
+			v->z = cos(yaw);
+		}
+	}
+}
+
+#define CHKGLERR(s) \
+do { \
+	GLint err = qfglGetError(); \
+	if (err != GL_NO_ERROR) printf ("%s: gl error %d\n", s, (int)err); \
+} while (0);
+
+#define NO(x) \
+do { \
+	if (x < 0) x += 360; \
+	else if (x >= 360) x -= 360; \
+} while (0)
+
+static void
+R_RenderCubeSide (int side)
+{
+	float pitch, n_pitch;
+	float yaw, n_yaw;
+	float roll, n_roll;
+	float s_roll;
+
+	pitch = n_pitch = r_refdef.viewangles[PITCH];
+	yaw  = n_yaw = r_refdef.viewangles[YAW];
+	// setting ROLL for now to 0, correct roll handling
+	// requre more exhaustive changes in rotation
+	// TODO: implement via matrix
+	//roll  = n_roll = r_refdef.viewangles[ROLL];
+	s_roll = r_refdef.viewangles[ROLL];
+	roll = n_roll = 0;
+	//roll -= scr_fviews->int_val*10;
+	//n_roll = roll;
+
+	switch (side) {
+	case BOX_FRONT: break;
+	case BOX_RIGHT:
+		n_pitch = roll;
+		n_yaw -= 90;
+		n_roll = -pitch;
+		break;
+	case BOX_LEFT:
+		n_pitch = -roll;
+		n_yaw += 90;
+		n_roll = pitch;
+		//static int f = 0;
+		//if (!(f++%100)) printf("%4d %4d %4d | %4d %4d %4d\n",
+		//(int)pitch, (int)yaw, (int)roll,
+		//(int)n_pitch, (int)n_yaw, (int)n_roll);
+		break;
+	case BOX_TOP:
+		n_pitch -= 90;
+		break;
+	case BOX_BOTTOM:
+		n_pitch += 90;
+		break;
+	case BOX_BEHIND:
+		n_pitch = -pitch;
+		n_yaw += 180;
+		break;
+	}
+	NO(n_pitch); NO(n_yaw); NO(n_roll);
+	r_refdef.viewangles[PITCH] = n_pitch;
+	r_refdef.viewangles[YAW] = n_yaw;
+	r_refdef.viewangles[ROLL] = n_roll;
+
+	R_RenderView_ ();
+	qfglEnable(GL_TEXTURE_CUBE_MAP_ARB);
+	qfglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, cube_map_tex);
+	qfglCopyTexSubImage2D (box2cube_map[side], 0, 0, 0, 0, 0,
+		gl_cube_map_size, gl_cube_map_size);
+	//CHKGLERR ("qfglCopyTexSubImage2D");
+	qfglDisable(GL_TEXTURE_CUBE_MAP_ARB);
+
+	r_refdef.viewangles[PITCH] = pitch;
+	r_refdef.viewangles[YAW] = yaw;
+	r_refdef.viewangles[ROLL] = s_roll;
+}
+
+static qboolean gl_cube_map_capable = false;
+static GLint gl_cube_map_maxtex;
+static GLuint fisheye_grid;
+
+static int
+R_InitFishEyeOnce (void)
+{
+	static qboolean fisheye_init_once_completed = false;
+
+	if (fisheye_init_once_completed) return 1;
+	Con_Printf ("GL_ARB_texture_cube_map ");
+	if (QFGL_ExtensionPresent ("GL_ARB_texture_cube_map")) {
+		qfglGetIntegerv (GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, &gl_cube_map_maxtex);
+		Con_Printf ("present, max texture size %d.\n", (int)gl_cube_map_maxtex);
+		gl_cube_map_capable = true;
+	} else {
+		Con_Printf ("not found.\n");
+	}
+	fisheye_init_once_completed = true;
+	return 1;
+}
+
+static int
+R_InitFishEye (void)
+{
+	int width = vid.width;
+	int height = vid.height;
+	int fov = scr_ffov->int_val;
+	int views = scr_fviews->int_val;
+
+	static int pwidth = -1;
+	static int pheight = -1;
+	static int pfov = -1;
+	static int pviews = -1;
+
+	int i, x, y, min_wh, wh_changed = 0;
+
+	if (!R_InitFishEyeOnce()) return 0;
+	if (!gl_cube_map_capable) return 0;
+
+	// There is a problem when max texture size is bigger than
+	// min(width, height), it shows up as black fat stripes at the edges
+	// of box polygons, probably due to missing texture fragment. Try
+	// to play in 640x480 with gl_cube_map_size == 512.
+	if (pwidth != width || pheight != height) {
+		wh_changed = 1;
+		min_wh = (height < width) ? height : width;
+		gl_cube_map_size = gl_cube_map_maxtex;
+		while (gl_cube_map_size > min_wh)
+			gl_cube_map_size /= 2;
+		gl_cube_map_step = gl_cube_map_size/FPOLYCNT;
+	}
+	if (pviews != views) {
+		qfglEnable (GL_TEXTURE_CUBE_MAP_ARB);
+		if (pviews != -1)
+			qfglDeleteTextures (1, &cube_map_tex);
+		pviews = views;
+		qfglGenTextures (1, &cube_map_tex);
+		qfglBindTexture (GL_TEXTURE_CUBE_MAP_ARB, cube_map_tex);
+		for (i = 0; i < 6; ++i) {
+			qfglTexImage2D (box2cube_map[i], 0, 3, gl_cube_map_size, gl_cube_map_size,
+				0, GL_RGB, GL_UNSIGNED_SHORT, NULL);
+		}
+		qfglTexParameteri (GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+		qfglTexParameteri (GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+		qfglDisable (GL_TEXTURE_CUBE_MAP_ARB);
+	}
+	if (wh_changed || pfov != fov) {
+		if (pfov != -1)
+			qfglDeleteLists (fisheye_grid, 1);
+		pwidth = width;
+		pheight = height;
+		pfov = fov;
+
+		R_BuildFisheyeLookup (gl_cube_map_size, gl_cube_map_size, ((float)fov)*M_PI/180.0);
+
+		fisheye_grid = qfglGenLists (1);
+		qfglNewList (fisheye_grid, GL_COMPILE);
+		qfglLoadIdentity ();
+		qfglTranslatef (-gl_cube_map_size/2, -gl_cube_map_size/2, -gl_cube_map_size/2);
+
+		qfglDisable (GL_DEPTH_TEST);
+		qfglCullFace (GL_BACK);
+		qfglClear (GL_COLOR_BUFFER_BIT);
+
+		qfglEnable(GL_TEXTURE_CUBE_MAP_ARB);
+		qfglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, cube_map_tex);
+		qfglBegin(GL_QUAD_STRIP);
+
+		for (y = 0; y < gl_cube_map_size; y += gl_cube_map_step) {
+			for (x = 0; x <= gl_cube_map_size; x += gl_cube_map_step) { // quad_strip, X should be inclusive
+				struct xyz *v = &FisheyeLookupTbl[x/gl_cube_map_step][y/gl_cube_map_step+1];
+				qfglTexCoord3f (v->x, v->y, v->z); qfglVertex2i (x, y+gl_cube_map_step);
+				--v;
+				qfglTexCoord3f (v->x, v->y, v->z); qfglVertex2i (x, y);
+			}
+		}
+		qfglEnd ();
+		qfglDisable (GL_TEXTURE_CUBE_MAP_ARB);
+		qfglEnable (GL_DEPTH_TEST);
+		qfglEndList ();
+	}
+	return 1;
+}
+
+static void
+R_RenderViewFishEye (void)
+{
+	float s_fov_x, s_fov_y;
+	int s_vid_w, s_vid_h, s_rect_w, s_rect_h, s_gl_w, s_gl_h;
+
+	if (!R_InitFishEye()) return;
+
+	// save values
+	s_fov_x = r_refdef.fov_x;
+	s_fov_y = r_refdef.fov_y;
+	s_vid_w = vid.width;
+	s_vid_h = vid.height;
+	s_rect_w = r_refdef.vrect.width;
+	s_rect_h = r_refdef.vrect.height;
+	s_gl_w = glwidth;
+	s_gl_h = glheight;
+	// the view should be square
+	r_refdef.fov_x = r_refdef.fov_y = 90;
+	vid.width = vid.height =
+		r_refdef.vrect.height = r_refdef.vrect.width =
+		glwidth = glheight = gl_cube_map_size;
+	switch (scr_fviews->int_val) {
+		case 6:   R_RenderCubeSide (BOX_BEHIND);
+		case 5:   R_RenderCubeSide (BOX_BOTTOM);
+		case 4:   R_RenderCubeSide (BOX_TOP);
+		case 3:   R_RenderCubeSide (BOX_LEFT);
+		case 2:   R_RenderCubeSide (BOX_RIGHT);
+		default:  R_RenderCubeSide (BOX_FRONT);
+	}
+	// restore
+	r_refdef.fov_x = s_fov_x;
+	r_refdef.fov_y = s_fov_y;
+	vid.width = s_vid_w;
+	vid.height = s_vid_h;
+	r_refdef.vrect.width = s_rect_w;
+	r_refdef.vrect.height = s_rect_h;
+	glwidth = s_gl_w;
+	glheight = s_gl_h;
+	R_SetupGL_Viewport_and_Perspective ();
+	qfglMatrixMode (GL_MODELVIEW);
+	qfglCallList (fisheye_grid);
+}
diff -rup quakeforge-0.5.2-orig/libs/video/renderer/r_cvar.c quakeforge-0.5.2/libs/video/renderer/r_cvar.c
--- quakeforge-0.5.2-orig/libs/video/renderer/r_cvar.c	2002-08-24 00:55:59.000000000 +0300
+++ quakeforge-0.5.2/libs/video/renderer/r_cvar.c	2002-12-28 16:26:21.000000000 +0200
@@ -130,6 +130,9 @@ cvar_t     *scr_centertime;
 cvar_t     *scr_consize;
 cvar_t     *scr_conspeed;
 cvar_t     *scr_fov;
+cvar_t     *scr_fisheye;
+cvar_t     *scr_fviews;
+cvar_t     *scr_ffov;
 cvar_t     *scr_printspeed;
 cvar_t     *scr_showpause;
 cvar_t     *scr_showram;
@@ -192,6 +195,28 @@ r_particles_nearclip_f (cvar_t *var)
 												r_farclip->value));
 }

+static void
+scr_fisheye_f (cvar_t *var)
+{
+	/* Regular fov is constrained in R_RenderViewFishEye()
+	if (var->int_val)
+		Cvar_Set (scr_fov, "90");
+	*/
+}
+
+static void
+scr_ffov_f (cvar_t *var)
+{
+	if (var->int_val < 1)
+		Cvar_Set (scr_ffov, "1");
+	if (var->int_val < 130)
+		Cvar_Set (scr_fviews, "3");
+	else if (var->int_val < 220)
+		Cvar_Set (scr_fviews, "5");
+	else
+		Cvar_Set (scr_fviews, "6");
+}
+
 void
 R_Init_Cvars (void)
 {
@@ -354,7 +379,7 @@ R_Init_Cvars (void)
 							"Toggles drawing of particles.");
 	r_particles_max = Cvar_Get ("r_particles_max", "2048", CVAR_ARCHIVE,
 								r_particles_max_f, "Maximum amount of "
-								"particles to display. No maximum, minimum " 
+								"particles to display. No maximum, minimum "
 								"is 0.");
 	r_particles_nearclip = Cvar_Get ("r_particles_nearclip", "32",
 									 CVAR_ARCHIVE, r_particles_nearclip_f,
@@ -395,7 +420,14 @@ R_Init_Cvars (void)
 	scr_conspeed = Cvar_Get ("scr_conspeed", "300", CVAR_NONE, NULL,
 							 "How quickly the console scrolls up or down");
 	scr_fov = Cvar_Get ("fov", "90", CVAR_NONE, NULL, "Your field of view in "
-						"degrees. Smaller than 90 zooms in.");
+						"degrees. Smaller than 90 zooms in. Don't touch in "
+						"fisheye mode, use ffov instead.");
+	scr_fisheye = Cvar_Get ("fisheye", "0", CVAR_NONE, scr_fisheye_f,
+							"Toggles fisheye mode.");
+	scr_fviews = Cvar_Get ("fviews", "6", CVAR_NONE, NULL, "The number of "
+						   "fisheye views.");
+	scr_ffov = Cvar_Get ("ffov", "180", CVAR_NONE, scr_ffov_f, "Your field of "
+						 "view in degrees in fisheye mode.");
 	scr_printspeed = Cvar_Get ("scr_printspeed", "8", CVAR_NONE, NULL,
 							   "How fast the text is displayed at the end of "
 							   "the single player episodes");
