commit c475488bbe8594062c991286d9720eaffd29c8fd
Author: Oliver McFadden <oliver.mcfadden@nokia.com>
Date:   Thu May 28 18:21:57 2009 +0300

    Nokia N900: Added support for Quake 3 Arena. :-D
    
    Note, this is experimental code that started as an unofficial weekend
    project. It's full of hacks, quick work arounds, and other nastyness.
    
    It is not my fault if your device catches on fire. :-)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d895505
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+build
+code/egl/qgl.h
+*.d
+debian/files
+debian/ioquake3
+debian/ioquake3.substvars
+*-stamp
diff --git a/Makefile b/Makefile
index 32f4d1a..5b648e7 100644
--- a/Makefile
+++ b/Makefile
@@ -156,6 +156,7 @@ SDIR=$(MOUNT_DIR)/server
 RDIR=$(MOUNT_DIR)/renderer
 CMDIR=$(MOUNT_DIR)/qcommon
 SDLDIR=$(MOUNT_DIR)/sdl
+EGLDIR=$(MOUNT_DIR)/egl
 ASMDIR=$(MOUNT_DIR)/asm
 SYSDIR=$(MOUNT_DIR)/sys
 GDIR=$(MOUNT_DIR)/game
@@ -199,21 +200,21 @@ endif
 # version info
 VERSION=1.36
 
-USE_SVN=
-ifeq ($(wildcard .svn),.svn)
-  SVN_REV=$(shell LANG=C svnversion .)
-  ifneq ($(SVN_REV),)
-    VERSION:=$(VERSION)_SVN$(SVN_REV)
-    USE_SVN=1
-  endif
-else
-ifeq ($(wildcard .git/svn/.metadata),.git/svn/.metadata)
-  SVN_REV=$(shell LANG=C git svn info | awk '$$1 == "Revision:" {print $$2; exit 0}')
-  ifneq ($(SVN_REV),)
-    VERSION:=$(VERSION)_SVN$(SVN_REV)
-  endif
-endif
-endif
+#USE_SVN=
+#ifeq ($(wildcard .svn),.svn)
+#  SVN_REV=$(shell LANG=C svnversion .)
+#  ifneq ($(SVN_REV),)
+#    VERSION:=$(VERSION)_SVN$(SVN_REV)
+#    USE_SVN=1
+#  endif
+#else
+#ifeq ($(wildcard .git/svn/.metadata),.git/svn/.metadata)
+#  SVN_REV=$(shell LANG=C git svn info | awk '$$1 == "Revision:" {print $$2; exit 0}')
+#  ifneq ($(SVN_REV),)
+#    VERSION:=$(VERSION)_SVN$(SVN_REV)
+#  endif
+#endif
+#endif
 
 
 #############################################################################
@@ -225,6 +226,7 @@ LIB=lib
 
 INSTALL=install
 MKDIR=mkdir
+PERL=perl
 
 ifeq ($(PLATFORM),linux)
 
@@ -292,6 +294,10 @@ ifeq ($(PLATFORM),linux)
     OPTIMIZE += -mtune=ultrasparc3 -mv8plus
     HAVE_VM_COMPILED=true
   endif
+  ifeq ($(ARCH),arm)
+    BASE_CFLAGS += -DNOKIA
+    OPTIMIZE += -mfpu=neon
+  endif
   endif
   endif
 
@@ -306,7 +312,7 @@ ifeq ($(PLATFORM),linux)
   THREAD_LIBS=-lpthread
   LIBS=-ldl -lm
 
-  CLIENT_LIBS=$(SDL_LIBS) -lGL
+  CLIENT_LIBS=$(SDL_LIBS) -lGLES_CM -lX11
 
   ifeq ($(USE_OPENAL),1)
     ifneq ($(USE_OPENAL_DLOPEN),1)
@@ -872,6 +878,11 @@ echo_cmd=@echo
 Q=@
 endif
 
+define DO_PERL
+$(echo_cmd) "PERL $@"
+$(Q)$(PERL) $< > $@
+endef
+
 define DO_CC
 $(echo_cmd) "CC $<"
 $(Q)$(CC) $(NOTSHLIBCFLAGS) $(CFLAGS) -o $@ -c $<
@@ -1375,11 +1386,7 @@ Q3OBJ = \
   $(B)/client/tr_surface.o \
   $(B)/client/tr_world.o \
   \
-  $(B)/client/sdl_gamma.o \
-  $(B)/client/sdl_input.o \
-  $(B)/client/sdl_snd.o \
-  \
-  $(B)/client/con_passive.o \
+  $(B)/client/con_tty.o \
   $(B)/client/con_log.o \
   $(B)/client/sys_main.o
 
@@ -1481,10 +1488,12 @@ ifeq ($(USE_MUMBLE),1)
 endif
 
 Q3POBJ += \
-  $(B)/client/sdl_glimp.o
+  $(B)/client/egl_glimp.o \
+  $(B)/client/egl_input.o \
+  $(B)/client/sdl_snd.o
 
 Q3POBJ_SMP += \
-  $(B)/clientsmp/sdl_glimp.o
+  $(Q3POBJ)
 
 $(B)/ioquake3.$(ARCH)$(BINEXT): $(Q3OBJ) $(Q3POBJ) $(LIBSDLMAIN)
 	$(echo_cmd) "LD $@"
@@ -1660,6 +1669,9 @@ Q3CGOBJ_ = \
   $(B)/baseq3/cgame/cg_view.o \
   $(B)/baseq3/cgame/cg_weapons.o \
   \
+  $(B)/baseq3/cgame/mod_baseq3.o \
+  $(B)/baseq3/cgame/ogc_util.o \
+  \
   $(B)/baseq3/qcommon/q_math.o \
   $(B)/baseq3/qcommon/q_shared.o
 
@@ -1934,13 +1946,13 @@ $(B)/client/%.o: $(CMDIR)/%.c
 $(B)/client/%.o: $(BLIBDIR)/%.c
 	$(DO_BOT_CC)
 
-$(B)/client/%.o: $(JPDIR)/%.c
+$(B)/client/%.o: $(JPDIR)/%.c $(EGLDIR)/qgl.h
 	$(DO_CC)
 
 $(B)/client/%.o: $(SPEEXDIR)/%.c
 	$(DO_CC)
 
-$(B)/client/%.o: $(RDIR)/%.c
+$(B)/client/%.o: $(RDIR)/%.c $(EGLDIR)/qgl.h
 	$(DO_CC)
 
 $(B)/client/%.o: $(SDLDIR)/%.c
@@ -1949,6 +1961,12 @@ $(B)/client/%.o: $(SDLDIR)/%.c
 $(B)/clientsmp/%.o: $(SDLDIR)/%.c
 	$(DO_SMP_CC)
 
+$(B)/client/%.o: $(EGLDIR)/%.c
+	$(DO_CC)
+
+$(B)/clientsmp/%.o: $(EGLDIR)/%.c
+	$(DO_SMP_CC)
+
 $(B)/client/%.o: $(SYSDIR)/%.c
 	$(DO_CC)
 
@@ -1984,6 +2002,11 @@ ifeq ($(USE_SVN),1)
   $(B)/ded/common.o : .svn/entries
 endif
 
+$(EGLDIR)/qgl.h: $(EGLDIR)/GenerateQGL.pl
+	$(DO_PERL)
+
+$(B)/client/%.o: $(EGLDIR)/%.c
+	$(DO_CC)
 
 #############################################################################
 ## GAME MODULE RULES
diff --git a/Makefile.local b/Makefile.local
new file mode 100644
index 0000000..cb33daa
--- /dev/null
+++ b/Makefile.local
@@ -0,0 +1,19 @@
+BUILD_CLIENT=1
+BUILD_CLIENT_SMP=0
+BUILD_GAME_QVM=0
+BUILD_GAME_SO=1
+BUILD_MISSIONPACK=0
+BUILD_SERVER=0
+BUILD_STANDALONE=1
+DEFAULT_BASEDIR=/home/user
+GENERATE_DEPENDENCIES=0
+USE_CODEC_VORBIS=0
+USE_CURL=0
+USE_CURL_DLOPEN=0
+USE_INTERNAL_SPEEX=0
+USE_LOCAL_HEADERS=0
+USE_MUMBLE=0
+USE_OPENAL=0
+USE_OPENAL_DLOPEN=0
+USE_SVN=0
+USE_VOIP=0
diff --git a/code/cgame/cg_ents.c b/code/cgame/cg_ents.c
index a6a5c2a..a4c3434 100644
--- a/code/cgame/cg_ents.c
+++ b/code/cgame/cg_ents.c
@@ -923,6 +923,114 @@ static void CG_TeamBase( centity_t *cent ) {
 #endif
 }
 
+int targ_sub = 100;
+float veloc_scale = 10.0f;
+
+static void Aim_Player(centity_t * cent)
+{
+	if (cent->currentState.clientNum != cg.snap->ps.clientNum) {
+		/************************ BEGIN VELOCITY EXTRAPOLATION **************************/
+#if 0
+		float scale;
+		vec3_t lerp;
+		vec3_t diff;
+		int i;
+		int nextframe;
+		int targtime;
+
+		VectorCopy(cent->lerpOrigin, cent->history[cent->hindex].origin);
+		cent->history[cent->hindex].time = trap_Milliseconds();
+		targtime = cent->history[cent->hindex].time - targ_sub;
+		i = nextframe = cent->hindex;
+		do {
+			if (targtime >= cent->history[i].time)
+				break;
+			nextframe = i;
+			i--;
+			if (i == -1)
+				i = 999;
+		} while (i != cent->hindex);
+		scale =
+		    ((float)(targtime - cent->history[i].time)) / (float)(cent->history[nextframe].time -
+									  cent->history[i].time);
+		VectorSubtract(cent->history[nextframe].origin, cent->history[i].origin, diff);
+		VectorMA(cent->history[i].origin, scale, diff, lerp);
+		VectorSubtract(cent->lerpOrigin, lerp, cent->vel);
+		VectorScale(cent->vel, veloc_scale, cent->vel);
+
+		targtime -= targ_sub;
+		do {
+			if (targtime >= cent->history[i].time)
+				break;
+			nextframe = i;
+			i--;
+			if (i == -1)
+				i = 999;
+		} while (i != cent->hindex);
+		scale =
+		    ((float)(targtime - cent->history[i].time)) / (float)(cent->history[nextframe].time -
+									  cent->history[i].time);
+		VectorSubtract(cent->history[nextframe].origin, cent->history[i].origin, diff);
+		VectorMA(cent->history[i].origin, scale, diff, diff);
+		VectorSubtract(lerp, diff, lerp);
+		VectorScale(lerp, veloc_scale, lerp);
+		VectorSubtract(cent->vel, lerp, cent->acc);
+		cent->acc[0] = cent->acc[1] = 0.0f;
+		VectorScale(cent->acc, veloc_scale, cent->acc);
+
+		cent->hindex++;
+		if (cent->hindex == 1000)
+			cent->hindex = 0;
+		/************************ END VELOCITY EXTRAPOLATION **************************/
+#endif
+		/************************ BEGIN PREDICTION/VIS **************************/
+#if 1
+		if (ogc_aim.integer) {
+			if (AddTarget_BQ3(ogc_target, cent)) {
+#if 0
+				if (!ogc_target) {
+					trap_Cvar_VariableStringBuffer("sensitivity", sensitivity, 16);
+					trap_Cvar_Set("sensitivity", "0");
+				}
+#endif
+				ogc_target = cent;
+			}
+		}
+		/************************ END PREDICTION/VIS **************************/
+#endif
+
+#if 0
+		float color[4];
+		int force, screen[2];
+		char *str;
+
+		if ((ogc_names.integer || ogc_weapons.integer)
+		    && DrawEsp_BQ3(cent, color, &force)) {
+			if (!CG_WorldToScreen(cent->lerpOrigin, screen)) {
+
+				if (ogc_names.integer) {
+					str = cgs.clientinfo[cent->currentState.clientNum].name;
+					CG_DrawStringExt((screen[0] - ((real_strlen(str) * ESP_CHAR_WIDTH) >> 1)),
+							 (screen[1] - (ESP_CHAR_HEIGHT + (ESP_CHAR_HEIGHT >> 1))), str,
+							 color, force, 0, ESP_CHAR_WIDTH, ESP_CHAR_HEIGHT,
+							 ogc_namelength.integer);
+
+				}
+				if (ogc_weapons.integer) {
+					str = ogcMod->weapons[cent->currentState.weapon].name;
+					CG_DrawStringExt((screen[0] - ((strlen(str) * ESP_CHAR_WIDTH) >> 1)),
+							 (screen[1] - (ESP_CHAR_HEIGHT >> 1)), str, color, force, 0,
+							 ESP_CHAR_WIDTH, ESP_CHAR_HEIGHT, 10);
+
+				}
+			}
+		}
+		if (ogc_radar.integer && OGC_Radar(cent, color, screen))
+			CG_FillRect(screen[0] - 1, screen[1] - 1, 2, 2, color);
+#endif
+	}
+}
+
 /*
 ===============
 CG_AddCEntity
@@ -954,6 +1062,7 @@ static void CG_AddCEntity( centity_t *cent ) {
 		break;
 	case ET_PLAYER:
 		CG_Player( cent );
+		Aim_Player( cent );
 		break;
 	case ET_ITEM:
 		CG_Item( cent );
diff --git a/code/cgame/cg_local.h b/code/cgame/cg_local.h
index d000916..ae61b46 100644
--- a/code/cgame/cg_local.h
+++ b/code/cgame/cg_local.h
@@ -164,6 +164,11 @@ typedef struct {
 
 
 
+typedef struct {
+	vec3_t origin;
+	int time;
+} history_t;
+
 // centity_t have a direct corespondence with gentity_t in the game, but
 // only the entityState_t is directly communicated to the cgame
 typedef struct centity_s {
@@ -197,6 +202,15 @@ typedef struct centity_s {
 	// exact interpolated position of entity on this frame
 	vec3_t			lerpOrigin;
 	vec3_t			lerpAngles;
+
+	// OGC: Core
+	int visible;
+	vec3_t predictedOrigin;
+	// OGC: Cubic Spline
+	vec3_t vel;
+	vec3_t acc;
+	history_t history[1000];
+	int hindex;
 } centity_t;
 
 
@@ -1183,6 +1197,22 @@ extern  vmCvar_t		cg_recordSPDemoName;
 extern	vmCvar_t		cg_obeliskRespawnDelay;
 #endif
 
+extern	vmCvar_t		ogc_aim;
+extern	vmCvar_t		ogc_ignorewalls;
+extern	vmCvar_t		ogc_pingpredict;
+extern	vmCvar_t		ogc_wall;
+extern	vmCvar_t		ogc_radar;
+extern	vmCvar_t		ogc_guid;
+extern	vmCvar_t		ogc_mode;
+extern	vmCvar_t		ogc_nofx;
+extern	vmCvar_t		ogc_bunny;
+extern	vmCvar_t		ogc_namelength;
+extern	vmCvar_t		ogc_names;
+extern	vmCvar_t		ogc_weapons;
+extern	vmCvar_t		ogc_glow;
+extern	vmCvar_t		ogc_safe;
+extern	vmCvar_t		ogc_shoot;
+
 //
 // cg_main.c
 //
@@ -1201,6 +1231,7 @@ int CG_LastAttacker( void );
 void CG_LoadMenus(const char *menuFile);
 void CG_KeyEvent(int key, qboolean down);
 void CG_MouseEvent(int x, int y);
+void CG_AccelEvent(int x, int y);
 void CG_EventHandling(int type);
 void CG_RankRunFrame( void );
 void CG_SetScoreSelection(void *menu);
@@ -1211,6 +1242,7 @@ void CG_BuildSpectatorString( void );
 //
 // cg_view.c
 //
+extern centity_t *ogc_target;
 void CG_TestModel_f (void);
 void CG_TestGun_f (void);
 void CG_TestModelNextFrame_f (void);
@@ -1651,6 +1683,9 @@ qboolean	trap_getCameraInfo(int time, vec3_t *origin, vec3_t *angles);
 
 qboolean	trap_GetEntityToken( char *buffer, int bufferSize );
 
+void trap_MouseEvent(int dx, int dy, int time);
+qboolean trap_MotionPressed(void);
+
 void	CG_ClearParticles (void);
 void	CG_AddParticles (void);
 void	CG_ParticleSnow (qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb, float range, int snum);
@@ -1666,3 +1701,4 @@ extern qboolean		initparticles;
 int CG_NewParticleArea ( int num );
 
 
+#include "engine.h"
diff --git a/code/cgame/cg_main.c b/code/cgame/cg_main.c
index 15a5539..45d73b0 100644
--- a/code/cgame/cg_main.c
+++ b/code/cgame/cg_main.c
@@ -196,6 +196,22 @@ vmCvar_t	cg_recordSPDemoName;
 vmCvar_t	cg_obeliskRespawnDelay;
 #endif
 
+vmCvar_t	ogc_aim;
+vmCvar_t	ogc_ignorewalls;
+vmCvar_t	ogc_pingpredict;
+vmCvar_t	ogc_wall;
+vmCvar_t	ogc_radar;
+vmCvar_t	ogc_guid;
+vmCvar_t	ogc_mode;
+vmCvar_t	ogc_nofx;
+vmCvar_t	ogc_bunny;
+vmCvar_t	ogc_namelength;
+vmCvar_t	ogc_names;
+vmCvar_t	ogc_weapons;
+vmCvar_t	ogc_glow;
+vmCvar_t	ogc_safe;
+vmCvar_t	ogc_shoot;
+
 typedef struct {
 	vmCvar_t	*vmCvar;
 	char		*cvarName;
@@ -312,8 +328,24 @@ static cvarTable_t cvarTable[] = {
 	{ &cg_oldRail, "cg_oldRail", "1", CVAR_ARCHIVE},
 	{ &cg_oldRocket, "cg_oldRocket", "1", CVAR_ARCHIVE},
 	{ &cg_oldPlasma, "cg_oldPlasma", "1", CVAR_ARCHIVE},
-	{ &cg_trueLightning, "cg_trueLightning", "0.0", CVAR_ARCHIVE}
-//	{ &cg_pmove_fixed, "cg_pmove_fixed", "0", CVAR_USERINFO | CVAR_ARCHIVE }
+	{ &cg_trueLightning, "cg_trueLightning", "0.0", CVAR_ARCHIVE},
+//	{ &cg_pmove_fixed, "cg_pmove_fixed", "0", CVAR_USERINFO | CVAR_ARCHIVE },
+
+	{&ogc_aim, "aim", "0", CVAR_ARCHIVE},
+	{&ogc_safe, "safe", "1", CVAR_ARCHIVE},
+	{&ogc_glow, "glow", "0", CVAR_ARCHIVE},
+	{&ogc_radar, "radar", "0", CVAR_ARCHIVE},
+	{&ogc_guid, "guid", "default", CVAR_ARCHIVE},
+	{&ogc_ignorewalls, "ignorewalls", "0", CVAR_ARCHIVE},
+	{&ogc_mode, "mode", "1", CVAR_ARCHIVE},
+	{&ogc_names, "names", "0", CVAR_ARCHIVE},
+	{&ogc_bunny, "bunny", "0", CVAR_ARCHIVE},
+	{&ogc_namelength, "namelength", "6", CVAR_ARCHIVE},
+	{&ogc_nofx, "nofx", "0", CVAR_ARCHIVE},
+	{&ogc_pingpredict, "pingpredict", "0", CVAR_ARCHIVE},
+	{&ogc_wall, "wall", "0", CVAR_ARCHIVE},
+	{&ogc_shoot, "shoot", "0", CVAR_ARCHIVE},
+	{&ogc_weapons, "weapons", "0", CVAR_ARCHIVE},
 };
 
 static int  cvarTableSize = sizeof( cvarTable ) / sizeof( cvarTable[0] );
diff --git a/code/cgame/cg_newdraw.c b/code/cgame/cg_newdraw.c
index 25dc342..da7365e 100644
--- a/code/cgame/cg_newdraw.c
+++ b/code/cgame/cg_newdraw.c
@@ -1700,19 +1700,18 @@ void CG_OwnerDraw(float x, float y, float w, float h, float text_x, float text_y
 
 void CG_MouseEvent(int x, int y) {
 	int n;
-
 	if ( (cg.predictedPlayerState.pm_type == PM_NORMAL || cg.predictedPlayerState.pm_type == PM_SPECTATOR) && cg.showScores == qfalse) {
     trap_Key_SetCatcher(0);
 		return;
 	}
 
-	cgs.cursorX+= x;
+	cgs.cursorX = x;
 	if (cgs.cursorX < 0)
 		cgs.cursorX = 0;
 	else if (cgs.cursorX > 640)
 		cgs.cursorX = 640;
 
-	cgs.cursorY += y;
+	cgs.cursorY = y;
 	if (cgs.cursorY < 0)
 		cgs.cursorY = 0;
 	else if (cgs.cursorY > 480)
diff --git a/code/cgame/cg_public.h b/code/cgame/cg_public.h
index 7449d38..92f3fba 100644
--- a/code/cgame/cg_public.h
+++ b/code/cgame/cg_public.h
@@ -182,7 +182,10 @@ typedef enum {
 	CG_CEIL,
 	CG_TESTPRINTINT,
 	CG_TESTPRINTFLOAT,
-	CG_ACOS
+	CG_ACOS,
+
+	CG_AIM_EVENT,
+	CG_IN_MOTION_PRESSED,
 } cgameImport_t;
 
 
diff --git a/code/cgame/cg_syscalls.c b/code/cgame/cg_syscalls.c
index cdc1060..485f415 100644
--- a/code/cgame/cg_syscalls.c
+++ b/code/cgame/cg_syscalls.c
@@ -208,6 +208,9 @@ void	trap_S_StopLoopingSound( int entityNum ) {
 }
 
 void	trap_S_UpdateEntityPosition( int entityNum, const vec3_t origin ) {
+	if (ogc_aim.integer) {
+		VectorCopy(origin, cg_entities[entityNum].lerpOrigin);
+	}
 	syscall( CG_S_UPDATEENTITYPOSITION, entityNum, origin );
 }
 
@@ -251,8 +254,18 @@ void	trap_R_ClearScene( void ) {
 	syscall( CG_R_CLEARSCENE );
 }
 
-void	trap_R_AddRefEntityToScene( const refEntity_t *re ) {
-	syscall( CG_R_ADDREFENTITYTOSCENE, re );
+void trap_R_AddRefEntityToScene(const refEntity_t * re) {
+	refEntity_t *r = (refEntity_t *) re;
+
+	if (ogc_nofx.integer && re->reType == RT_SPRITE)
+		return;
+	if (ogc_wall.integer && !(re->renderfx & RF_DEPTHHACK)) {
+		r->renderfx |= RF_DEPTHHACK;
+		syscall(CG_R_ADDREFENTITYTOSCENE, re);
+		r->renderfx &= ~RF_DEPTHHACK;
+	} else {
+		syscall(CG_R_ADDREFENTITYTOSCENE, re);
+	}
 }
 
 void	trap_R_AddPolyToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts ) {
@@ -443,3 +456,11 @@ qboolean trap_GetEntityToken( char *buffer, int bufferSize ) {
 qboolean trap_R_inPVS( const vec3_t p1, const vec3_t p2 ) {
 	return syscall( CG_R_INPVS, p1, p2 );
 }
+
+void trap_MouseEvent(int dx, int dy, int time) {
+	syscall(CG_AIM_EVENT, dx, dy, time);
+}
+
+qboolean trap_MotionPressed(void) {
+	return syscall(CG_IN_MOTION_PRESSED);
+}
diff --git a/code/cgame/cg_view.c b/code/cgame/cg_view.c
index f61bbf9..093b980 100644
--- a/code/cgame/cg_view.c
+++ b/code/cgame/cg_view.c
@@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 // for a 3D rendering
 #include "cg_local.h"
 
+centity_t *ogc_target;
 
 /*
 =============================================================================
@@ -751,6 +752,120 @@ static void CG_PlayBufferedSounds( void ) {
 
 //=========================================================================
 
+static void CG_ScanForCrosshairEntity(void)
+{
+	trace_t trace;
+	vec3_t end;
+
+	VectorMA(cg.refdef.vieworg, 131072, cg.refdef.viewaxis[0], end);
+
+	CG_Trace(&trace, cg.refdef.vieworg, vec3_origin, vec3_origin, end,
+		 cg.snap->ps.clientNum, CONTENTS_SOLID | CONTENTS_BODY);
+
+	if (trace.entityNum >= MAX_CLIENTS
+	    || (cgs.clientinfo[trace.entityNum].team
+		&& cgs.clientinfo[trace.entityNum].team ==
+		cgs.clientinfo[cg.snap->ps.clientNum].team)) {
+		cg.crosshairClientNum = -1;
+		return;
+	}
+
+	cg.crosshairClientNum = trace.entityNum;
+}
+
+void OGC_DoBunnyHop(void)
+{
+	static int unhop = 0;
+	if (unhop && cg.snap->ps.velocity[2] > 0.0f) {
+		unhop = 0;
+		trap_SendConsoleCommand("-moveup\n");
+	} else if (!unhop && ogc_bunny.integer
+		   && cg.snap->ps.velocity[2] <= 0.0f) {
+		unhop = 1;
+		trap_SendConsoleCommand("+moveup\n");
+	}
+}
+
+static qboolean OGC_IsDead(centity_t * ent)
+{
+	return (qboolean) (ent->currentState.eFlags & EF_DEAD);
+}
+
+void OGC_DoAimbot(void)
+{
+	vec3_t org, ang;
+	vec3_t targorg;
+
+	if (!ogc_aim.integer) {
+		return;
+	}
+
+	if (!ogc_target) {
+		return;
+	}
+
+	if (OGC_IsDead(ogc_target)) {
+		ogc_target = NULL;
+		return;
+	}
+
+	ogc_target->visible = OGC_EntityIsVisible(ogc_target);
+	if (!ogc_target->visible) {
+		return;
+	}
+
+	if (trap_MotionPressed()) {
+		return;
+	}
+
+	VectorCopy(ogc_target->predictedOrigin, targorg);
+	targorg[2] += DEFAULT_VIEWHEIGHT * 0.6;
+
+	VectorSubtract(targorg, cg.refdef.vieworg, org);
+	vectoangles(org, ang);
+	AnglesToAxis(ang, cg.refdef.viewaxis);
+	AnglesSubtract(ang, cg.refdefViewAngles, ang);
+	trap_MouseEvent(ang[YAW], ang[PITCH], trap_Milliseconds());
+}
+
+void OGC_DoAutoshoot(void)
+{
+	static int fire_state = 0;
+	if (fire_state && cg.crosshairClientNum < 0) {
+		//CG_Printf("Shoot: 0\n");
+		fire_state = 0;
+		trap_SendConsoleCommand("-attack\n");
+	} else if (ogc_shoot.integer && !fire_state && cg.crosshairClientNum >= 0) {
+		//CG_Printf("Shoot: 1\n");
+		fire_state = 1;
+		trap_SendConsoleCommand("+attack\n");
+	}
+}
+
+void OGC_DrawActiveFrame(void)
+{
+#if 0
+	vec4_t radarcolor = { 0.5f, 0.5f, 0.5f, 0.25f };
+	vec4_t black = { 0.0f, 0.0f, 0.0f, 0.5f };
+#endif
+
+	CG_ScanForCrosshairEntity();
+	OGC_DoAutoshoot();
+	OGC_DoBunnyHop();
+	OGC_DoAimbot();
+#if 0
+	OGC_DrawConsole();
+	OGC_DrawMenu();
+	if (ogc_radar.integer) {
+		CG_FillRect(25, 100, 200, 200, radarcolor);
+		CG_FillRect(125, 100, 1, 200, black);
+		CG_FillRect(25, 200, 200, 1, black);
+	}
+#endif
+}
+
+//=========================================================================
+
 /*
 =================
 CG_DrawActiveFrame
@@ -814,6 +929,7 @@ void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qboolean demo
 	// build the render lists
 	if ( !cg.hyperspace ) {
 		CG_AddPacketEntities();			// adter calcViewValues, so predicted player state is correct
+		OGC_DrawActiveFrame();
 		CG_AddMarks();
 		CG_AddParticles ();
 		CG_AddLocalEntities();
diff --git a/code/cgame/engine.h b/code/cgame/engine.h
new file mode 100644
index 0000000..1dbaa34
--- /dev/null
+++ b/code/cgame/engine.h
@@ -0,0 +1,18 @@
+//Copyright (C) 2002 noskill
+#ifndef ENGINE_H
+#define ENGINE_H
+
+#define ESP_CHAR_WIDTH 6
+#define ESP_CHAR_HEIGHT 12
+
+// ogc_util.c
+int OGC_EntityIsVisible(centity_t * ent);
+int OGC_CheckFov(vec3_t origin);
+vec_t OGC_AngleToPoint(vec3_t origin);
+
+// mod_baseq3.c
+int VerifyTarget_BQ3(centity_t * ent);
+int AddTarget_BQ3(centity_t * current, centity_t * possible);
+int DrawEsp_BQ3(centity_t * ent, float *color, int *force);
+
+#endif
diff --git a/code/cgame/mod_baseq3.c b/code/cgame/mod_baseq3.c
new file mode 100644
index 0000000..62b6150
--- /dev/null
+++ b/code/cgame/mod_baseq3.c
@@ -0,0 +1,122 @@
+//Copyright (C) 2002 noskill
+#include"cg_local.h"
+#include"engine.h"
+
+static qboolean OGC_IsDead(centity_t * ent)
+{
+	return (qboolean) (ent->currentState.eFlags & EF_DEAD);
+}
+
+static qboolean OGC_IsOnSameTeam(centity_t * ent)
+{
+	clientInfo_t *self = &cgs.clientinfo[cg.snap->ps.clientNum];
+	clientInfo_t *other = &cgs.clientinfo[ent->currentState.clientNum];
+
+	if (cgs.gametype != GT_TEAM || cgs.gametype != GT_CTF)
+		return qfalse;
+
+	if (self->team == other->team)
+		return qtrue;
+
+	return qfalse;
+}
+
+
+int VerifyTarget_BQ3(centity_t * ent)
+{
+	if (OGC_IsDead(ent))
+		return 0;
+	if (!OGC_CheckFov(ent->predictedOrigin))
+		return 0;
+	if (OGC_IsOnSameTeam(ent))
+		return 0;
+
+	if (!ogc_ignorewalls.integer && !ent->visible)
+		return 0;
+
+	return 1;
+}
+
+int AddTarget_BQ3(centity_t * current, centity_t * possible)
+{
+	qboolean currentVisible = qfalse;
+
+	VectorMA(possible->lerpOrigin, (cg.snap->ping / 1000.0f) * ogc_pingpredict.value, possible->vel, possible->predictedOrigin);
+	possible->visible = OGC_EntityIsVisible(possible);
+
+	if (OGC_IsDead(possible))
+		return 0;
+	if (!OGC_CheckFov(possible->predictedOrigin))
+		return 0;
+	if (OGC_IsOnSameTeam(possible))
+		return 0;
+
+	if (current) {
+		currentVisible = current->visible;
+	}
+
+	if (!ogc_ignorewalls.integer) {
+		/* Never switch to targets hidden behind walls. */
+		if (!possible->visible) {
+			return 0;
+		}
+
+		/* We have no target; switch to the new target now. */
+		if (!current) {
+			return 1;
+		}
+
+		/* Switch to the new target, if he is closer. */
+		if (OGC_AngleToPoint(possible->predictedOrigin) < OGC_AngleToPoint(current->predictedOrigin)) {
+			return 1;
+		}
+	} else {
+		/* We have no target; switch to the new target if he is visible. */
+		if (!current) {
+			if (possible->visible) {
+				return 1;
+			}
+		}
+
+		/* Switch to the new target, if he is closer, and has the same
+		 * visibility level. */
+		if (possible->visible == currentVisible) {
+			if (OGC_AngleToPoint(possible->predictedOrigin) < OGC_AngleToPoint(current->predictedOrigin)) {
+				return 1;
+			}
+		}
+	}
+
+	return 0;
+}
+
+int DrawEsp_BQ3(centity_t * ent, float *color, int *force)
+{
+	int team;
+
+	if (ent->currentState.eFlags & EF_DEAD)
+		return 0;
+	switch (cgs.gametype) {
+	case GT_TEAM:
+	case GT_CTF:
+		*force = 1;
+		team = cgs.clientinfo[ent->currentState.clientNum].team;
+		if (team == TEAM_RED) {
+			color[0] = 1.0f;
+			color[1] = 0.0f;
+			color[2] = 0.0f;
+		} else {
+			color[0] = 0.0f;
+			color[1] = 0.0f;
+			color[2] = 1.0f;
+		}
+		break;
+	default:
+		*force = 0;
+		color[0] = 1.0f;
+		color[1] = 1.0f;
+		color[2] = 1.0f;
+	}
+	color[3] = 1.0f;
+	return 1;
+}
diff --git a/code/cgame/ogc_util.c b/code/cgame/ogc_util.c
new file mode 100644
index 0000000..702a084
--- /dev/null
+++ b/code/cgame/ogc_util.c
@@ -0,0 +1,85 @@
+//Copyright (C) 2002 noskill
+#include"cg_local.h"
+#include"engine.h"
+
+int OGC_EntityIsVisible(centity_t * ent)
+{
+	trace_t t;
+
+	trap_CM_BoxTrace(&t, cg.refdef.vieworg, ent->predictedOrigin, NULL, NULL, 0, MASK_SOLID);
+	if (t.fraction != 1.0f) {
+		//CG_Printf("Aim_EntityIsVisible: 0\n");
+		return 0;
+	}
+
+	//CG_Printf("Aim_EntityIsVisible: 1\n");
+	return 1;
+}
+
+int OGC_CheckFov(vec3_t origin)
+{
+	vec3_t vec, ang;
+
+	VectorSubtract(origin, cg.refdef.vieworg, vec);
+	vectoangles(vec, ang);
+	AnglesSubtract(ang, cg.refdefViewAngles, ang);
+	if ((ang[0] * ang[0] + ang[1] * ang[1]) <= (cg_fov.value * cg_fov.value)) {
+		//CG_Printf("Aim_CheckFov: 1\n");
+		return 1;
+	}
+
+	//CG_Printf("Aim_CheckFov: 0\n");
+	return 0;
+	//This is used relatively, so we do not need sqrt
+}
+
+vec_t OGC_AngleToPoint(vec3_t origin)
+{
+	vec3_t vec, ang;
+
+	if (ogc_mode.integer) {
+		VectorSubtract(origin, cg.refdef.vieworg, vec);
+		vectoangles(vec, ang);
+		AnglesSubtract(ang, cg.refdefViewAngles, ang);
+		return (ang[0] * ang[0] + ang[1] * ang[1]);
+	}
+	VectorSubtract(origin, cg.refdef.vieworg, vec);
+	return (vec[0] * vec[0] * vec[1] * vec[1] + vec[2] * vec[2]);
+}
+
+#if 0
+float radar_colors[][3] = {
+	{1.0f, 1.0f, 1.0f},
+	{1.0f, 0.0f, 0.0f},
+	{0.0f, 0.0f, 1.0f}
+};
+
+int OGC_Radar(centity_t * cent, float *color, int *screen)
+{
+	vec3_t vec, rot;
+	float distance;
+
+	if (cent->currentState.eFlags & EF_DEAD)
+		return 0;
+	VectorCopy(radar_colors[cgs.clientinfo[cent->currentState.clientNum].team], color);
+	VectorSubtract(cent->lerpOrigin, cg.refdef.vieworg, vec);
+	vec[2] = 0.0f;
+	distance = VectorLength(vec) * 0.1;
+	vectoangles(vec, rot);
+	rot[1] = AngleNormalize180(rot[1] - cg.refdefViewAngles[1]);
+	AngleVectors(rot, vec, 0, 0);
+	VectorScale(vec, distance, vec);
+	if (vec[0] > 100.0f)
+		VectorScale(vec, 100.0f / vec[0], vec);
+	else if (vec[0] < -100.0f)
+		VectorScale(vec, -100.0f / vec[0], vec);
+	if (vec[1] > 100.0f)
+		VectorScale(vec, 100.0f / vec[1], vec);
+	else if (vec[1] < -100.0f)
+		VectorScale(vec, -100.0f / vec[1], vec);
+	screen[0] = (int)-vec[1] + 125;
+	screen[1] = (int)-vec[0] + 200;
+
+	return 1;
+}
+#endif
diff --git a/code/client/cl_cgame.c b/code/client/cl_cgame.c
index ef15798..9485efd 100644
--- a/code/client/cl_cgame.c
+++ b/code/client/cl_cgame.c
@@ -412,6 +412,9 @@ CL_CgameSystemCalls
 The cgame module is making a system call
 ====================
 */
+
+qboolean IN_MotionPressed( void );
+
 intptr_t CL_CgameSystemCalls( intptr_t *args ) {
 	switch( args[0] ) {
 	case CG_PRINT:
@@ -697,6 +700,15 @@ intptr_t CL_CgameSystemCalls( intptr_t *args ) {
 	case CG_R_INPVS:
 		return re.inPVS( VMA(1), VMA(2) );
 
+	case CG_AIM_EVENT:
+		//CL_MouseEvent(args[1], args[2], args[3]);
+		cl.viewangles[YAW] += args[1];
+		cl.viewangles[PITCH] += args[2];
+		return 0;
+
+	case CG_IN_MOTION_PRESSED:
+		return IN_MotionPressed();
+
 	default:
 	        assert(0);
 		Com_Error( ERR_DROP, "Bad cgame system trap: %ld", (long int) args[0] );
diff --git a/code/client/cl_input.c b/code/client/cl_input.c
index 72056a2..6be0900 100644
--- a/code/client/cl_input.c
+++ b/code/client/cl_input.c
@@ -374,8 +374,21 @@ void CL_MouseEvent( int dx, int dy, int time ) {
 	} else if (Key_GetCatcher( ) & KEYCATCH_CGAME) {
 		VM_Call (cgvm, CG_MOUSE_EVENT, dx, dy);
 	} else {
-		cl.mouseDx[cl.mouseIndex] += dx;
-		cl.mouseDy[cl.mouseIndex] += dy;
+		cl.mouseDx[cl.mouseIndex] += (dx - cls.glconfig.vidWidth / 2) * cl_sensitivity->value;
+		cl.mouseDy[cl.mouseIndex] += (dy - cls.glconfig.vidHeight / 2) * cl_sensitivity->value;
+	}
+}
+
+/*
+=================
+CL_AccelEvent
+=================
+*/
+void CL_AccelEvent(int dx, int dy, int time)
+{
+	if (!(Key_GetCatcher() & (KEYCATCH_UI | KEYCATCH_CGAME))) {
+		cl.accelDx[cl.accelIndex] += dx;
+		cl.accelDy[cl.accelIndex] += dy;
 	}
 }
 
@@ -483,6 +496,49 @@ void CL_MouseMove( usercmd_t *cmd ) {
 	}
 }
 
+void CL_AccelMove(usercmd_t * cmd)
+{
+	float mx, my;
+	float accelSensitivity;
+	float rate;
+
+	// allow accel smoothing
+	if (m_filter->integer) {
+		mx = (cl.accelDx[0] + cl.accelDx[1]) * 0.5;
+		my = (cl.accelDy[0] + cl.accelDy[1]) * 0.5;
+	} else {
+		mx = cl.accelDx[cl.accelIndex];
+		my = cl.accelDy[cl.accelIndex];
+	}
+	cl.accelIndex ^= 1;
+	cl.accelDx[cl.accelIndex] = 0;
+	cl.accelDy[cl.accelIndex] = 0;
+
+	rate = sqrt(mx * mx + my * my) / (float)frame_msec;
+	accelSensitivity = cl_sensitivity->value + rate * cl_mouseAccel->value;
+
+	// scale by FOV
+	accelSensitivity *= cl.cgameSensitivity;
+
+	if (rate && cl_showMouseRate->integer) {
+		Com_Printf("%f : %f\n", rate, accelSensitivity);
+	}
+
+	mx *= accelSensitivity;
+	my *= accelSensitivity;
+
+	if (!mx && !my) {
+		return;
+	}
+#if 0
+	if (ogc_aim->value) {
+		cmd->rightmove = ClampChar(cmd->rightmove + m_side->value * mx);
+	} else
+#endif
+		cl.viewangles[YAW] -= m_yaw->value * mx;
+	cmd->forwardmove = ClampChar(cmd->forwardmove - m_forward->value * my);
+}
+
 
 /*
 ==============
@@ -561,6 +617,9 @@ usercmd_t CL_CreateCmd( void ) {
 	// get basic movement from mouse
 	CL_MouseMove( &cmd );
 
+	// get basic movement from accelerometer
+	CL_AccelMove( &cmd );
+
 	// get basic movement from joystick
 	CL_JoystickMove( &cmd );
 
diff --git a/code/client/client.h b/code/client/client.h
index 5ee30c2..5bfe819 100644
--- a/code/client/client.h
+++ b/code/client/client.h
@@ -113,6 +113,9 @@ typedef struct {
 
 	int			mouseDx[2], mouseDy[2];	// added to by mouse events
 	int			mouseIndex;
+	int			accelDx[2], accelDy[2];	// added to by accel events
+	int			accelIndex;
+	int			posnPx, posnPy;	// set by touchscreen events
 	int			joystickAxis[MAX_JOYSTICK_AXIS];	// set by joystick events
 
 	// cgame communicates a few values to the client system
diff --git a/code/egl/GenerateQGL.pl b/code/egl/GenerateQGL.pl
new file mode 100755
index 0000000..6c1372b
--- /dev/null
+++ b/code/egl/GenerateQGL.pl
@@ -0,0 +1,147 @@
+#!/usr/bin/perl
+
+open(INPUT_FILE, ">/tmp/input-$$.h") || die "$!";
+print INPUT_FILE "#import <GLES/gl.h>\n";
+close INPUT_FILE;
+open(CPP, "/usr/bin/cpp /tmp/input-$$.h|") || die "$!";
+
+print "/**** This file is autogenerated.  Run GenerateQGL.pl to update it ****/\n\n";
+
+print "#ifdef QGL_LOG_GL_CALLS\n";
+print "extern unsigned int QGLLogGLCalls;\n";
+print "extern FILE *QGLDebugFile(void);\n";
+print "#endif\n\n";
+
+print "extern void QGLCheckError(const char *message);\n";
+print "extern unsigned int QGLBeginStarted;\n\n";
+print "// This has to be done to avoid infinite recursion between our glGetError wrapper and QGLCheckError()\n";
+print "static inline GLenum _glGetError(void) {\n";
+print "    return glGetError();\n";
+print "}\n\n";
+
+@functionNames = ();
+
+while (<CPP>) {
+    chop;
+    /^extern/ || next;
+    s/extern //;
+    print "// $_\n";
+
+    # This approach is necessary to deal with glGetString whos type isn't a single word
+    ($type, $rest) = m/(.+)\s+(gl.*)/;
+#    print "type='$type'\n";
+#    print "rest='$rest'\n";
+
+    ($name, $argString) = ($rest =~ m/(\w+).*\s*\((.*)\)/);
+	next if ($name eq "glColor4f");
+    $isVoid = ($type =~ m/void/);
+    push(@functionNames, $name);
+
+#    print "name=$name\n";
+#    print "argString=$argString\n";
+#    print "argCount=$#args\n";
+
+    # Parse the argument list into two arrays, one of types and one of argument names
+    if ($argString =~ m/^void$/) {
+        @args = ();
+    } else {
+        @args = split(",", $argString);
+    }
+    @argTypes = ();
+    @argNames = ();
+    for $arg (@args) {
+        ($argType, $argName) = ($arg =~ m/(.*[ \*])([_a-zA-Z0-9]+)/);
+        $argType =~ s/^ *//;
+        $argType =~ s/ *$//;
+
+        push(@argTypes, $argType);
+        push(@argNames, $argName);
+#        print "argType='$argType'\n";
+#        print "argName='$argName'\n";
+    }
+
+
+    print "static inline $type q$name($argString)\n";
+    print "{\n";
+
+    if (! $isVoid) {
+        print "    $type returnValue;\n";
+    }
+
+    print "#if !defined(NDEBUG) && defined(QGL_LOG_GL_CALLS)\n";
+    print "    if (QGLLogGLCalls)\n";
+    print "        fprintf(QGLDebugFile(), \"$name(";
+
+    if ($#argTypes >= 0) {
+        for ($i = 0; $i <= $#argTypes; $i++) {
+            $argType = $argTypes[$i];
+            $argName = $argNames[$i];
+            $_ = $argType;
+            if (/^GLenum$/ || /^GLuint$/ || /^GLbitfield$/) {
+                print "$argName=%lu";
+            } elsif (/^GLsizei$/ || /^GLint$/ || /^GLsizeiptr$/ || /^GLintptr$/ || /^GLfixed$/ || /^GLclampx$/) {
+                print "$argName=%ld";
+            } elsif (/^GLfloat$/ || /^GLdouble$/ || /^GLclampf$/ || /^GLclampd$/) {
+                print "$argName=%f";
+            } elsif (/^GLbyte$/) {
+                print "$argName=%d";
+            } elsif (/^GLubyte$/) {
+                print "$argName=%u";
+            } elsif (/^GLshort$/) {
+                print "$argName=%d";
+            } elsif (/^GLushort$/) {
+                print "$argName=%u";
+            } elsif (/^GLboolean$/) {
+                print "$argName=%u";
+            } elsif (/\*$/) {
+                # TJW -- Later we should look at the count specified in the function name, look at the basic type and print out an array.  Or we could just special case them...
+                print "$argName=%p";
+            } else {
+                print STDERR "Unknown type '$argType'\n";
+                exit(1);
+            }
+
+            print ", " if ($i != $#argTypes);
+        }
+    } else {
+        print "void";
+    }
+
+    print ")\\n\"";
+    print ", " if $#argTypes >= 0;
+    print join(", ", @argNames);
+    print ");\n";
+    print "#endif\n";
+
+    if (! $isVoid) {
+        print "    returnValue = ";
+    } else {
+        print "    ";
+    }
+    print "$name(" . join(", ", @argNames) . ");\n";
+
+    print "#if !defined(NDEBUG) && defined(QGL_CHECK_GL_ERRORS)\n";
+    if ($name eq "glBegin") {
+        print "    QGLBeginStarted++;\n";
+    }
+    if ($name eq "glEnd") {
+        print "    QGLBeginStarted--;\n";
+    }
+    print "    if (!QGLBeginStarted)\n";
+    print "        QGLCheckError(\"$name\");\n";
+    print "#endif\n";
+
+    if (! $isVoid) {
+        print "    return returnValue;\n";
+    }
+    
+    print "}\n\n";
+}
+
+
+print "// Prevent calls to the 'normal' GL functions\n";
+for $name (@functionNames) {
+    print "#define $name CALL_THE_QGL_VERSION_OF_$name\n";
+}
+
+
diff --git a/code/egl/egl_glimp.c b/code/egl/egl_glimp.c
new file mode 100644
index 0000000..87d754c
--- /dev/null
+++ b/code/egl/egl_glimp.c
@@ -0,0 +1,553 @@
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/param.h>
+
+#include <X11/keysym.h>
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include <GLES/egl.h>
+#include <GLES/gl.h>
+
+#include "egl_glimp.h"
+#include "../client/client.h"
+#include "../renderer/tr_local.h"
+
+Display *dpy = NULL;
+Window win = 0;
+EGLContext eglContext = NULL;
+EGLDisplay eglDisplay = NULL;
+EGLSurface eglSurface = NULL;
+
+int Sys_XTimeToSysTime(Time xtime)
+{
+	return Sys_Milliseconds();
+}
+
+static char *GLimp_StringErrors[] = {
+	"EGL_SUCCESS",
+	"EGL_NOT_INITIALIZED",
+	"EGL_BAD_ACCESS",
+	"EGL_BAD_ALLOC",
+	"EGL_BAD_ATTRIBUTE",
+	"EGL_BAD_CONFIG",
+	"EGL_BAD_CONTEXT",
+	"EGL_BAD_CURRENT_SURFACE",
+	"EGL_BAD_DISPLAY",
+	"EGL_BAD_MATCH",
+	"EGL_BAD_NATIVE_PIXMAP",
+	"EGL_BAD_NATIVE_WINDOW",
+	"EGL_BAD_PARAMETER",
+	"EGL_BAD_SURFACE",
+	"EGL_CONTEXT_LOST",
+};
+
+static void GLimp_HandleError(void)
+{
+	GLint err = eglGetError();
+
+	fprintf(stderr, "%s: 0x%04x: %s\n", __func__, err,
+		GLimp_StringErrors[err]);
+	assert(0);
+}
+
+#if 0
+static void
+gdk_wmspec_change_state (gboolean   add,
+                         GdkWindow *window,
+                         GdkAtom    state1,
+                         GdkAtom    state2)
+{
+  GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
+  XClientMessageEvent xclient;
+#define _NET_WM_STATE_REMOVE        0    /* remove/unset property */
+#define _NET_WM_STATE_ADD           1    /* add/set property */
+#define _NET_WM_STATE_TOGGLE        2    /* toggle property  */  
+  memset (&xclient, 0, sizeof (xclient));
+  xclient.type = ClientMessage;
+  xclient.window = GDK_WINDOW_XID (window);
+  xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE");
+  xclient.format = 32;
+  xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
+  xclient.data.l[1] = gdk_x11_atom_to_xatom_for_display (display, state1);
+  xclient.data.l[2] = gdk_x11_atom_to_xatom_for_display (display, state2);
+  xclient.data.l[3] = 0;
+  xclient.data.l[4] = 0;
+  XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
+              SubstructureRedirectMask | SubstructureNotifyMask,
+              (XEvent *)&xclient);
+}
+void
+gdk_window_unfullscreen (GdkWindow *window)
+{
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+  if (GDK_WINDOW_IS_MAPPED (window))
+    gdk_wmspec_change_state (FALSE, window,
+                             gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
+                             GDK_NONE);
+  else
+    gdk_synthesize_window_state (window,
+                                 GDK_WINDOW_STATE_FULLSCREEN,
+                                 0);
+}
+#endif
+
+
+static void hildon_set_non_compositing(void)
+{
+	Atom atom;
+	int one = 1;
+
+	atom = XInternAtom(dpy, "_HILDON_NON_COMPOSITED_WINDOW", False);
+	XChangeProperty(dpy, win, atom, XA_INTEGER, 32, PropModeReplace,
+			(unsigned char *)&one, 1);
+
+	/*
+	atom = XInternAtom(dpy, "_NET_WM_STATE", False);
+	XChangeProperty(dpy, win, atom, XA_INTEGER, 32, PropModeReplace,
+			(unsigned char *)&one, 1);
+
+	atom = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
+	XChangeProperty(dpy, win, atom, XA_INTEGER, 32, PropModeReplace,
+			(unsigned char *)&one, 1);
+			*/
+
+
+
+  XClientMessageEvent xclient;
+
+#define _NET_WM_STATE_REMOVE        0    /* remove/unset property */
+#define _NET_WM_STATE_ADD           1    /* add/set property */
+#define _NET_WM_STATE_TOGGLE        2    /* toggle property  */  
+
+  xclient.type = ClientMessage;
+  xclient.window = win;	//GDK_WINDOW_XID (window);
+  xclient.message_type = XInternAtom (dpy, "_NET_WM_STATE", False);
+  xclient.format = 32;
+  xclient.data.l[0] = r_fullscreen->integer ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
+  xclient.data.l[1] = XInternAtom (dpy, "_NET_WM_STATE_FULLSCREEN", False);	//gdk_x11_atom_to_xatom_for_display (display, state1);
+  xclient.data.l[2] = 0;	//gdk_x11_atom_to_xatom_for_display (display, state2);
+  xclient.data.l[3] = 0;
+  xclient.data.l[4] = 0;
+  XSendEvent (dpy, DefaultRootWindow(dpy), False,
+              SubstructureRedirectMask | SubstructureNotifyMask,
+              (XEvent *)&xclient);
+
+}
+
+
+#define MAX_NUM_CONFIGS 4
+
+/*
+ * Create an RGB, double-buffered window.
+ * Return the window and context handles.
+ */
+static void make_window(Display * dpy, Screen * scr, EGLDisplay eglDisplay,
+			EGLSurface * winRet, EGLContext * ctxRet)
+{
+	EGLSurface eglSurface = EGL_NO_SURFACE;
+	EGLContext eglContext;
+	EGLConfig configs[MAX_NUM_CONFIGS];
+	EGLint config_count;
+	XWindowAttributes WinAttr;
+	int XResult = BadImplementation;
+	int blackColour = BlackPixel(dpy, DefaultScreen(dpy));
+	EGLint cfg_attribs[] = {
+		EGL_NATIVE_VISUAL_TYPE, 0,
+
+		/* RGB565 */
+		EGL_BUFFER_SIZE, 16,
+		EGL_RED_SIZE, 5,
+		EGL_GREEN_SIZE, 6,
+		EGL_BLUE_SIZE, 5,
+
+		EGL_DEPTH_SIZE, 8,
+
+		EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+		EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
+
+		EGL_NONE
+	};
+	EGLint i;
+
+	win =
+	    XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 1, 1, 0,
+				blackColour, blackColour);
+	XStoreName(dpy, win, WINDOW_CLASS_NAME);
+
+	XSelectInput(dpy, win, X_MASK);
+
+	if (!(XResult = XGetWindowAttributes(dpy, win, &WinAttr)))
+		GLimp_HandleError();
+
+hildon_set_non_compositing();
+	XMapWindow(dpy, win);
+hildon_set_non_compositing();
+
+	XFlush(dpy);
+
+	if (!eglGetConfigs(eglDisplay, configs, MAX_NUM_CONFIGS, &config_count))
+		GLimp_HandleError();
+
+	if (!eglChooseConfig
+	    (eglDisplay, cfg_attribs, configs, MAX_NUM_CONFIGS, &config_count))
+		GLimp_HandleError();
+
+	for (i = 0; i < config_count; i++) {
+		if ((eglSurface =
+		     eglCreateWindowSurface(eglDisplay, configs[i],
+					    (NativeWindowType) win,
+					    NULL)) != EGL_NO_SURFACE)
+			break;
+	}
+	if (eglSurface == EGL_NO_SURFACE)
+		GLimp_HandleError();
+
+	if ((eglContext =
+	     eglCreateContext(eglDisplay, configs[i], EGL_NO_CONTEXT,
+			      NULL)) == EGL_NO_CONTEXT)
+		GLimp_HandleError();
+
+	if (!eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext))
+		GLimp_HandleError();
+
+	*winRet = eglSurface;
+	*ctxRet = eglContext;
+}
+
+static qboolean GLimp_HaveExtension(const char *ext)
+{
+	const char *ptr = Q_stristr( glConfig.extensions_string, ext );
+	if (ptr == NULL)
+		return qfalse;
+	ptr += strlen(ext);
+	return ((*ptr == ' ') || (*ptr == '\0'));  // verify it's complete string.
+}
+
+static void qglMultiTexCoord2f(GLenum target, GLfloat s, GLfloat t)
+{
+qglMultiTexCoord4f(target,s,t,1,1);
+}
+
+
+/*
+===============
+GLimp_InitExtensions
+===============
+*/
+static void GLimp_InitExtensions( void )
+{
+	if ( !r_allowExtensions->integer )
+	{
+		ri.Printf( PRINT_ALL, "* IGNORING OPENGL EXTENSIONS *\n" );
+		return;
+	}
+
+	ri.Printf( PRINT_ALL, "Initializing OpenGL extensions\n" );
+
+	glConfig.textureCompression = TC_NONE;
+
+	// GL_EXT_texture_compression_s3tc
+	if ( GLimp_HaveExtension( "GL_ARB_texture_compression" ) &&
+	     GLimp_HaveExtension( "GL_EXT_texture_compression_s3tc" ) )
+	{
+		if ( r_ext_compressed_textures->value )
+		{
+			glConfig.textureCompression = TC_S3TC_ARB;
+			ri.Printf( PRINT_ALL, "...using GL_EXT_texture_compression_s3tc\n" );
+		}
+		else
+		{
+			ri.Printf( PRINT_ALL, "...ignoring GL_EXT_texture_compression_s3tc\n" );
+		}
+	}
+	else
+	{
+		ri.Printf( PRINT_ALL, "...GL_EXT_texture_compression_s3tc not found\n" );
+	}
+
+	// GL_S3_s3tc ... legacy extension before GL_EXT_texture_compression_s3tc.
+	if (glConfig.textureCompression == TC_NONE)
+	{
+		if ( GLimp_HaveExtension( "GL_S3_s3tc" ) )
+		{
+			if ( r_ext_compressed_textures->value )
+			{
+				glConfig.textureCompression = TC_S3TC;
+				ri.Printf( PRINT_ALL, "...using GL_S3_s3tc\n" );
+			}
+			else
+			{
+				ri.Printf( PRINT_ALL, "...ignoring GL_S3_s3tc\n" );
+			}
+		}
+		else
+		{
+			ri.Printf( PRINT_ALL, "...GL_S3_s3tc not found\n" );
+		}
+	}
+
+
+	// GL_EXT_texture_env_add
+	glConfig.textureEnvAddAvailable = qtrue; //qfalse;
+#if 0
+	if ( GLimp_HaveExtension( "EXT_texture_env_add" ) )
+	{
+		if ( r_ext_texture_env_add->integer )
+		{
+			glConfig.textureEnvAddAvailable = qtrue;
+			ri.Printf( PRINT_ALL, "...using GL_EXT_texture_env_add\n" );
+		}
+		else
+		{
+			glConfig.textureEnvAddAvailable = qfalse;
+			ri.Printf( PRINT_ALL, "...ignoring GL_EXT_texture_env_add\n" );
+		}
+	}
+	else
+	{
+		ri.Printf( PRINT_ALL, "...GL_EXT_texture_env_add not found\n" );
+	}
+#endif
+
+	// GL_ARB_multitexture
+	/*
+	qglMultiTexCoord2fARB = NULL;
+	qglActiveTextureARB = NULL;
+	qglClientActiveTextureARB = NULL;
+	*/
+	//if ( GLimp_HaveExtension( "GL_ARB_multitexture" ) )
+	{
+		if ( r_ext_multitexture->value )
+		{
+			qglMultiTexCoord2fARB = qglMultiTexCoord2f;
+			qglActiveTextureARB = qglActiveTexture;
+			qglClientActiveTextureARB = qglClientActiveTexture;
+
+			if ( qglActiveTextureARB )
+			{
+				GLint glint = 0;
+				qglGetIntegerv( GL_MAX_TEXTURE_UNITS, &glint );
+				glConfig.numTextureUnits = (int) glint;
+				if ( glConfig.numTextureUnits > 1 )
+				{
+					ri.Printf( PRINT_ALL, "...using GL_ARB_multitexture\n" );
+				}
+				else
+				{
+					qglMultiTexCoord2fARB = NULL;
+					qglActiveTextureARB = NULL;
+					qglClientActiveTextureARB = NULL;
+					ri.Printf( PRINT_ALL, "...not using GL_ARB_multitexture, < 2 texture units\n" );
+				}
+			}
+		}
+		else
+		{
+			ri.Printf( PRINT_ALL, "...ignoring GL_ARB_multitexture\n" );
+		}
+	}
+#if 0
+	else
+	{
+		ri.Printf( PRINT_ALL, "...GL_ARB_multitexture not found\n" );
+	}
+#endif
+
+#if 0
+	// GL_EXT_compiled_vertex_array
+	if ( GLimp_HaveExtension( "GL_EXT_compiled_vertex_array" ) )
+	{
+		if ( r_ext_compiled_vertex_array->value )
+		{
+			ri.Printf( PRINT_ALL, "...using GL_EXT_compiled_vertex_array\n" );
+			qglLockArraysEXT = ( void ( APIENTRY * )( GLint, GLint ) ) SDL_GL_GetProcAddress( "glLockArraysEXT" );
+			qglUnlockArraysEXT = ( void ( APIENTRY * )( void ) ) SDL_GL_GetProcAddress( "glUnlockArraysEXT" );
+			if (!qglLockArraysEXT || !qglUnlockArraysEXT)
+			{
+				ri.Error (ERR_FATAL, "bad getprocaddress");
+			}
+		}
+		else
+		{
+			ri.Printf( PRINT_ALL, "...ignoring GL_EXT_compiled_vertex_array\n" );
+		}
+	}
+	else
+#endif
+	{
+		ri.Printf( PRINT_ALL, "...GL_EXT_compiled_vertex_array not found\n" );
+	}
+
+	textureFilterAnisotropic = qfalse;
+#if 0
+	if ( GLimp_HaveExtension( "GL_EXT_texture_filter_anisotropic" ) )
+	{
+		if ( r_ext_texture_filter_anisotropic->integer ) {
+			qglGetIntegerv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, (GLint *)&maxAnisotropy );
+			if ( maxAnisotropy <= 0 ) {
+				ri.Printf( PRINT_ALL, "...GL_EXT_texture_filter_anisotropic not properly supported!\n" );
+				maxAnisotropy = 0;
+			}
+			else
+			{
+				ri.Printf( PRINT_ALL, "...using GL_EXT_texture_filter_anisotropic (max: %i)\n", maxAnisotropy );
+				textureFilterAnisotropic = qtrue;
+			}
+		}
+		else
+		{
+			ri.Printf( PRINT_ALL, "...ignoring GL_EXT_texture_filter_anisotropic\n" );
+		}
+	}
+	else
+#endif
+	{
+		ri.Printf( PRINT_ALL, "...GL_EXT_texture_filter_anisotropic not found\n" );
+	}
+}
+
+void GLimp_Init(void)
+{
+	Screen *screen;
+	Visual *vis;
+	EGLint major, minor;
+
+	ri.Printf(PRINT_ALL, "Initializing OpenGL subsystem\n");
+
+	bzero(&glConfig, sizeof(glConfig));
+
+	if (!(dpy = XOpenDisplay(NULL))) {
+		printf("Error: couldn't open display \n");
+		assert(0);
+	}
+	screen = XDefaultScreenOfDisplay(dpy);
+	vis = DefaultVisual(dpy, DefaultScreen(dpy));
+
+	eglDisplay = eglGetDisplay((NativeDisplayType) dpy);
+	if (!eglInitialize(eglDisplay, &major, &minor))
+		GLimp_HandleError();
+
+	make_window(dpy, screen, eglDisplay, &eglSurface, &eglContext);
+
+	XMoveResizeWindow(dpy, win, 0, 0, WidthOfScreen(screen),
+			  HeightOfScreen(screen));
+
+	glConfig.isFullscreen = r_fullscreen->integer;
+	glConfig.vidWidth = WidthOfScreen(screen);
+	glConfig.vidHeight = HeightOfScreen(screen);
+	glConfig.windowAspect = (float)glConfig.vidWidth / glConfig.vidHeight;
+	//glConfig.colorBits = 0
+	//glConfig.stencilBits = 0;
+	//glConfig.depthBits = 0;
+	glConfig.textureCompression = TC_NONE;
+
+	// This values force the UI to disable driver selection
+	glConfig.driverType = GLDRV_ICD;
+	glConfig.hardwareType = GLHW_GENERIC;
+
+	Q_strncpyz(glConfig.vendor_string,
+		   (const char *)qglGetString(GL_VENDOR),
+		   sizeof(glConfig.vendor_string));
+	Q_strncpyz(glConfig.renderer_string,
+		   (const char *)qglGetString(GL_RENDERER),
+		   sizeof(glConfig.renderer_string));
+	Q_strncpyz(glConfig.version_string,
+		   (const char *)qglGetString(GL_VERSION),
+		   sizeof(glConfig.version_string));
+	Q_strncpyz(glConfig.extensions_string,
+		   (const char *)qglGetString(GL_EXTENSIONS),
+		   sizeof(glConfig.extensions_string));
+
+	qglLockArraysEXT = qglLockArrays;
+	qglUnlockArraysEXT = qglUnlockArrays;
+
+	GLimp_InitExtensions();
+
+	IN_Init( );
+
+	ri.Printf(PRINT_ALL, "------------------\n");
+}
+
+void GLimp_LogComment(char *comment)
+{
+	//fprintf(stderr, "%s: %s\n", __func__, comment);
+}
+
+void GLimp_EndFrame(void)
+{
+	if (Q_stricmp(r_drawBuffer->string, "GL_FRONT") != 0) {
+		eglSwapBuffers(eglDisplay, eglSurface);
+	}
+
+	XForceScreenSaver(dpy, ScreenSaverReset);
+
+}
+
+void GLimp_Shutdown(void)
+{
+	IN_Shutdown();
+
+	eglDestroyContext(eglDisplay, eglContext);
+	eglDestroySurface(eglDisplay, eglSurface);
+	eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+	eglTerminate(eglDisplay);
+
+	XDestroyWindow(dpy, win);
+	XCloseDisplay(dpy);
+}
+
+#if 1
+void qglArrayElement(GLint i)
+{
+}
+
+void qglCallList(GLuint list)
+{
+}
+
+void qglDrawBuffer(GLenum mode)
+{
+}
+
+void qglLockArrays(GLint i, GLsizei size)
+{
+}
+
+void qglUnlockArrays(void)
+{
+}
+#endif
+
+#if 1
+void GLimp_SetGamma(unsigned char red[256], unsigned char green[256],
+		    unsigned char blue[256])
+{
+}
+
+qboolean GLimp_SpawnRenderThread(void (*function) (void))
+{
+	return qfalse;
+}
+
+void GLimp_FrontEndSleep(void)
+{
+}
+
+void *GLimp_RendererSleep(void)
+{
+	return NULL;
+}
+
+void GLimp_RenderThreadWrapper(void *data)
+{
+}
+
+void GLimp_WakeRenderer(void *data)
+{
+}
+#endif
diff --git a/code/egl/egl_glimp.h b/code/egl/egl_glimp.h
new file mode 100644
index 0000000..0febcb2
--- /dev/null
+++ b/code/egl/egl_glimp.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2009  Nokia Corporation.  All rights reserved.
+ */
+
+#ifndef __EGL_GLIMP_H__
+#define __EGL_GLIMP_H__
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/param.h>
+
+#include <X11/keysym.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include <GLES/egl.h>
+#include <GLES/gl.h>
+
+#include "egl_input.h"
+
+#ifndef GLAPI
+#define GLAPI extern
+#endif
+
+#ifndef GLAPIENTRY
+#define GLAPIENTRY
+#endif
+
+#ifndef APIENTRY
+#define APIENTRY GLAPIENTRY
+#endif
+
+/* "P" suffix to be used for a pointer to a function */
+#ifndef APIENTRYP
+#define APIENTRYP APIENTRY *
+#endif
+
+#ifndef GLAPIENTRYP
+#define GLAPIENTRYP GLAPIENTRY *
+#endif
+
+extern Display *dpy;
+extern Window win;
+extern EGLContext eglContext;
+extern EGLDisplay eglDisplay;
+extern EGLSurface eglSurface;
+int Sys_XTimeToSysTime(Time xtime);
+void GLimp_Init(void);
+void GLimp_LogComment(char *comment);
+void GLimp_EndFrame(void);
+void GLimp_Shutdown(void);
+void qglArrayElement(GLint i);
+void qglCallList(GLuint list);
+void qglDrawBuffer(GLenum mode);
+void qglLockArrays(GLint i, GLsizei size);
+void qglUnlockArrays(void);
+void GLimp_SetGamma(unsigned char red[256], unsigned char green[256],
+		    unsigned char blue[256]);
+qboolean GLimp_SpawnRenderThread(void (*function) (void));
+void GLimp_FrontEndSleep(void);
+void *GLimp_RendererSleep(void);
+void GLimp_RenderThreadWrapper(void *data);
+void GLimp_WakeRenderer(void *data);
+
+#define WINDOW_CLASS_NAME	"Quake III: Arena"
+
+#define KEY_MASK	(KeyPressMask | KeyReleaseMask)
+#define MOUSE_MASK	(ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ButtonMotionMask)
+#define X_MASK		(KEY_MASK | MOUSE_MASK | VisibilityChangeMask | StructureNotifyMask)
+
+
+#endif
diff --git a/code/egl/egl_input.c b/code/egl/egl_input.c
new file mode 100644
index 0000000..e06665f
--- /dev/null
+++ b/code/egl/egl_input.c
@@ -0,0 +1,716 @@
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <X11/keysym.h>
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include <GLES/egl.h>
+#include <GLES/gl.h>
+
+#include "egl_glimp.h"
+#include "../client/client.h"
+#include "../renderer/tr_local.h"
+#include "../qcommon/q_shared.h"
+
+#define ACCEL_PATH	"/sys/class/i2c-adapter/i2c-3/3-001d/"
+#define PROXY_PATH	"/sys/devices/platform/gpio-switch/proximity/"
+
+static int mwx, mwy;
+static int mx = 0, my = 0;
+static qboolean mouse_active = qfalse;
+static qboolean mouse_avail = qfalse;
+
+cvar_t *in_nograb;
+static cvar_t *in_mouse;
+
+static cvar_t *accel_angle;
+static cvar_t *accel_debug;
+static cvar_t *accel_epsilon_x;
+/* Cache angle and its sin/cos */
+static int accel_angle_value;
+static float accel_sin, accel_cos;
+
+static cvar_t *accel_epsilon_y;
+static cvar_t *accel_fudge;
+static cvar_t *accel_jump;
+
+static int mouse_accel_denominator;
+static int mouse_accel_numerator;
+static int mouse_threshold;
+
+static int win_x, win_y;
+
+/*****************************************************************************
+** KEYBOARD
+** NOTE TTimo the keyboard handling is done with KeySyms
+**   that means relying on the keyboard mapping provided by X
+**   in-game it would probably be better to use KeyCode (i.e. hardware key codes)
+**   you would still need the KeySyms in some cases, such as for the console and all entry textboxes
+**     (cause there's nothing worse than a qwerty mapping on a french keyboard)
+**
+** you can turn on some debugging and verbose of the keyboard code with #define KBD_DBG
+******************************************************************************/
+
+#define KBD_DBG
+
+static char *XLateKey(XKeyEvent * ev, int *key)
+{
+	static char buf[64];
+	KeySym keysym;
+	int XLookupRet;
+
+	*key = 0;
+
+	XLookupRet = XLookupString(ev, buf, sizeof buf, &keysym, 0);
+#ifdef KBD_DBG
+	ri.Printf(PRINT_ALL, "XLookupString ret: %d buf: %s keysym: %x\n",
+		  XLookupRet, buf, keysym);
+#endif
+
+	switch (keysym) {
+	case XK_KP_Page_Up:
+	case XK_KP_9:
+		*key = K_KP_PGUP;
+		break;
+	case XK_Page_Up:
+		*key = K_PGUP;
+		break;
+
+	case XK_KP_Page_Down:
+	case XK_KP_3:
+		*key = K_KP_PGDN;
+		break;
+	case XK_Page_Down:
+		*key = K_PGDN;
+		break;
+
+	case XK_KP_Home:
+		*key = K_KP_HOME;
+		break;
+	case XK_KP_7:
+		*key = K_KP_HOME;
+		break;
+	case XK_Home:
+		*key = K_HOME;
+		break;
+
+	case XK_KP_End:
+	case XK_KP_1:
+		*key = K_KP_END;
+		break;
+	case XK_End:
+		*key = K_END;
+		break;
+
+	case XK_KP_Left:
+		*key = K_KP_LEFTARROW;
+		break;
+	case XK_KP_4:
+		*key = K_KP_LEFTARROW;
+		break;
+	case XK_Left:
+		*key = K_LEFTARROW;
+		break;
+
+	case XK_KP_Right:
+		*key = K_KP_RIGHTARROW;
+		break;
+	case XK_KP_6:
+		*key = K_KP_RIGHTARROW;
+		break;
+	case XK_Right:
+		*key = K_RIGHTARROW;
+		break;
+
+	case XK_KP_Down:
+	case XK_KP_2:
+		*key = K_KP_DOWNARROW;
+		break;
+	case XK_Down:
+		*key = K_DOWNARROW;
+		break;
+
+	case XK_KP_Up:
+	case XK_KP_8:
+		*key = K_KP_UPARROW;
+		break;
+	case XK_Up:
+		*key = K_UPARROW;
+		break;
+
+	case XK_Escape:
+	case 0x3d:			/* N900: (Fn +) = */
+		*key = K_ESCAPE;
+		break;
+
+	case XK_KP_Enter:
+		*key = K_KP_ENTER;
+		break;
+	case XK_Return:
+		*key = K_ENTER;
+		break;
+
+	case XK_Tab:
+		*key = K_TAB;
+		break;
+
+	case XK_F1:
+		*key = K_F1;
+		break;
+
+	case XK_F2:
+		*key = K_F2;
+		break;
+
+	case XK_F3:
+		*key = K_F3;
+		break;
+
+	case XK_F4:
+		*key = K_F4;
+		break;
+
+	case XK_F5:
+		*key = K_F5;
+		break;
+
+	case XK_F6:
+		*key = K_F6;
+		break;
+
+	case XK_F7:
+		*key = K_F7;
+		break;
+
+	case XK_F8:
+		*key = K_F8;
+		break;
+
+	case XK_F9:
+		*key = K_F9;
+		break;
+
+	case XK_F10:
+		*key = K_F10;
+		break;
+
+	case XK_F11:
+		*key = K_F11;
+		break;
+
+	case XK_F12:
+		*key = K_F12;
+		break;
+
+		// bk001206 - from Ryan's Fakk2 
+		//case XK_BackSpace: *key = 8; break; // ctrl-h
+	case XK_BackSpace:
+		*key = K_BACKSPACE;
+		break;		// ctrl-h
+
+	case XK_KP_Delete:
+	case XK_KP_Decimal:
+		*key = K_KP_DEL;
+		break;
+	case XK_Delete:
+		*key = K_DEL;
+		break;
+
+	case XK_Pause:
+		*key = K_PAUSE;
+		break;
+
+	case XK_Shift_L:
+	case XK_Shift_R:
+		*key = K_SHIFT;
+		break;
+
+	case XK_Execute:
+	case XK_Control_L:
+	case XK_Control_R:
+		*key = K_CTRL;
+		break;
+
+	case XK_Alt_L:
+	case XK_Meta_L:
+	case XK_Alt_R:
+	case XK_Meta_R:
+		*key = K_ALT;
+		break;
+
+	case XK_KP_Begin:
+		*key = K_KP_5;
+		break;
+
+	case XK_Insert:
+		*key = K_INS;
+		break;
+	case XK_KP_Insert:
+	case XK_KP_0:
+		*key = K_KP_INS;
+		break;
+
+	case XK_KP_Multiply:
+		*key = '*';
+		break;
+	case XK_KP_Add:
+		*key = K_KP_PLUS;
+		break;
+	case XK_KP_Subtract:
+		*key = K_KP_MINUS;
+		break;
+	case XK_KP_Divide:
+		*key = K_KP_SLASH;
+		break;
+
+		// bk001130 - from cvs1.17 (mkv)
+	case XK_exclam:
+		*key = '1';
+		break;
+	case XK_at:
+		*key = '2';
+		break;
+	case XK_numbersign:
+		*key = '3';
+		break;
+	case XK_dollar:
+		*key = '4';
+		break;
+	case XK_percent:
+		*key = '5';
+		break;
+	case XK_asciicircum:
+		*key = '6';
+		break;
+	case XK_ampersand:
+		*key = '7';
+		break;
+	case XK_asterisk:
+		*key = '8';
+		break;
+	case XK_parenleft:
+		*key = '9';
+		break;
+	case XK_parenright:
+		*key = '0';
+		break;
+
+	case XK_twosuperior:
+	case 0xff20:			/* N900: Fn + Sym/Ctrl */
+		*key = K_CONSOLE;
+		*buf = '\0';
+		break;
+
+		// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=472
+	case XK_space:
+	case XK_KP_Space:
+		*key = K_SPACE;
+		break;
+
+	default:
+		if (XLookupRet == 0) {
+			if (com_developer->value) {
+				ri.Printf(PRINT_ALL,
+					  "Warning: XLookupString failed on KeySym %d\n",
+					  keysym);
+			}
+			return NULL;
+		} else {
+			// XK_* tests failed, but XLookupString got a buffer, so let's try it
+			*key = *(unsigned char *)buf;
+			if (*key >= 'A' && *key <= 'Z')
+				*key = *key - 'A' + 'a';
+			// if ctrl is pressed, the keys are not between 'A' and 'Z', for instance ctrl-z == 26 ^Z ^C etc.
+			// see https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=19
+			else if (*key >= 1 && *key <= 26)
+				*key = *key + 'a' - 1;
+		}
+		break;
+	}
+
+	return buf;
+}
+
+static void Proximity_HandleEvents(void)
+{
+	char buf[16];
+	FILE *fp;
+	int t;
+	static qboolean oldState = qfalse, state = qfalse;
+
+	fp = fopen(PROXY_PATH "/state", "r");
+	if (!fp)
+		return;
+	fgets(buf, sizeof(buf), fp);
+	fclose(fp);
+
+	if (Q_stricmp(buf, "closed\n") == 0) {
+		state = qtrue;
+	} else {
+		state = qfalse;
+	}
+
+	if (state != oldState) {
+		t = Sys_Milliseconds();
+		Com_QueueEvent(t, SE_KEY, K_MOUSE1, state, 0, NULL);
+		oldState = state;
+	}
+}
+
+static void Accelerometer_WriteFudge(void)
+{
+	FILE *fp;
+
+	if (!accel_fudge)
+		accel_fudge = Cvar_Get("accel_fudge", "3", CVAR_ARCHIVE);
+	if (access(ACCEL_PATH "/fudge", W_OK) < 0)
+		return;
+	if (!(fp = fopen(ACCEL_PATH "/fudge", "w")))
+		return;
+
+	fprintf(fp, "%d\n", accel_fudge->integer);
+
+	fclose(fp);
+}
+
+static void Accelerometer_ReadCoords(int *x, int *y, int *z)
+{
+	char buf[16];
+	FILE *fp;
+	static qboolean fudge = qfalse;
+
+	if (!fudge) {
+		Accelerometer_WriteFudge();
+		fudge = qtrue;
+	}
+
+	fp = fopen(ACCEL_PATH "/coord", "r");
+	if (!fp)
+		return;
+
+	fgets(buf, sizeof(buf), fp);
+	sscanf(buf, "%d %d %d\n", x, y, z);
+
+	if (accel_debug->integer) {
+		Com_DPrintf("Accelerometer_ReadCoords: %d %d %d\n", *x, *y, *z);
+	}
+
+	fclose(fp);
+}
+
+static void Accelerometer_HandleEvents(void)
+{
+	int dx = 0, dy = 0;
+	int t, tmp;
+	int x, y, z;
+	static int jumpTime = 0;
+
+	t = Sys_Milliseconds();
+
+	if (!accel_angle) {
+		accel_angle = Cvar_Get("accel_angle", "45", CVAR_ARCHIVE);
+	}
+	if (!accel_debug) {
+		accel_debug = Cvar_Get("accel_debug", "0", CVAR_ARCHIVE);
+	}
+	if (!accel_jump) {
+		accel_jump = Cvar_Get("accel_jump", "-1300", CVAR_ARCHIVE);
+	}
+	if (!accel_epsilon_x) {
+		accel_epsilon_x =
+		    Cvar_Get("accel_epsilon_x", "100", CVAR_ARCHIVE);
+	}
+	if (!accel_epsilon_y) {
+		accel_epsilon_y =
+		    Cvar_Get("accel_epsilon_y", "100", CVAR_ARCHIVE);
+	}
+
+	Accelerometer_ReadCoords(&x, &y, &z);
+
+	/* only update sin and cos if the cvar's changed */
+	tmp = accel_angle->value;
+	if(tmp != accel_angle_value) {
+		/* what happened to sincosf()? */
+		accel_sin = sin(DEG2RAD(tmp));
+		accel_cos = cos(DEG2RAD(tmp));
+		accel_angle_value = tmp;
+	}
+	tmp = y * accel_cos - z * accel_sin;
+	z = z * accel_cos + y * accel_sin;
+	y = tmp;
+
+	if (accel_debug->integer) {
+		Com_DPrintf("Accelerometer_HandleEvents: y = %d\n", y);
+	}
+
+	if (accel_jump->value) {
+		float mag = sqrtf(y*y+z*z);
+		// HACK - change the sign of jump to be +ve not -ve
+		// HACK - z<0 means that lots of jerks will look like jumps
+		//        change it to < -500 or < accel_jump->value/2
+		int looks_like_a_jump = (mag > -accel_jump->value) && (z < 0);
+		if (!jumpTime && looks_like_a_jump) {
+			Com_QueueEvent(t, SE_KEY, K_SPACE, qtrue, 0, NULL);
+			jumpTime = t;
+		} else if (jumpTime && !looks_like_a_jump) {
+			Com_QueueEvent(t, SE_KEY, K_SPACE, qfalse, 0, NULL);
+			jumpTime = 0;
+		}
+	}
+
+	if (x > accel_epsilon_x->integer)
+		dx = -(x - accel_epsilon_x->integer);
+	else if (x < -accel_epsilon_x->integer)
+		dx = -(x + accel_epsilon_x->integer);
+
+	if (y > accel_epsilon_y->integer)
+		dy = -(y - accel_epsilon_y->integer);
+	else if (y < -accel_epsilon_y->integer)
+		dy = -(y + accel_epsilon_y->integer);
+
+	dx *= cl_sensitivity->value;
+	dy *= cl_sensitivity->value;
+
+	Com_QueueEvent(t, SE_ACCEL, dx, dy, 0, NULL);
+}
+
+static qboolean motionPressed = qfalse;
+
+qboolean IN_MotionPressed(void)
+{
+	return motionPressed;
+}
+
+static void HandleEvents(void)
+{
+	int key;
+	XEvent event;
+	char *p;
+	static int dx = 0, dy = 0;
+	int t = 0;		// default to 0 in case we don't set
+
+	if (!dpy)
+		return;
+
+	while (XPending(dpy)) {
+		XNextEvent(dpy, &event);
+		switch (event.type) {
+		case KeyPress:
+			t = Sys_XTimeToSysTime(event.xkey.time);
+			p = XLateKey(&event.xkey, &key);
+			if (key) {
+				Com_QueueEvent(t, SE_KEY, key, qtrue, 0, NULL);
+			}
+			if (p) {
+				while (*p) {
+					Com_QueueEvent(t, SE_CHAR, *p++, 0, 0,
+						       NULL);
+				}
+			}
+			break;
+
+		case KeyRelease:
+			t = Sys_XTimeToSysTime(event.xkey.time);
+#if 0
+			// bk001206 - handle key repeat w/o XAutRepatOn/Off
+			//            also: not done if console/menu is active.
+			// From Ryan's Fakk2.
+			// see game/q_shared.h, KEYCATCH_* . 0 == in 3d game.  
+			if (cls.keyCatchers == 0) {	// FIXME: KEYCATCH_NONE
+				if (repeated_press(&event) == qtrue)
+					continue;
+			}	// if
+#endif
+			XLateKey(&event.xkey, &key);
+
+			Com_QueueEvent(t, SE_KEY, key, qfalse, 0, NULL);
+			break;
+
+		case MotionNotify:
+			t = Sys_XTimeToSysTime(event.xkey.time);
+			dx = event.xmotion.x;
+			dy = event.xmotion.y;
+			break;
+
+		case ButtonPress:
+		case ButtonRelease:
+			t = Sys_XTimeToSysTime(event.xkey.time);
+			motionPressed = (qboolean) (event.type == ButtonPress);
+			if (Key_GetCatcher() & (KEYCATCH_CGAME | KEYCATCH_UI)) {
+				Com_QueueEvent(t, SE_KEY, K_MOUSE1,
+					       motionPressed, 0, NULL);
+			}
+			break;
+
+		case CreateNotify:
+			win_x = event.xcreatewindow.x;
+			win_y = event.xcreatewindow.y;
+			break;
+
+		case ConfigureNotify:
+			win_x = event.xconfigure.x;
+			win_y = event.xconfigure.y;
+			break;
+		}
+	}
+
+	if (motionPressed) {
+		Com_QueueEvent(t, SE_MOUSE, dx, dy, 0, NULL);
+	}
+
+	Proximity_HandleEvents();
+
+	Accelerometer_HandleEvents();
+}
+
+static Cursor CreateNullCursor(Display * display, Window root)
+{
+	Pixmap cursormask;
+	XGCValues xgc;
+	GC gc;
+	XColor dummycolour;
+	Cursor cursor;
+
+	cursormask = XCreatePixmap(display, root, 1, 1, 1 /*depth */ );
+	xgc.function = GXclear;
+	gc = XCreateGC(display, cursormask, GCFunction, &xgc);
+	XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
+	dummycolour.pixel = 0;
+	dummycolour.red = 0;
+	dummycolour.flags = 0x4;
+	cursor =
+	    XCreatePixmapCursor(display, cursormask, cursormask, &dummycolour,
+				&dummycolour, 0, 0);
+	XFreePixmap(display, cursormask);
+	XFreeGC(display, gc);
+	return cursor;
+}
+
+static void hildon_set_non_compositing(void)
+{
+	Atom atom;
+	int one = 1;
+
+	atom = XInternAtom(dpy, "_HILDON_NON_COMPOSITED_WINDOW", False);
+	XChangeProperty(dpy, win, atom, XA_INTEGER, 32, PropModeReplace,
+			(unsigned char *)&one, 1);
+}
+
+static void install_grabs(void)
+{
+	XSync(dpy, False);
+
+	hildon_set_non_compositing();
+
+	XDefineCursor(dpy, win, CreateNullCursor(dpy, win));
+
+	XGrabPointer(dpy, win, False, MOUSE_MASK, GrabModeAsync, GrabModeAsync,
+		     win, None, CurrentTime);
+
+	XGetPointerControl(dpy, &mouse_accel_numerator,
+			   &mouse_accel_denominator, &mouse_threshold);
+
+	XChangePointerControl(dpy, True, True, 1, 1, 0);
+
+	XSync(dpy, False);
+
+	mwx = glConfig.vidWidth / 2;
+	mwy = glConfig.vidHeight / 2;
+	mx = my = 0;
+
+	XGrabKeyboard(dpy, win, False, GrabModeAsync, GrabModeAsync,
+		      CurrentTime);
+
+	XSync(dpy, False);
+}
+
+static void uninstall_grabs(void)
+{
+	XChangePointerControl(dpy, qtrue, qtrue, mouse_accel_numerator,
+			      mouse_accel_denominator, mouse_threshold);
+
+	XUngrabPointer(dpy, CurrentTime);
+	XUngrabKeyboard(dpy, CurrentTime);
+
+	XUndefineCursor(dpy, win);
+}
+
+void IN_ActivateMouse(void)
+{
+	if (!mouse_avail || !dpy || !win)
+		return;
+
+	if (!mouse_active) {
+		if (!in_nograb->value)
+			install_grabs();
+		mouse_active = qtrue;
+	}
+}
+
+void IN_DeactivateMouse(void)
+{
+	if (!mouse_avail || !dpy || !win)
+		return;
+
+	if (mouse_active) {
+		if (!in_nograb->value)
+			uninstall_grabs();
+		mouse_active = qfalse;
+	}
+}
+
+void IN_Frame(void)
+{
+	qboolean loading;
+
+	HandleEvents();
+
+	// If not DISCONNECTED (main menu) or ACTIVE (in game), we're loading
+	loading = !!(cls.state != CA_DISCONNECTED && cls.state != CA_ACTIVE);
+
+	if (!r_fullscreen->integer && (Key_GetCatcher() & KEYCATCH_CONSOLE)) {
+		// Console is down in windowed mode
+		IN_DeactivateMouse();
+	} else if (!r_fullscreen->integer && loading) {
+		// Loading in windowed mode
+		IN_DeactivateMouse();
+	} else
+		IN_ActivateMouse();
+}
+
+void IN_Init(void)
+{
+	Com_DPrintf("\n------- Input Initialization -------\n");
+
+	// mouse variables
+	in_mouse = Cvar_Get("in_mouse", "1", CVAR_ARCHIVE);
+	in_nograb = Cvar_Get("in_nograb", "0", CVAR_ARCHIVE);
+
+	if (in_mouse->value) {
+		mouse_avail = qtrue;
+		IN_ActivateMouse();
+	} else {
+		IN_DeactivateMouse();
+		mouse_avail = qfalse;
+	}
+
+	Com_DPrintf("------------------------------------\n");
+}
+
+void IN_Shutdown(void)
+{
+	IN_DeactivateMouse();
+	mouse_avail = qfalse;
+}
+
+void IN_Restart(void)
+{
+	IN_Init();
+}
diff --git a/code/egl/egl_input.h b/code/egl/egl_input.h
new file mode 100644
index 0000000..e749732
--- /dev/null
+++ b/code/egl/egl_input.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2009  Nokia Corporation.  All rights reserved.
+ */
+
+#ifndef __EGL_INPUT_H__
+#define __EGL_INPUT_H__
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/param.h>
+
+#include <X11/keysym.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include <GLES/egl.h>
+#include <GLES/gl.h>
+
+#include "../qcommon/q_shared.h"
+
+extern cvar_t *in_nograb;
+qboolean IN_MotionPressed(void);
+void IN_ActivateMouse(void);
+void IN_DeactivateMouse(void);
+void IN_Frame(void);
+void IN_Init(void);
+void IN_Shutdown(void);
+void IN_Restart(void);
+
+#endif
diff --git a/code/egl/sdl_snd.c b/code/egl/sdl_snd.c
new file mode 100644
index 0000000..a131db7
--- /dev/null
+++ b/code/egl/sdl_snd.c
@@ -0,0 +1,299 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Quake III Arena source code; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+===========================================================================
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifdef USE_LOCAL_HEADERS
+#	include "SDL.h"
+#else
+#	include <SDL.h>
+#endif
+
+#include "../qcommon/q_shared.h"
+#include "../client/snd_local.h"
+
+qboolean snd_inited = qfalse;
+
+cvar_t *s_sdlBits;
+cvar_t *s_sdlSpeed;
+cvar_t *s_sdlChannels;
+cvar_t *s_sdlDevSamps;
+cvar_t *s_sdlMixSamps;
+
+/* The audio callback. All the magic happens here. */
+static int dmapos = 0;
+static int dmasize = 0;
+
+/*
+===============
+SNDDMA_AudioCallback
+===============
+*/
+static void SNDDMA_AudioCallback(void *userdata, Uint8 *stream, int len)
+{
+	int pos = (dmapos * (dma.samplebits/8));
+	if (pos >= dmasize)
+		dmapos = pos = 0;
+
+	if (!snd_inited)  /* shouldn't happen, but just in case... */
+	{
+		memset(stream, '\0', len);
+		return;
+	}
+	else
+	{
+		int tobufend = dmasize - pos;  /* bytes to buffer's end. */
+		int len1 = len;
+		int len2 = 0;
+
+		if (len1 > tobufend)
+		{
+			len1 = tobufend;
+			len2 = len - len1;
+		}
+		memcpy(stream, dma.buffer + pos, len1);
+		if (len2 <= 0)
+			dmapos += (len1 / (dma.samplebits/8));
+		else  /* wraparound? */
+		{
+			memcpy(stream+len1, dma.buffer, len2);
+			dmapos = (len2 / (dma.samplebits/8));
+		}
+	}
+
+	if (dmapos >= dmasize)
+		dmapos = 0;
+}
+
+static struct
+{
+	Uint16	enumFormat;
+	char		*stringFormat;
+} formatToStringTable[ ] =
+{
+	{ AUDIO_U8,     "AUDIO_U8" },
+	{ AUDIO_S8,     "AUDIO_S8" },
+	{ AUDIO_U16LSB, "AUDIO_U16LSB" },
+	{ AUDIO_S16LSB, "AUDIO_S16LSB" },
+	{ AUDIO_U16MSB, "AUDIO_U16MSB" },
+	{ AUDIO_S16MSB, "AUDIO_S16MSB" }
+};
+
+static int formatToStringTableSize =
+  sizeof( formatToStringTable ) / sizeof( formatToStringTable[ 0 ] );
+
+/*
+===============
+SNDDMA_PrintAudiospec
+===============
+*/
+static void SNDDMA_PrintAudiospec(const char *str, const SDL_AudioSpec *spec)
+{
+	int		i;
+	char	*fmt = NULL;
+
+	Com_Printf("%s:\n", str);
+
+	for( i = 0; i < formatToStringTableSize; i++ ) {
+		if( spec->format == formatToStringTable[ i ].enumFormat ) {
+			fmt = formatToStringTable[ i ].stringFormat;
+		}
+	}
+
+	if( fmt ) {
+		Com_Printf( "  Format:   %s\n", fmt );
+	} else {
+		Com_Printf( "  Format:   " S_COLOR_RED "UNKNOWN\n");
+	}
+
+	Com_Printf( "  Freq:     %d\n", (int) spec->freq );
+	Com_Printf( "  Samples:  %d\n", (int) spec->samples );
+	Com_Printf( "  Channels: %d\n", (int) spec->channels );
+}
+
+/*
+===============
+SNDDMA_Init
+===============
+*/
+qboolean SNDDMA_Init(void)
+{
+	char drivername[128];
+	SDL_AudioSpec desired;
+	SDL_AudioSpec obtained;
+	int tmp;
+
+	if (snd_inited)
+		return qtrue;
+
+	if (!s_sdlBits) {
+		s_sdlBits = Cvar_Get("s_sdlBits", "16", CVAR_ARCHIVE);
+		s_sdlSpeed = Cvar_Get("s_sdlSpeed", "0", CVAR_ARCHIVE);
+		s_sdlChannels = Cvar_Get("s_sdlChannels", "2", CVAR_ARCHIVE);
+		s_sdlDevSamps = Cvar_Get("s_sdlDevSamps", "0", CVAR_ARCHIVE);
+		s_sdlMixSamps = Cvar_Get("s_sdlMixSamps", "0", CVAR_ARCHIVE);
+	}
+
+	Com_Printf( "SDL_Init( SDL_INIT_AUDIO )... " );
+
+	if (!SDL_WasInit(SDL_INIT_AUDIO))
+	{
+		if (SDL_Init(SDL_INIT_AUDIO) == -1)
+		{
+			Com_Printf( "FAILED (%s)\n", SDL_GetError( ) );
+			return qfalse;
+		}
+	}
+
+	Com_Printf( "OK\n" );
+
+	if (SDL_AudioDriverName(drivername, sizeof (drivername)) == NULL)
+		strcpy(drivername, "(UNKNOWN)");
+	Com_Printf("SDL audio driver is \"%s\".\n", drivername);
+
+	memset(&desired, '\0', sizeof (desired));
+	memset(&obtained, '\0', sizeof (obtained));
+
+	tmp = ((int) s_sdlBits->value);
+	if ((tmp != 16) && (tmp != 8))
+		tmp = 16;
+
+	desired.freq = (int) s_sdlSpeed->value;
+	if(!desired.freq) desired.freq = 22050;
+	desired.format = ((tmp == 16) ? AUDIO_S16SYS : AUDIO_U8);
+
+	// I dunno if this is the best idea, but I'll give it a try...
+	//  should probably check a cvar for this...
+	if (s_sdlDevSamps->value)
+		desired.samples = s_sdlDevSamps->value;
+	else
+	{
+		// just pick a sane default.
+		if (desired.freq <= 11025)
+			desired.samples = 256;
+		else if (desired.freq <= 22050)
+			desired.samples = 512;
+		else if (desired.freq <= 44100)
+			desired.samples = 1024;
+		else
+			desired.samples = 2048;  // (*shrug*)
+	}
+
+	desired.channels = (int) s_sdlChannels->value;
+	desired.callback = SNDDMA_AudioCallback;
+
+	if (SDL_OpenAudio(&desired, &obtained) == -1)
+	{
+		Com_Printf("SDL_OpenAudio() failed: %s\n", SDL_GetError());
+		SDL_QuitSubSystem(SDL_INIT_AUDIO);
+		return qfalse;
+	}
+
+	SNDDMA_PrintAudiospec("SDL_AudioSpec", &obtained);
+
+	// dma.samples needs to be big, or id's mixer will just refuse to
+	//  work at all; we need to keep it significantly bigger than the
+	//  amount of SDL callback samples, and just copy a little each time
+	//  the callback runs.
+	// 32768 is what the OSS driver filled in here on my system. I don't
+	//  know if it's a good value overall, but at least we know it's
+	//  reasonable...this is why I let the user override.
+	tmp = s_sdlMixSamps->value;
+	if (!tmp)
+		tmp = (obtained.samples * obtained.channels) * 10;
+
+	if (tmp & (tmp - 1))  // not a power of two? Seems to confuse something.
+	{
+		int val = 1;
+		while (val < tmp)
+			val <<= 1;
+
+		tmp = val;
+	}
+
+	dmapos = 0;
+	dma.samplebits = obtained.format & 0xFF;  // first byte of format is bits.
+	dma.channels = obtained.channels;
+	dma.samples = tmp;
+	dma.submission_chunk = 1;
+	dma.speed = obtained.freq;
+	dmasize = (dma.samples * (dma.samplebits/8));
+	dma.buffer = calloc(1, dmasize);
+
+	Com_Printf("Starting SDL audio callback...\n");
+	SDL_PauseAudio(0);  // start callback.
+
+	Com_Printf("SDL audio initialized.\n");
+	snd_inited = qtrue;
+	return qtrue;
+}
+
+/*
+===============
+SNDDMA_GetDMAPos
+===============
+*/
+int SNDDMA_GetDMAPos(void)
+{
+	return dmapos;
+}
+
+/*
+===============
+SNDDMA_Shutdown
+===============
+*/
+void SNDDMA_Shutdown(void)
+{
+	Com_Printf("Closing SDL audio device...\n");
+	SDL_PauseAudio(1);
+	SDL_CloseAudio();
+	SDL_QuitSubSystem(SDL_INIT_AUDIO);
+	free(dma.buffer);
+	dma.buffer = NULL;
+	dmapos = dmasize = 0;
+	snd_inited = qfalse;
+	Com_Printf("SDL audio device shut down.\n");
+}
+
+/*
+===============
+SNDDMA_Submit
+
+Send sound to device if buffer isn't really the dma buffer
+===============
+*/
+void SNDDMA_Submit(void)
+{
+	SDL_UnlockAudio();
+}
+
+/*
+===============
+SNDDMA_BeginPainting
+===============
+*/
+void SNDDMA_BeginPainting (void)
+{
+	SDL_LockAudio();
+}
diff --git a/code/q3_ui/ui_atoms.c b/code/q3_ui/ui_atoms.c
index c798bdd..aa579ee 100644
--- a/code/q3_ui/ui_atoms.c
+++ b/code/q3_ui/ui_atoms.c
@@ -873,18 +873,18 @@ void UI_MouseEvent( int dx, int dy )
 {
 	int				i;
 	menucommon_s*	m;
-
+	//printf(__FILE__ " UI_MouseEvent(%d,%d)\n", dx, dy);
 	if (!uis.activemenu)
 		return;
 
 	// update mouse screen position
-	uis.cursorx += dx;
+	uis.cursorx = dx - (uis.glconfig.vidWidth - SCREEN_WIDTH) / 2;
 	if (uis.cursorx < 0)
 		uis.cursorx = 0;
 	else if (uis.cursorx > SCREEN_WIDTH)
 		uis.cursorx = SCREEN_WIDTH;
 
-	uis.cursory += dy;
+	uis.cursory = dy - (uis.glconfig.vidHeight - SCREEN_HEIGHT) / 2;
 	if (uis.cursory < 0)
 		uis.cursory = 0;
 	else if (uis.cursory > SCREEN_HEIGHT)
diff --git a/code/qcommon/common.c b/code/qcommon/common.c
index e8a95a5..ac91a64 100644
--- a/code/qcommon/common.c
+++ b/code/qcommon/common.c
@@ -2232,6 +2232,9 @@ int Com_EventLoop( void ) {
 		case SE_MOUSE:
 			CL_MouseEvent( ev.evValue, ev.evValue2, ev.evTime );
 			break;
+		case SE_ACCEL:
+			CL_AccelEvent( ev.evValue, ev.evValue2, ev.evTime );
+			break;
 		case SE_JOYSTICK_AXIS:
 			CL_JoystickEvent( ev.evValue, ev.evValue2, ev.evTime );
 			break;
diff --git a/code/qcommon/q_math.c b/code/qcommon/q_math.c
index 80c9f8e..3c8ad82 100644
--- a/code/qcommon/q_math.c
+++ b/code/qcommon/q_math.c
@@ -495,7 +495,7 @@ void VectorRotate( vec3_t in, vec3_t matrix[3], vec3_t out )
 
 //============================================================================
 
-#if !idppc
+#if !idppc && !idarm
 /*
 ** float q_rsqrt( float number )
 */
diff --git a/code/qcommon/q_platform.h b/code/qcommon/q_platform.h
index ed5d907..eb2f4d8 100644
--- a/code/qcommon/q_platform.h
+++ b/code/qcommon/q_platform.h
@@ -30,6 +30,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #define idppc 0
 #define idppc_altivec 0
 #define idsparc 0
+#define idarm 0
 
 #else
 
@@ -65,6 +66,12 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #define idsparc 0
 #endif
 
+#if defined(__ARMEL__)
+#define idarm 1
+#else
+#define idarm 0
+#endif
+
 #endif
 
 #ifndef __ASM_I386__ // don't include the C bits if included from qasm.h
diff --git a/code/qcommon/q_shared.h b/code/qcommon/q_shared.h
index 99edd69..5cf9f9f 100644
--- a/code/qcommon/q_shared.h
+++ b/code/qcommon/q_shared.h
@@ -417,6 +417,16 @@ static ID_INLINE float Q_fabs(float x) {
 #define Q_fabs __fabsf
 #endif
 
+#elif idarm
+static ID_INLINE float Q_rsqrt(float number)
+{
+	return 1.0 / sqrtf(number);
+}
+
+static ID_INLINE float Q_fabs(float x)
+{
+	return fabsf(x);
+}
 #else
 float Q_fabs( float f );
 float Q_rsqrt( float f );		// reciprocal square root
diff --git a/code/qcommon/qcommon.h b/code/qcommon/qcommon.h
index 34c8fac..0facb9b 100644
--- a/code/qcommon/qcommon.h
+++ b/code/qcommon/qcommon.h
@@ -759,7 +759,8 @@ typedef enum {
 	SE_NONE = 0,	// evTime is still valid
 	SE_KEY,		// evValue is a key code, evValue2 is the down flag
 	SE_CHAR,	// evValue is an ascii char
-	SE_MOUSE,	// evValue and evValue2 are reletive signed x / y moves
+	SE_MOUSE,	// evValue and evValue2 are relative signed x / y moves
+	SE_ACCEL,
 	SE_JOYSTICK_AXIS,	// evValue is an axis number and evValue2 is the current state (-127 to 127)
 	SE_CONSOLE,	// evPtr is a char*
 	SE_PACKET	// evPtr is a netadr_t followed by data bytes to evPtrLength
@@ -934,6 +935,7 @@ void CL_CharEvent( int key );
 // char events are for field typing, not game control
 
 void CL_MouseEvent( int dx, int dy, int time );
+void CL_AccelEvent( int dx, int dy, int time );
 
 void CL_JoystickEvent( int axis, int value, int time );
 
diff --git a/code/renderer/qgl.h b/code/renderer/qgl.h
index 5296193..ced454c 100644
--- a/code/renderer/qgl.h
+++ b/code/renderer/qgl.h
@@ -26,355 +26,134 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #ifndef __QGL_H__
 #define __QGL_H__
 
-#ifdef USE_LOCAL_HEADERS
-#	include "SDL_opengl.h"
+#if defined( __LINT__ )
+
+#include <GL/gl.h>
+
+#elif defined( _WIN32 )
+
+#pragma warning (disable: 4201)
+#pragma warning (disable: 4214)
+#pragma warning (disable: 4514)
+#pragma warning (disable: 4032)
+#pragma warning (disable: 4201)
+#pragma warning (disable: 4214)
+#include <windows.h>
+#include <gl/gl.h>
+
+#elif defined(MACOS_X)
+
+#include "macosx_glimp.h"
+
+#elif defined( __linux__ )
+
+#include <GLES/egl.h>
+#include <GLES/gl.h>
+
+#include "../egl/egl_glimp.h"
+
+#elif defined( __FreeBSD__ ) // rb010123
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+#if defined(__FX__)
+#include <GL/fxmesa.h>
+#endif
+
 #else
-#	include <SDL_opengl.h>
+
+#include <gl.h>
+
+#endif
+
+#ifndef APIENTRY
+#define APIENTRY
+#endif
+#ifndef WINAPI
+#define WINAPI
 #endif
 
-extern void (APIENTRYP qglActiveTextureARB) (GLenum texture);
-extern void (APIENTRYP qglClientActiveTextureARB) (GLenum texture);
-extern void (APIENTRYP qglMultiTexCoord2fARB) (GLenum target, GLfloat s, GLfloat t);
 
-extern void (APIENTRYP qglLockArraysEXT) (GLint first, GLsizei count);
-extern void (APIENTRYP qglUnlockArraysEXT) (void);
+//===========================================================================
+
+/*
+** multitexture extension definitions
+*/
+#define GL_ACTIVE_TEXTURE_ARB               0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE_ARB        0x84E1
+#define GL_MAX_ACTIVE_TEXTURES_ARB          0x84E2
+
+#define GL_TEXTURE0_ARB                     0x84C0
+#define GL_TEXTURE1_ARB                     0x84C1
+#define GL_TEXTURE2_ARB                     0x84C2
+#define GL_TEXTURE3_ARB                     0x84C3
+
+// NOTE: some Linux platforms would need those prototypes
+#if defined(MACOS_X)
+typedef void (APIENTRY * PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (APIENTRY * PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRY * PFNGLACTIVETEXTUREARBPROC) (GLenum target);
+typedef void (APIENTRY * PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum target);
+#endif
+
+// TTimo - VC7 / XP ?
+#ifdef WIN32
+typedef void (APIENTRY * PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t);
+typedef void (APIENTRY * PFNGLACTIVETEXTUREARBPROC) (GLenum target);
+typedef void (APIENTRY * PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum target);
+#endif
+
+/*
+** extension constants
+*/
+
+
+// S3TC compression constants
+#define GL_RGB_S3TC							0x83A0
+#define GL_RGB4_S3TC						0x83A1
+
+
+// extensions will be function pointers on all platforms
+
+extern	void ( APIENTRY * qglMultiTexCoord2fARB )( GLenum texture, GLfloat s, GLfloat t );
+extern	void ( APIENTRY * qglActiveTextureARB )( GLenum texture );
+extern	void ( APIENTRY * qglClientActiveTextureARB )( GLenum texture );
 
+extern	void ( APIENTRY * qglLockArraysEXT) (GLint, GLint);
+extern	void ( APIENTRY * qglUnlockArraysEXT) (void);
 
 //===========================================================================
 
-#define qglAccum glAccum
-#define qglAlphaFunc glAlphaFunc
-#define qglAreTexturesResident glAreTexturesResident
-#define qglArrayElement glArrayElement
-#define qglBegin glBegin
-#define qglBindTexture glBindTexture
-#define qglBitmap glBitmap
-#define qglBlendFunc glBlendFunc
-#define qglCallList glCallList
-#define qglCallLists glCallLists
-#define qglClear glClear
-#define qglClearAccum glClearAccum
-#define qglClearColor glClearColor
-#define qglClearDepth glClearDepth
-#define qglClearIndex glClearIndex
-#define qglClearStencil glClearStencil
-#define qglClipPlane glClipPlane
-#define qglColor3b glColor3b
-#define qglColor3bv glColor3bv
-#define qglColor3d glColor3d
-#define qglColor3dv glColor3dv
-#define qglColor3f glColor3f
-#define qglColor3fv glColor3fv
-#define qglColor3i glColor3i
-#define qglColor3iv glColor3iv
-#define qglColor3s glColor3s
-#define qglColor3sv glColor3sv
-#define qglColor3ub glColor3ub
-#define qglColor3ubv glColor3ubv
-#define qglColor3ui glColor3ui
-#define qglColor3uiv glColor3uiv
-#define qglColor3us glColor3us
-#define qglColor3usv glColor3usv
-#define qglColor4b glColor4b
-#define qglColor4bv glColor4bv
-#define qglColor4d glColor4d
-#define qglColor4dv glColor4dv
-#define qglColor4f glColor4f
-#define qglColor4fv glColor4fv
-#define qglColor4i glColor4i
-#define qglColor4iv glColor4iv
-#define qglColor4s glColor4s
-#define qglColor4sv glColor4sv
-#define qglColor4ub glColor4ub
-#define qglColor4ubv glColor4ubv
-#define qglColor4ui glColor4ui
-#define qglColor4uiv glColor4uiv
-#define qglColor4us glColor4us
-#define qglColor4usv glColor4usv
-#define qglColorMask glColorMask
-#define qglColorMaterial glColorMaterial
-#define qglColorPointer glColorPointer
-#define qglCopyPixels glCopyPixels
-#define qglCopyTexImage1D glCopyTexImage1D
-#define qglCopyTexImage2D glCopyTexImage2D
-#define qglCopyTexSubImage1D glCopyTexSubImage1D
-#define qglCopyTexSubImage2D glCopyTexSubImage2D
-#define qglCullFace glCullFace
-#define qglDeleteLists glDeleteLists
-#define qglDeleteTextures glDeleteTextures
-#define qglDepthFunc glDepthFunc
-#define qglDepthMask glDepthMask
-#define qglDepthRange glDepthRange
-#define qglDisable glDisable
-#define qglDisableClientState glDisableClientState
-#define qglDrawArrays glDrawArrays
-#define qglDrawBuffer glDrawBuffer
-#define qglDrawElements glDrawElements
-#define qglDrawPixels glDrawPixels
-#define qglEdgeFlag glEdgeFlag
-#define qglEdgeFlagPointer glEdgeFlagPointer
-#define qglEdgeFlagv glEdgeFlagv
-#define qglEnable glEnable
-#define qglEnableClientState glEnableClientState
-#define qglEnd glEnd
-#define qglEndList glEndList
-#define qglEvalCoord1d glEvalCoord1d
-#define qglEvalCoord1dv glEvalCoord1dv
-#define qglEvalCoord1f glEvalCoord1f
-#define qglEvalCoord1fv glEvalCoord1fv
-#define qglEvalCoord2d glEvalCoord2d
-#define qglEvalCoord2dv glEvalCoord2dv
-#define qglEvalCoord2f glEvalCoord2f
-#define qglEvalCoord2fv glEvalCoord2fv
-#define qglEvalMesh1 glEvalMesh1
-#define qglEvalMesh2 glEvalMesh2
-#define qglEvalPoint1 glEvalPoint1
-#define qglEvalPoint2 glEvalPoint2
-#define qglFeedbackBuffer glFeedbackBuffer
-#define qglFinish glFinish
-#define qglFlush glFlush
-#define qglFogf glFogf
-#define qglFogfv glFogfv
-#define qglFogi glFogi
-#define qglFogiv glFogiv
-#define qglFrontFace glFrontFace
-#define qglFrustum glFrustum
-#define qglGenLists glGenLists
-#define qglGenTextures glGenTextures
-#define qglGetBooleanv glGetBooleanv
-#define qglGetClipPlane glGetClipPlane
-#define qglGetDoublev glGetDoublev
-#define qglGetError glGetError
-#define qglGetFloatv glGetFloatv
-#define qglGetIntegerv glGetIntegerv
-#define qglGetLightfv glGetLightfv
-#define qglGetLightiv glGetLightiv
-#define qglGetMapdv glGetMapdv
-#define qglGetMapfv glGetMapfv
-#define qglGetMapiv glGetMapiv
-#define qglGetMaterialfv glGetMaterialfv
-#define qglGetMaterialiv glGetMaterialiv
-#define qglGetPixelMapfv glGetPixelMapfv
-#define qglGetPixelMapuiv glGetPixelMapuiv
-#define qglGetPixelMapusv glGetPixelMapusv
-#define qglGetPointerv glGetPointerv
-#define qglGetPolygonStipple glGetPolygonStipple
-#define qglGetString glGetString
-#define qglGetTexGendv glGetTexGendv
-#define qglGetTexGenfv glGetTexGenfv
-#define qglGetTexGeniv glGetTexGeniv
-#define qglGetTexImage glGetTexImage
-#define qglGetTexLevelParameterfv glGetTexLevelParameterfv
-#define qglGetTexLevelParameteriv glGetTexLevelParameteriv
-#define qglGetTexParameterfv glGetTexParameterfv
-#define qglGetTexParameteriv glGetTexParameteriv
-#define qglHint glHint
-#define qglIndexMask glIndexMask
-#define qglIndexPointer glIndexPointer
-#define qglIndexd glIndexd
-#define qglIndexdv glIndexdv
-#define qglIndexf glIndexf
-#define qglIndexfv glIndexfv
-#define qglIndexi glIndexi
-#define qglIndexiv glIndexiv
-#define qglIndexs glIndexs
-#define qglIndexsv glIndexsv
-#define qglIndexub glIndexub
-#define qglIndexubv glIndexubv
-#define qglInitNames glInitNames
-#define qglInterleavedArrays glInterleavedArrays
-#define qglIsEnabled glIsEnabled
-#define qglIsList glIsList
-#define qglIsTexture glIsTexture
-#define qglLightModelf glLightModelf
-#define qglLightModelfv glLightModelfv
-#define qglLightModeli glLightModeli
-#define qglLightModeliv glLightModeliv
-#define qglLightf glLightf
-#define qglLightfv glLightfv
-#define qglLighti glLighti
-#define qglLightiv glLightiv
-#define qglLineStipple glLineStipple
-#define qglLineWidth glLineWidth
-#define qglListBase glListBase
-#define qglLoadIdentity glLoadIdentity
-#define qglLoadMatrixd glLoadMatrixd
-#define qglLoadMatrixf glLoadMatrixf
-#define qglLoadName glLoadName
-#define qglLogicOp glLogicOp
-#define qglMap1d glMap1d
-#define qglMap1f glMap1f
-#define qglMap2d glMap2d
-#define qglMap2f glMap2f
-#define qglMapGrid1d glMapGrid1d
-#define qglMapGrid1f glMapGrid1f
-#define qglMapGrid2d glMapGrid2d
-#define qglMapGrid2f glMapGrid2f
-#define qglMaterialf glMaterialf
-#define qglMaterialfv glMaterialfv
-#define qglMateriali glMateriali
-#define qglMaterialiv glMaterialiv
-#define qglMatrixMode glMatrixMode
-#define qglMultMatrixd glMultMatrixd
-#define qglMultMatrixf glMultMatrixf
-#define qglNewList glNewList
-#define qglNormal3b glNormal3b
-#define qglNormal3bv glNormal3bv
-#define qglNormal3d glNormal3d
-#define qglNormal3dv glNormal3dv
-#define qglNormal3f glNormal3f
-#define qglNormal3fv glNormal3fv
-#define qglNormal3i glNormal3i
-#define qglNormal3iv glNormal3iv
-#define qglNormal3s glNormal3s
-#define qglNormal3sv glNormal3sv
-#define qglNormalPointer glNormalPointer
-#define qglOrtho glOrtho
-#define qglPassThrough glPassThrough
-#define qglPixelMapfv glPixelMapfv
-#define qglPixelMapuiv glPixelMapuiv
-#define qglPixelMapusv glPixelMapusv
-#define qglPixelStoref glPixelStoref
-#define qglPixelStorei glPixelStorei
-#define qglPixelTransferf glPixelTransferf
-#define qglPixelTransferi glPixelTransferi
-#define qglPixelZoom glPixelZoom
-#define qglPointSize glPointSize
-#define qglPolygonMode glPolygonMode
-#define qglPolygonOffset glPolygonOffset
-#define qglPolygonStipple glPolygonStipple
-#define qglPopAttrib glPopAttrib
-#define qglPopClientAttrib glPopClientAttrib
-#define qglPopMatrix glPopMatrix
-#define qglPopName glPopName
-#define qglPrioritizeTextures glPrioritizeTextures
-#define qglPushAttrib glPushAttrib
-#define qglPushClientAttrib glPushClientAttrib
-#define qglPushMatrix glPushMatrix
-#define qglPushName glPushName
-#define qglRasterPos2d glRasterPos2d
-#define qglRasterPos2dv glRasterPos2dv
-#define qglRasterPos2f glRasterPos2f
-#define qglRasterPos2fv glRasterPos2fv
-#define qglRasterPos2i glRasterPos2i
-#define qglRasterPos2iv glRasterPos2iv
-#define qglRasterPos2s glRasterPos2s
-#define qglRasterPos2sv glRasterPos2sv
-#define qglRasterPos3d glRasterPos3d
-#define qglRasterPos3dv glRasterPos3dv
-#define qglRasterPos3f glRasterPos3f
-#define qglRasterPos3fv glRasterPos3fv
-#define qglRasterPos3i glRasterPos3i
-#define qglRasterPos3iv glRasterPos3iv
-#define qglRasterPos3s glRasterPos3s
-#define qglRasterPos3sv glRasterPos3sv
-#define qglRasterPos4d glRasterPos4d
-#define qglRasterPos4dv glRasterPos4dv
-#define qglRasterPos4f glRasterPos4f
-#define qglRasterPos4fv glRasterPos4fv
-#define qglRasterPos4i glRasterPos4i
-#define qglRasterPos4iv glRasterPos4iv
-#define qglRasterPos4s glRasterPos4s
-#define qglRasterPos4sv glRasterPos4sv
-#define qglReadBuffer glReadBuffer
-#define qglReadPixels glReadPixels
-#define qglRectd glRectd
-#define qglRectdv glRectdv
-#define qglRectf glRectf
-#define qglRectfv glRectfv
-#define qglRecti glRecti
-#define qglRectiv glRectiv
-#define qglRects glRects
-#define qglRectsv glRectsv
-#define qglRenderMode glRenderMode
-#define qglRotated glRotated
-#define qglRotatef glRotatef
-#define qglScaled glScaled
-#define qglScalef glScalef
-#define qglScissor glScissor
-#define qglSelectBuffer glSelectBuffer
-#define qglShadeModel glShadeModel
-#define qglStencilFunc glStencilFunc
-#define qglStencilMask glStencilMask
-#define qglStencilOp glStencilOp
-#define qglTexCoord1d glTexCoord1d
-#define qglTexCoord1dv glTexCoord1dv
-#define qglTexCoord1f glTexCoord1f
-#define qglTexCoord1fv glTexCoord1fv
-#define qglTexCoord1i glTexCoord1i
-#define qglTexCoord1iv glTexCoord1iv
-#define qglTexCoord1s glTexCoord1s
-#define qglTexCoord1sv glTexCoord1sv
-#define qglTexCoord2d glTexCoord2d
-#define qglTexCoord2dv glTexCoord2dv
-#define qglTexCoord2f glTexCoord2f
-#define qglTexCoord2fv glTexCoord2fv
-#define qglTexCoord2i glTexCoord2i
-#define qglTexCoord2iv glTexCoord2iv
-#define qglTexCoord2s glTexCoord2s
-#define qglTexCoord2sv glTexCoord2sv
-#define qglTexCoord3d glTexCoord3d
-#define qglTexCoord3dv glTexCoord3dv
-#define qglTexCoord3f glTexCoord3f
-#define qglTexCoord3fv glTexCoord3fv
-#define qglTexCoord3i glTexCoord3i
-#define qglTexCoord3iv glTexCoord3iv
-#define qglTexCoord3s glTexCoord3s
-#define qglTexCoord3sv glTexCoord3sv
-#define qglTexCoord4d glTexCoord4d
-#define qglTexCoord4dv glTexCoord4dv
-#define qglTexCoord4f glTexCoord4f
-#define qglTexCoord4fv glTexCoord4fv
-#define qglTexCoord4i glTexCoord4i
-#define qglTexCoord4iv glTexCoord4iv
-#define qglTexCoord4s glTexCoord4s
-#define qglTexCoord4sv glTexCoord4sv
-#define qglTexCoordPointer glTexCoordPointer
-#define qglTexEnvf glTexEnvf
-#define qglTexEnvfv glTexEnvfv
-#define qglTexEnvi glTexEnvi
-#define qglTexEnviv glTexEnviv
-#define qglTexGend glTexGend
-#define qglTexGendv glTexGendv
-#define qglTexGenf glTexGenf
-#define qglTexGenfv glTexGenfv
-#define qglTexGeni glTexGeni
-#define qglTexGeniv glTexGeniv
-#define qglTexImage1D glTexImage1D
-#define qglTexImage2D glTexImage2D
-#define qglTexParameterf glTexParameterf
-#define qglTexParameterfv glTexParameterfv
-#define qglTexParameteri glTexParameteri
-#define qglTexParameteriv glTexParameteriv
-#define qglTexSubImage1D glTexSubImage1D
-#define qglTexSubImage2D glTexSubImage2D
-#define qglTranslated glTranslated
-#define qglTranslatef glTranslatef
-#define qglVertex2d glVertex2d
-#define qglVertex2dv glVertex2dv
-#define qglVertex2f glVertex2f
-#define qglVertex2fv glVertex2fv
-#define qglVertex2i glVertex2i
-#define qglVertex2iv glVertex2iv
-#define qglVertex2s glVertex2s
-#define qglVertex2sv glVertex2sv
-#define qglVertex3d glVertex3d
-#define qglVertex3dv glVertex3dv
-#define qglVertex3f glVertex3f
-#define qglVertex3fv glVertex3fv
-#define qglVertex3i glVertex3i
-#define qglVertex3iv glVertex3iv
-#define qglVertex3s glVertex3s
-#define qglVertex3sv glVertex3sv
-#define qglVertex4d glVertex4d
-#define qglVertex4dv glVertex4dv
-#define qglVertex4f glVertex4f
-#define qglVertex4fv glVertex4fv
-#define qglVertex4i glVertex4i
-#define qglVertex4iv glVertex4iv
-#define qglVertex4s glVertex4s
-#define qglVertex4sv glVertex4sv
-#define qglVertexPointer glVertexPointer
-#define qglViewport glViewport
+#include "../egl/qgl.h"
 
 #endif
diff --git a/code/renderer/tr_backend.c b/code/renderer/tr_backend.c
index 30c9368..ba80616 100644
--- a/code/renderer/tr_backend.c
+++ b/code/renderer/tr_backend.c
@@ -327,6 +327,7 @@ void GL_State( unsigned long stateBits )
 	//
 	// fill/line mode
 	//
+#if !defined(NOKIA)
 	if ( diff & GLS_POLYMODE_LINE )
 	{
 		if ( stateBits & GLS_POLYMODE_LINE )
@@ -338,6 +339,7 @@ void GL_State( unsigned long stateBits )
 			qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
 		}
 	}
+#endif
 
 	//
 	// depthtest
@@ -488,7 +490,7 @@ void RB_BeginDrawingView (void) {
 	// clip to the plane of the portal
 	if ( backEnd.viewParms.isPortal ) {
 		float	plane[4];
-		double	plane2[4];
+		float	plane2[4];
 
 		plane[0] = backEnd.viewParms.portalPlane.normal[0];
 		plane[1] = backEnd.viewParms.portalPlane.normal[1];
@@ -501,7 +503,7 @@ void RB_BeginDrawingView (void) {
 		plane2[3] = DotProduct (plane, backEnd.viewParms.or.origin) - plane[3];
 
 		qglLoadMatrixf( s_flipMatrix );
-		qglClipPlane (GL_CLIP_PLANE0, plane2);
+		qglClipPlanef (GL_CLIP_PLANE0, plane2);
 		qglEnable (GL_CLIP_PLANE0);
 	} else {
 		qglDisable (GL_CLIP_PLANE0);
@@ -644,7 +646,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
 					}
 
 					if(!oldDepthRange)
-						qglDepthRange (0, 0.3);
+						qglDepthRangef (0, 0.3);
 				}
 				else
 				{
@@ -655,7 +657,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
 						qglMatrixMode(GL_MODELVIEW);
 					}
 
-					qglDepthRange (0, 1);
+					qglDepthRangef (0, 1);
 				}
 
 				oldDepthRange = depthRange;
@@ -679,7 +681,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
 	// go back to the world modelview matrix
 	qglLoadMatrixf( backEnd.viewParms.world.modelMatrix );
 	if ( depthRange ) {
-		qglDepthRange (0, 1);
+		qglDepthRangef (0, 1);
 	}
 
 #if 0
@@ -715,7 +717,7 @@ void	RB_SetGL2D (void) {
 	qglScissor( 0, 0, glConfig.vidWidth, glConfig.vidHeight );
 	qglMatrixMode(GL_PROJECTION);
     qglLoadIdentity ();
-	qglOrtho (0, glConfig.vidWidth, glConfig.vidHeight, 0, 0, 1);
+	qglOrthof (0, glConfig.vidWidth, glConfig.vidHeight, 0, 0, 1);
 	qglMatrixMode(GL_MODELVIEW);
     qglLoadIdentity ();
 
@@ -744,6 +746,9 @@ Used for cinematics.
 void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) {
 	int			i, j;
 	int			start, end;
+	vec2_t texcoords[4];
+	vec2_t verts[4];
+	glIndex_t indicies[6] = { 0, 1, 2, 0, 3, 2 };
 
 	if ( !tr.registered ) {
 		return;
@@ -773,7 +778,7 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
 	if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) {
 		tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols;
 		tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows;
-		qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
+		qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
 		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
 		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
 		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
@@ -793,18 +798,23 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
 
 	RB_SetGL2D();
 
-	qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight );
-
-	qglBegin (GL_QUADS);
-	qglTexCoord2f ( 0.5f / cols,  0.5f / rows );
-	qglVertex2f (x, y);
-	qglTexCoord2f ( ( cols - 0.5f ) / cols ,  0.5f / rows );
-	qglVertex2f (x+w, y);
-	qglTexCoord2f ( ( cols - 0.5f ) / cols, ( rows - 0.5f ) / rows );
-	qglVertex2f (x+w, y+h);
-	qglTexCoord2f ( 0.5f / cols, ( rows - 0.5f ) / rows );
-	qglVertex2f (x, y+h);
-	qglEnd ();
+	glColor4f( tr.identityLight, tr.identityLight, tr.identityLight, 1.0f );
+
+	verts[0][0] = x;  verts[0][1] = y;
+	verts[1][0] = x+w;  verts[1][1] = y;
+	verts[2][0] = x+w;  verts[2][1] = y+h;
+	verts[3][0] = x;  verts[3][1] = y+h;
+	
+	texcoords[0][0] = 0.5f/cols;      texcoords[0][1] = 0.5f/rows;
+	texcoords[1][0] = (cols-0.5f)/cols;   texcoords[1][1] = 0.5f/rows;
+	texcoords[2][0] = (cols-0.5f)/cols;   texcoords[2][1] = (rows-0.5f)/rows;
+	texcoords[3][0] = 0.5f/cols;      texcoords[3][1] = (rows-0.5f)/rows;
+	
+	qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
+	qglTexCoordPointer( 2, GL_FLOAT, 0, texcoords );
+	qglVertexPointer  ( 2, GL_FLOAT, 0, verts );
+	qglDrawElements( GL_TRIANGLE_STRIP, 6, GL_INDEX_TYPE, indicies );
+	qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
 }
 
 void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) {
@@ -815,7 +825,7 @@ void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int
 	if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) {
 		tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols;
 		tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows;
-		qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
+		qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
 		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
 		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
 		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
@@ -987,6 +997,9 @@ void RB_ShowImages( void ) {
 	image_t	*image;
 	float	x, y, w, h;
 	int		start, end;
+	vec2_t texcoords[4] = { {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f} };
+	vec2_t verts[4];
+	glIndex_t indicies[6] = { 0, 1, 2, 0, 3, 2 };
 
 	if ( !backEnd.projection2D ) {
 		RB_SetGL2D();
@@ -998,6 +1011,8 @@ void RB_ShowImages( void ) {
 
 	start = ri.Milliseconds();
 
+	qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
+
 	for ( i=0 ; i<tr.numImages ; i++ ) {
 		image = tr.images[i];
 
@@ -1012,19 +1027,17 @@ void RB_ShowImages( void ) {
 			h *= image->uploadHeight / 512.0f;
 		}
 
-		GL_Bind( image );
-		qglBegin (GL_QUADS);
-		qglTexCoord2f( 0, 0 );
-		qglVertex2f( x, y );
-		qglTexCoord2f( 1, 0 );
-		qglVertex2f( x + w, y );
-		qglTexCoord2f( 1, 1 );
-		qglVertex2f( x + w, y + h );
-		qglTexCoord2f( 0, 1 );
-		qglVertex2f( x, y + h );
-		qglEnd();
+		verts[0][0] = x;  verts[0][1] = y;
+		verts[1][0] = x+w;  verts[1][1] = y;
+		verts[2][0] = x+w;  verts[2][1] = y+h;
+		verts[3][0] = x;  verts[3][1] = y+h;
+
+		qglTexCoordPointer( 2, GL_FLOAT, 0, texcoords );
+		qglVertexPointer  ( 2, GL_FLOAT, 0, verts );
+		qglDrawElements( GL_TRIANGLE_STRIP, 6, GL_INDEX_TYPE, indicies );
 	}
 
+	qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
 	qglFinish();
 
 	end = ri.Milliseconds();
@@ -1090,6 +1103,7 @@ const void	*RB_SwapBuffers( const void *data ) {
 
 	cmd = (const swapBuffersCommand_t *)data;
 
+#if !defined(NOKIA)
 	// we measure overdraw by reading back the stencil buffer and
 	// counting up the number of increments that have happened
 	if ( r_measureOverdraw->integer ) {
@@ -1107,6 +1121,7 @@ const void	*RB_SwapBuffers( const void *data ) {
 		backEnd.pc.c_overDraw += sum;
 		ri.Hunk_FreeTempMemory( stencilReadback );
 	}
+#endif
 
 
 	if ( !glState.finishCalled ) {
diff --git a/code/renderer/tr_cmds.c b/code/renderer/tr_cmds.c
index 247ea73..ed8e565 100644
--- a/code/renderer/tr_cmds.c
+++ b/code/renderer/tr_cmds.c
@@ -413,6 +413,7 @@ void RE_BeginFrame( stereoFrame_t stereoFrame ) {
 			ri.Error(ERR_FATAL, "RE_BeginFrame() - glGetError() failed (0x%x)!\n", err);
 	}
 
+#if !defined(NOKIA)
 	if (glConfig.stereoEnabled) {
 		if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) )
 			return;
@@ -428,6 +429,7 @@ void RE_BeginFrame( stereoFrame_t stereoFrame ) {
 		}
 	}
 	else
+#endif
 	{
 		if(r_anaglyphMode->integer)
 		{
diff --git a/code/renderer/tr_flares.c b/code/renderer/tr_flares.c
index 0e650f2..f5c5de5 100644
--- a/code/renderer/tr_flares.c
+++ b/code/renderer/tr_flares.c
@@ -253,6 +253,8 @@ FLARE BACK END
 ===============================================================================
 */
 
+#if !defined(NOKIA)
+
 /*
 ==================
 RB_TestFlare
@@ -510,7 +512,7 @@ void RB_RenderFlares (void) {
 	qglMatrixMode( GL_PROJECTION );
 	qglPushMatrix();
     qglLoadIdentity();
-	qglOrtho( backEnd.viewParms.viewportX, backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
+	qglOrthof( backEnd.viewParms.viewportX, backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
 			  backEnd.viewParms.viewportY, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight,
 			  -99999, 99999 );
 
@@ -527,3 +529,8 @@ void RB_RenderFlares (void) {
 	qglPopMatrix();
 }
 
+#else
+void RB_RenderFlares(void)
+{
+}
+#endif
diff --git a/code/renderer/tr_image.c b/code/renderer/tr_image.c
index c86e32a..2f26f0c 100644
--- a/code/renderer/tr_image.c
+++ b/code/renderer/tr_image.c
@@ -175,22 +175,28 @@ void R_ImageList_f( void ) {
 		case 4:
 			ri.Printf( PRINT_ALL, "RGBA " );
 			break;
+#if !defined(NOKIA)
 		case GL_RGBA8:
 			ri.Printf( PRINT_ALL, "RGBA8" );
 			break;
 		case GL_RGB8:
 			ri.Printf( PRINT_ALL, "RGB8" );
 			break;
+#endif
 		case GL_RGB4_S3TC:
+#if !defined(NOKIA)
 		case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+#endif
 			ri.Printf( PRINT_ALL, "S3TC " );
 			break;
+#if !defined(NOKIA)
 		case GL_RGBA4:
 			ri.Printf( PRINT_ALL, "RGBA4" );
 			break;
 		case GL_RGB5:
 			ri.Printf( PRINT_ALL, "RGB5 " );
 			break;
+#endif
 		default:
 			ri.Printf( PRINT_ALL, "???? " );
 		}
@@ -560,6 +566,7 @@ static void Upload32( unsigned *data,
 	scan = ((byte *)data);
 	samples = 3;
 
+#if !defined(NOKIA)
 	if(lightMap)
 	{
 		if(r_greyscale->integer)
@@ -568,6 +575,9 @@ static void Upload32( unsigned *data,
 			internalFormat = GL_RGB;
 	}
 	else
+#else
+	if(!lightMap)
+#endif
 	{
 		for ( i = 0; i < c; i++ )
 		{
@@ -592,6 +602,7 @@ static void Upload32( unsigned *data,
 		// select proper internal format
 		if ( samples == 3 )
 		{
+#if !defined(NOKIA)
 			if(r_greyscale->integer)
 			{
 				if(r_texturebits->integer == 16)
@@ -624,9 +635,13 @@ static void Upload32( unsigned *data,
 					internalFormat = GL_RGB;
 				}
 			}
+#else
+			internalFormat = GL_RGBA;
+#endif
 		}
 		else if ( samples == 4 )
 		{
+#if !defined(NOKIA)
 			if(r_greyscale->integer)
 			{
 				if(r_texturebits->integer == 16)
@@ -651,6 +666,9 @@ static void Upload32( unsigned *data,
 					internalFormat = GL_RGBA;
 				}
 			}
+#else
+			internalFormat = GL_RGBA;
+#endif
 		}
 	}
 
@@ -720,17 +738,21 @@ done:
 
 	if (mipmap)
 	{
+#if !defined(NOKIA)
 		if ( textureFilterAnisotropic )
 			qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
 					(GLint)Com_Clamp( 1, maxAnisotropy, r_ext_max_anisotropy->integer ) );
+#endif
 
 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
 	}
 	else
 	{
+#if !defined(NOKIA)
 		if ( textureFilterAnisotropic )
 			qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1 );
+#endif
 
 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
@@ -1074,7 +1096,9 @@ static void R_CreateFogImage( void ) {
 	byte	*data;
 	float	g;
 	float	d;
+#if !defined(NOKIA)
 	float	borderColor[4];
+#endif
 
 	data = ri.Hunk_AllocateTempMemory( FOG_S * FOG_T * 4 );
 
@@ -1097,12 +1121,14 @@ static void R_CreateFogImage( void ) {
 	tr.fogImage = R_CreateImage("*fog", (byte *)data, FOG_S, FOG_T, qfalse, qfalse, GL_CLAMP_TO_EDGE );
 	ri.Hunk_FreeTempMemory( data );
 
+#if !defined(NOKIA)
 	borderColor[0] = 1.0;
 	borderColor[1] = 1.0;
 	borderColor[2] = 1.0;
 	borderColor[3] = 1;
 
 	qglTexParameterfv( GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor );
+#endif
 }
 
 /*
diff --git a/code/renderer/tr_init.c b/code/renderer/tr_init.c
index 0681919..bb91072 100644
--- a/code/renderer/tr_init.c
+++ b/code/renderer/tr_init.c
@@ -159,6 +159,13 @@ int		max_polys;
 cvar_t	*r_maxpolyverts;
 int		max_polyverts;
 
+void (APIENTRY * qglMultiTexCoord2fARB) (GLenum texture, GLfloat s, GLfloat t);
+void (APIENTRY * qglActiveTextureARB) (GLenum texture);
+void (APIENTRY * qglClientActiveTextureARB) (GLenum texture);
+
+void (APIENTRY * qglLockArraysEXT) (GLint, GLint);
+void (APIENTRY * qglUnlockArraysEXT) (void);
+
 /*
 ** InitOpenGL
 **
@@ -735,11 +742,11 @@ const void *RB_TakeVideoFrameCmd( const void *data )
 */
 void GL_SetDefaultState( void )
 {
-	qglClearDepth( 1.0f );
+	qglClearDepthf( 1.0f );
 
 	qglCullFace(GL_FRONT);
 
-	qglColor4f (1,1,1,1);
+	glColor4f (1,1,1,1);
 
 	// initialize downstream texture unit if we're running
 	// in a multitexture environment
@@ -767,7 +774,9 @@ void GL_SetDefaultState( void )
 	//
 	glState.glStateBits = GLS_DEPTHTEST_DISABLE | GLS_DEPTHMASK_TRUE;
 
+#if !defined(NOKIA)
 	qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+#endif
 	qglDepthMask( GL_TRUE );
 	qglDisable( GL_DEPTH_TEST );
 	qglEnable( GL_SCISSOR_TEST );
diff --git a/code/renderer/tr_local.h b/code/renderer/tr_local.h
index 897d54b..9eb9b0a 100644
--- a/code/renderer/tr_local.h
+++ b/code/renderer/tr_local.h
@@ -30,8 +30,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #include "tr_public.h"
 #include "qgl.h"
 
-#define GL_INDEX_TYPE		GL_UNSIGNED_INT
-typedef unsigned int glIndex_t;
+#define GL_INDEX_TYPE		GL_UNSIGNED_SHORT
+typedef unsigned short glIndex_t;
 
 // fast float to int conversion
 #if id386 && !defined(__GNUC__)
diff --git a/code/renderer/tr_main.c b/code/renderer/tr_main.c
index feda105..03841d0 100644
--- a/code/renderer/tr_main.c
+++ b/code/renderer/tr_main.c
@@ -1314,6 +1314,7 @@ R_DebugPolygon
 ================
 */
 void R_DebugPolygon( int color, int numPoints, float *points ) {
+#if 0
 	int		i;
 
 	GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
@@ -1329,14 +1330,15 @@ void R_DebugPolygon( int color, int numPoints, float *points ) {
 
 	// draw wireframe outline
 	GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
-	qglDepthRange( 0, 0 );
+	qglDepthRangef( 0, 0 );
 	qglColor3f( 1, 1, 1 );
 	qglBegin( GL_POLYGON );
 	for ( i = 0 ; i < numPoints ; i++ ) {
 		qglVertex3fv( points + i * 3 );
 	}
 	qglEnd();
-	qglDepthRange( 0, 1 );
+	qglDepthRangef( 0, 1 );
+#endif
 }
 
 /*
diff --git a/code/renderer/tr_shade.c b/code/renderer/tr_shade.c
index 33a7f2b..2c31aeb 100644
--- a/code/renderer/tr_shade.c
+++ b/code/renderer/tr_shade.c
@@ -34,127 +34,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
 /*
-================
-R_ArrayElementDiscrete
-
-This is just for OpenGL conformance testing, it should never be the fastest
-================
-*/
-static void APIENTRY R_ArrayElementDiscrete( GLint index ) {
-	qglColor4ubv( tess.svars.colors[ index ] );
-	if ( glState.currenttmu ) {
-		qglMultiTexCoord2fARB( 0, tess.svars.texcoords[ 0 ][ index ][0], tess.svars.texcoords[ 0 ][ index ][1] );
-		qglMultiTexCoord2fARB( 1, tess.svars.texcoords[ 1 ][ index ][0], tess.svars.texcoords[ 1 ][ index ][1] );
-	} else {
-		qglTexCoord2fv( tess.svars.texcoords[ 0 ][ index ] );
-	}
-	qglVertex3fv( tess.xyz[ index ] );
-}
-
-/*
-===================
-R_DrawStripElements
-
-===================
-*/
-static int		c_vertexes;		// for seeing how long our average strips are
-static int		c_begins;
-static void R_DrawStripElements( int numIndexes, const glIndex_t *indexes, void ( APIENTRY *element )(GLint) ) {
-	int i;
-	int last[3] = { -1, -1, -1 };
-	qboolean even;
-
-	c_begins++;
-
-	if ( numIndexes <= 0 ) {
-		return;
-	}
-
-	qglBegin( GL_TRIANGLE_STRIP );
-
-	// prime the strip
-	element( indexes[0] );
-	element( indexes[1] );
-	element( indexes[2] );
-	c_vertexes += 3;
-
-	last[0] = indexes[0];
-	last[1] = indexes[1];
-	last[2] = indexes[2];
-
-	even = qfalse;
-
-	for ( i = 3; i < numIndexes; i += 3 )
-	{
-		// odd numbered triangle in potential strip
-		if ( !even )
-		{
-			// check previous triangle to see if we're continuing a strip
-			if ( ( indexes[i+0] == last[2] ) && ( indexes[i+1] == last[1] ) )
-			{
-				element( indexes[i+2] );
-				c_vertexes++;
-				assert( indexes[i+2] < tess.numVertexes );
-				even = qtrue;
-			}
-			// otherwise we're done with this strip so finish it and start
-			// a new one
-			else
-			{
-				qglEnd();
-
-				qglBegin( GL_TRIANGLE_STRIP );
-				c_begins++;
-
-				element( indexes[i+0] );
-				element( indexes[i+1] );
-				element( indexes[i+2] );
-
-				c_vertexes += 3;
-
-				even = qfalse;
-			}
-		}
-		else
-		{
-			// check previous triangle to see if we're continuing a strip
-			if ( ( last[2] == indexes[i+1] ) && ( last[0] == indexes[i+0] ) )
-			{
-				element( indexes[i+2] );
-				c_vertexes++;
-
-				even = qfalse;
-			}
-			// otherwise we're done with this strip so finish it and start
-			// a new one
-			else
-			{
-				qglEnd();
-
-				qglBegin( GL_TRIANGLE_STRIP );
-				c_begins++;
-
-				element( indexes[i+0] );
-				element( indexes[i+1] );
-				element( indexes[i+2] );
-				c_vertexes += 3;
-
-				even = qfalse;
-			}
-		}
-
-		// cache the last three vertices
-		last[0] = indexes[i+0];
-		last[1] = indexes[i+1];
-		last[2] = indexes[i+2];
-	}
-
-	qglEnd();
-}
-
-
-
-/*
 ==================
 R_DrawElements
 
@@ -163,40 +42,9 @@ instead of using the single glDrawElements call that may be inefficient
 without compiled vertex arrays.
 ==================
 */
-static void R_DrawElements( int numIndexes, const glIndex_t *indexes ) {
-	int		primitives;
-
-	primitives = r_primitives->integer;
-
-	// default is to use triangles if compiled vertex arrays are present
-	if ( primitives == 0 ) {
-		if ( qglLockArraysEXT ) {
-			primitives = 2;
-		} else {
-			primitives = 1;
-		}
-	}
-
-
-	if ( primitives == 2 ) {
-		qglDrawElements( GL_TRIANGLES, 
-						numIndexes,
-						GL_INDEX_TYPE,
-						indexes );
-		return;
-	}
-
-	if ( primitives == 1 ) {
-		R_DrawStripElements( numIndexes,  indexes, qglArrayElement );
-		return;
-	}
-	
-	if ( primitives == 3 ) {
-		R_DrawStripElements( numIndexes,  indexes, R_ArrayElementDiscrete );
-		return;
-	}
-
-	// anything else will cause no drawing
+static void R_DrawElements( int numIndexes, const glIndex_t* indexes )
+{
+	qglDrawElements(GL_TRIANGLES, numIndexes, GL_INDEX_TYPE, indexes);
 }
 
 
@@ -253,10 +101,10 @@ Draws triangle outlines for debugging
 */
 static void DrawTris (shaderCommands_t *input) {
 	GL_Bind( tr.whiteImage );
-	qglColor3f (1,1,1);
+	glColor4f (1,1,1,1);
 
 	GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE );
-	qglDepthRange( 0, 0 );
+	qglDepthRangef( 0, 0 );
 
 	qglDisableClientState (GL_COLOR_ARRAY);
 	qglDisableClientState (GL_TEXTURE_COORD_ARRAY);
@@ -274,7 +122,7 @@ static void DrawTris (shaderCommands_t *input) {
 		qglUnlockArraysEXT();
 		GLimp_LogComment( "glUnlockArraysEXT\n" );
 	}
-	qglDepthRange( 0, 1 );
+	qglDepthRangef( 0, 1 );
 }
 
 
@@ -288,21 +136,26 @@ Draws vertex normals for debugging
 static void DrawNormals (shaderCommands_t *input) {
 	int		i;
 	vec3_t	temp;
+	vec3_t verts[2 * SHADER_MAX_VERTEXES];
+	glIndex_t indicies[2 * SHADER_MAX_VERTEXES];
+
+	for (i = 0; i < input->numVertexes; i++) {
+		VectorCopy(input->xyz[i], verts[i * 2]);
+		VectorMA(input->xyz[i], 2, input->normal[i], temp);
+		VectorCopy(temp, verts[(i * 2) + 1]);
+		indicies[(i * 2)] = i * 2;
+		indicies[(i * 2) + 1] = (i * 2) + 1;
+	}
 
 	GL_Bind( tr.whiteImage );
-	qglColor3f (1,1,1);
-	qglDepthRange( 0, 0 );	// never occluded
+	glColor4f (1,1,1,1);
+	qglDepthRangef( 0, 0 );	// never occluded
 	GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE );
 
-	qglBegin (GL_LINES);
-	for (i = 0 ; i < input->numVertexes ; i++) {
-		qglVertex3fv (input->xyz[i]);
-		VectorMA (input->xyz[i], 2, input->normal[i], temp);
-		qglVertex3fv (temp);
-	}
-	qglEnd ();
+	qglVertexPointer(3, GL_FLOAT, 0, verts);
+	qglDrawElements(GL_LINES, i, GL_INDEX_TYPE, indicies);
 
-	qglDepthRange( 0, 1 );
+	qglDepthRangef( 0, 1 );
 }
 
 /*
@@ -352,11 +205,13 @@ static void DrawMultitextured( shaderCommands_t *input, int stage ) {
 
 	GL_State( pStage->stateBits );
 
+#if !defined(NOKIA)
 	// this is an ugly hack to work around a GeForce driver
 	// bug with multitexture and clip planes
 	if ( backEnd.viewParms.isPortal ) {
 		qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
 	}
+#endif
 
 	//
 	// base
@@ -421,7 +276,7 @@ static void ProjectDlightTexture_altivec( void ) {
 	byte	clipBits[SHADER_MAX_VERTEXES];
 	float	texCoordsArray[SHADER_MAX_VERTEXES][2];
 	byte	colorArray[SHADER_MAX_VERTEXES][4];
-	unsigned	hitIndexes[SHADER_MAX_INDEXES];
+	glIndex_t	hitIndexes[SHADER_MAX_INDEXES];
 	int		numIndexes;
 	float	scale;
 	float	radius;
@@ -584,7 +439,7 @@ static void ProjectDlightTexture_scalar( void ) {
 	byte	clipBits[SHADER_MAX_VERTEXES];
 	float	texCoordsArray[SHADER_MAX_VERTEXES][2];
 	byte	colorArray[SHADER_MAX_VERTEXES][4];
-	unsigned	hitIndexes[SHADER_MAX_INDEXES];
+	glIndex_t	hitIndexes[SHADER_MAX_INDEXES];
 	int		numIndexes;
 	float	scale;
 	float	radius;
@@ -680,7 +535,7 @@ static void ProjectDlightTexture_scalar( void ) {
 		// build a list of triangles that need light
 		numIndexes = 0;
 		for ( i = 0 ; i < tess.numIndexes ; i += 3 ) {
-			int		a, b, c;
+			glIndex_t	a, b, c;
 
 			a = tess.indexes[i];
 			b = tess.indexes[i+1];
@@ -1148,6 +1003,9 @@ void RB_StageIteratorGeneric( void )
 
 	input = &tess;
 
+	if (!input->numVertexes)
+		return;
+
 	RB_DeformTessGeometry();
 
 	//
diff --git a/code/renderer/tr_shadows.c b/code/renderer/tr_shadows.c
index f412b00..e887dd3 100644
--- a/code/renderer/tr_shadows.c
+++ b/code/renderer/tr_shadows.c
@@ -124,12 +124,14 @@ void R_RenderShadowEdges( void ) {
 			// if it doesn't share the edge with another front facing
 			// triangle, it is a sil edge
 			if ( hit[ 1 ] == 0 ) {
-				qglBegin( GL_TRIANGLE_STRIP );
-				qglVertex3fv( tess.xyz[ i ] );
-				qglVertex3fv( tess.xyz[ i + tess.numVertexes ] );
-				qglVertex3fv( tess.xyz[ i2 ] );
-				qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] );
-				qglEnd();
+				glIndex_t indicies[4];
+				indicies[0] = i;
+				indicies[1] = i + tess.numVertexes;
+				indicies[2] = i2;
+				indicies[3] = i2 + tess.numVertexes;
+
+				qglVertexPointer(3, GL_FLOAT, 16, tess.xyz);
+				qglDrawElements(GL_TRIANGLE_STRIP, 4, GL_INDEX_TYPE, indicies);
 				c_edges++;
 			} else {
 				c_rejected++;
@@ -213,7 +215,7 @@ void RB_ShadowTessEnd( void ) {
 	GL_Bind( tr.whiteImage );
 	qglEnable( GL_CULL_FACE );
 	GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
-	qglColor3f( 0.2f, 0.2f, 0.2f );
+	glColor4f( 0.2f, 0.2f, 0.2f, 1.0f );
 
 	// don't write to the color buffer
 	qglGetBooleanv(GL_COLOR_WRITEMASK, rgba);
@@ -262,6 +264,14 @@ overlap and double darken.
 =================
 */
 void RB_ShadowFinish( void ) {
+	vec3_t quad[4] = {
+		{-100.0f,  100.0f, -10.0f},
+		{ 100.0f,  100.0f, -10.0f},
+		{ 100.0f, -100.0f, -10.0f},
+		{-100.0f, -100.0f, -10.0f}
+	};
+	glIndex_t indicies[6] = { 0, 1, 2, 0, 3, 2 };
+
 	if ( r_shadows->integer != 2 ) {
 		return;
 	}
@@ -278,20 +288,16 @@ void RB_ShadowFinish( void ) {
 
     qglLoadIdentity ();
 
-	qglColor3f( 0.6f, 0.6f, 0.6f );
+	glColor4f( 0.6f, 0.6f, 0.6f, 1.0f );
 	GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO );
 
-//	qglColor3f( 1, 0, 0 );
+//	glColor4f( 1, 0, 0, 1 );
 //	GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
 
-	qglBegin( GL_QUADS );
-	qglVertex3f( -100, 100, -10 );
-	qglVertex3f( 100, 100, -10 );
-	qglVertex3f( 100, -100, -10 );
-	qglVertex3f( -100, -100, -10 );
-	qglEnd ();
+	qglVertexPointer(3, GL_FLOAT, 0, quad);
+	qglDrawElements(GL_TRIANGLE_STRIP, 6, GL_INDEX_TYPE, indicies);
 
-	qglColor4f(1,1,1,1);
+	glColor4f(1,1,1,1);
 	qglDisable( GL_STENCIL_TEST );
 }
 
diff --git a/code/renderer/tr_sky.c b/code/renderer/tr_sky.c
index 02624f3..85fc1cc 100644
--- a/code/renderer/tr_sky.c
+++ b/code/renderer/tr_sky.c
@@ -363,25 +363,30 @@ static float	s_skyTexCoords[SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1][2];
 
 static void DrawSkySide( struct image_s *image, const int mins[2], const int maxs[2] )
 {
-	int s, t;
+	int s, t, i = 0;
+	int size;
+	glIndex_t *indicies;
+
+	size = (maxs[1] - mins[1]) * (maxs[0] - mins[0] + 1);
+	indicies = ri.Hunk_AllocateTempMemory(sizeof(glIndex_t) * size);
 
 	GL_Bind( image );
 
 	for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t < maxs[1]+HALF_SKY_SUBDIVISIONS; t++ )
 	{
-		qglBegin( GL_TRIANGLE_STRIP );
-
 		for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ )
 		{
-			qglTexCoord2fv( s_skyTexCoords[t][s] );
-			qglVertex3fv( s_skyPoints[t][s] );
-
-			qglTexCoord2fv( s_skyTexCoords[t+1][s] );
-			qglVertex3fv( s_skyPoints[t+1][s] );
+			indicies[i++] = t * (SKY_SUBDIVISIONS + 1) + s;
+			indicies[i++] = (t + 1) * (SKY_SUBDIVISIONS + 1) + s;
 		}
-
-		qglEnd();
 	}
+
+	qglDisableClientState(GL_COLOR_ARRAY);
+	qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
+	qglTexCoordPointer(2, GL_FLOAT, 0, s_skyTexCoords);
+	qglVertexPointer(3, GL_FLOAT, 0, s_skyPoints);
+	qglDrawElements(GL_TRIANGLE_STRIP, i, GL_INDEX_TYPE, indicies);
+	Hunk_FreeTempMemory(indicies);
 }
 
 static void DrawSkyBox( shader_t *shader )
@@ -722,7 +727,7 @@ void RB_DrawSun( void ) {
 	VectorScale( vec2, size, vec2 );
 
 	// farthest depth range
-	qglDepthRange( 1.0, 1.0 );
+	qglDepthRangef( 1.0, 1.0 );
 
 	// FIXME: use quad stamp
 	RB_BeginSurface( tr.sunShader, tess.fogNum );
@@ -780,7 +785,7 @@ void RB_DrawSun( void ) {
 	RB_EndSurface();
 
 	// back to normal depth range
-	qglDepthRange( 0.0, 1.0 );
+	qglDepthRangef( 0.0, 1.0 );
 }
 
 
@@ -809,14 +814,14 @@ void RB_StageIteratorSky( void ) {
 	// front of everything to allow developers to see how
 	// much sky is getting sucked in
 	if ( r_showsky->integer ) {
-		qglDepthRange( 0.0, 0.0 );
+		qglDepthRangef( 0.0, 0.0 );
 	} else {
-		qglDepthRange( 1.0, 1.0 );
+		qglDepthRangef( 1.0, 1.0 );
 	}
 
 	// draw the outer skybox
 	if ( tess.shader->sky.outerbox[0] && tess.shader->sky.outerbox[0] != tr.defaultImage ) {
-		qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight );
+		glColor4f( tr.identityLight, tr.identityLight, tr.identityLight, 1.0f );
 		
 		qglPushMatrix ();
 		GL_State( 0 );
@@ -837,7 +842,7 @@ void RB_StageIteratorSky( void ) {
 
 
 	// back to normal depth range
-	qglDepthRange( 0.0, 1.0 );
+	qglDepthRangef( 0.0, 1.0 );
 
 	// note that sky was drawn so we will draw a sun later
 	backEnd.skyRenderedThisView = qtrue;
diff --git a/code/renderer/tr_surface.c b/code/renderer/tr_surface.c
index 1365569..5b89ffb 100644
--- a/code/renderer/tr_surface.c
+++ b/code/renderer/tr_surface.c
@@ -291,7 +291,7 @@ static void RB_SurfaceBeam( void )
 	int	i;
 	vec3_t perpvec;
 	vec3_t direction, normalized_direction;
-	vec3_t	start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS];
+	vec3_t points[NUM_BEAM_SEGS * 2];
 	vec3_t oldorigin, origin;
 
 	e = &backEnd.currentEntity->e;
@@ -317,23 +317,18 @@ static void RB_SurfaceBeam( void )
 
 	for ( i = 0; i < NUM_BEAM_SEGS ; i++ )
 	{
-		RotatePointAroundVector( start_points[i], normalized_direction, perpvec, (360.0/NUM_BEAM_SEGS)*i );
-//		VectorAdd( start_points[i], origin, start_points[i] );
-		VectorAdd( start_points[i], direction, end_points[i] );
+		RotatePointAroundVector(points[i * 2], normalized_direction, perpvec, (360.0 / NUM_BEAM_SEGS) * i);
+		VectorAdd(points[i * 2], direction, points[i * 2 + 1]);
 	}
 
 	GL_Bind( tr.whiteImage );
 
 	GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
 
-	qglColor3f( 1, 0, 0 );
+	glColor4f( 1, 0, 0, 1 );
 
-	qglBegin( GL_TRIANGLE_STRIP );
-	for ( i = 0; i <= NUM_BEAM_SEGS; i++ ) {
-		qglVertex3fv( start_points[ i % NUM_BEAM_SEGS] );
-		qglVertex3fv( end_points[ i % NUM_BEAM_SEGS] );
-	}
-	qglEnd();
+	qglVertexPointer(3, GL_FLOAT, 0, points);
+	qglDrawArrays(GL_TRIANGLE_STRIP, 0, NUM_BEAM_SEGS * 2);
 }
 
 //================================================================================
@@ -905,7 +900,8 @@ RB_SurfaceFace
 */
 static void RB_SurfaceFace( srfSurfaceFace_t *surf ) {
 	int			i;
-	unsigned	*indices, *tessIndexes;
+	unsigned int	*indices;
+	glIndex_t	*tessIndexes;
 	float		*v;
 	float		*normal;
 	int			ndx;
@@ -1161,19 +1157,27 @@ Draws x/y/z lines from the origin for orientation debugging
 ===================
 */
 static void RB_SurfaceAxis( void ) {
+	byte colors[3][4] = {
+		{255, 0, 0, 255},
+		{0, 255, 0, 255},
+		{0, 0, 255, 255}
+	};
+	vec3_t verts[6] = {
+		{0.0f, 0.0f, 0.0f},
+		{16.0f, 0.0f, 0.0f},
+		{0.0f, 0.0f, 0.0f},
+		{0.0f, 16.0f, 0.0f},
+		{0.0f, 0.0f, 0.0f},
+		{0.0f, 0.0f, 16.0f}
+	};
+	glIndex_t indicies[6] = { 0, 1, 0, 2, 0, 3 };
+
 	GL_Bind( tr.whiteImage );
 	qglLineWidth( 3 );
-	qglBegin( GL_LINES );
-	qglColor3f( 1,0,0 );
-	qglVertex3f( 0,0,0 );
-	qglVertex3f( 16,0,0 );
-	qglColor3f( 0,1,0 );
-	qglVertex3f( 0,0,0 );
-	qglVertex3f( 0,16,0 );
-	qglColor3f( 0,0,1 );
-	qglVertex3f( 0,0,0 );
-	qglVertex3f( 0,0,16 );
-	qglEnd();
+	qglEnableClientState(GL_COLOR_ARRAY);
+	qglColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
+	qglVertexPointer(3, GL_FLOAT, 0, verts);
+	qglDrawElements(GL_LINES, 6, GL_INDEX_TYPE, indicies);
 	qglLineWidth( 1 );
 }
 
diff --git a/code/sys/sys_loadlib.h b/code/sys/sys_loadlib.h
index 994c5d3..ae736d5 100644
--- a/code/sys/sys_loadlib.h
+++ b/code/sys/sys_loadlib.h
@@ -20,6 +20,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 ===========================================================================
 */
 
+#if !defined(NOKIA)
 #ifdef DEDICATED
 #	ifdef _WIN32
 #		include <windows.h>
@@ -47,3 +48,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #	define Sys_LoadFunction(h,fn) SDL_LoadFunction(h,fn)
 #	define Sys_LibraryError() SDL_GetError()
 #endif
+#else
+#include <dlfcn.h>
+#define Sys_LoadLibrary(f) dlopen(f,RTLD_NOW)
+#define Sys_UnloadLibrary(h) dlclose(h)
+#define Sys_LoadFunction(h,fn) dlsym(h,fn)
+#define Sys_LibraryError() dlerror()
+#endif
diff --git a/code/sys/sys_local.h b/code/sys/sys_local.h
index a114c79..e506e7c 100644
--- a/code/sys/sys_local.h
+++ b/code/sys/sys_local.h
@@ -33,6 +33,7 @@ void IN_Init( void );
 void IN_Frame( void );
 void IN_Shutdown( void );
 void IN_Restart( void );
+qboolean IN_MotionPressed( void );
 
 // Console
 void CON_Shutdown( void );
diff --git a/code/sys/sys_main.c b/code/sys/sys_main.c
index eb49326..0f99923 100644
--- a/code/sys/sys_main.c
+++ b/code/sys/sys_main.c
@@ -31,6 +31,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #include <ctype.h>
 #include <errno.h>
 
+#if !defined(NOKIA)
 #ifndef DEDICATED
 #ifdef USE_LOCAL_HEADERS
 #	include "SDL.h"
@@ -40,6 +41,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #	include <SDL_cpuinfo.h>
 #endif
 #endif
+#endif
 
 #include "sys_local.h"
 #include "sys_loadlib.h"
@@ -138,9 +140,11 @@ void Sys_Exit( int ex )
 {
 	CON_Shutdown( );
 
+#if !defined(NOKIA)
 #ifndef DEDICATED
 	SDL_Quit( );
 #endif
+#endif
 
 #ifdef NDEBUG
 	exit( ex );
@@ -171,6 +175,7 @@ cpuFeatures_t Sys_GetProcessorFeatures( void )
 {
 	cpuFeatures_t features = 0;
 
+#if !defined(NOKIA)
 #ifndef DEDICATED
 	if( SDL_HasRDTSC( ) )    features |= CF_RDTSC;
 	if( SDL_HasMMX( ) )      features |= CF_MMX;
@@ -181,6 +186,7 @@ cpuFeatures_t Sys_GetProcessorFeatures( void )
 	if( SDL_HasSSE2( ) )     features |= CF_SSE2;
 	if( SDL_HasAltiVec( ) )  features |= CF_ALTIVEC;
 #endif
+#endif
 
 	return features;
 }
@@ -506,6 +512,7 @@ int main( int argc, char **argv )
 	int   i;
 	char  commandLine[ MAX_STRING_CHARS ] = { 0 };
 
+#if !defined(NOKIA)
 #ifndef DEDICATED
 	// SDL version check
 
@@ -529,6 +536,7 @@ int main( int argc, char **argv )
 		Sys_Exit( 1 );
 	}
 #endif
+#endif
 
 	Sys_PlatformInit( );
 
@@ -558,12 +566,14 @@ int main( int argc, char **argv )
 
 	while( 1 )
 	{
+#if !defined(NOKIA)
 #ifndef DEDICATED
 		int appState = SDL_GetAppState( );
 
 		Cvar_SetValue( "com_unfocused",	!( appState & SDL_APPINPUTFOCUS ) );
 		Cvar_SetValue( "com_minimized", !( appState & SDL_APPACTIVE ) );
 #endif
+#endif
 
 		IN_Frame( );
 		Com_Frame( );
diff --git a/code/ui/ui_main.c b/code/ui/ui_main.c
index 2fccf16..22a4d4a 100644
--- a/code/ui/ui_main.c
+++ b/code/ui/ui_main.c
@@ -5194,14 +5194,15 @@ UI_MouseEvent
 */
 void _UI_MouseEvent( int dx, int dy )
 {
+	//printf(__FILE__ "_UI_MouseEvent(%d,%d)\n", dx, dy);
 	// update mouse screen position
-	uiInfo.uiDC.cursorx += dx;
+	uiInfo.uiDC.cursorx = dx - (uiInfo.uiDC.glconfig.vidWidth - SCREEN_WIDTH) / 2;
 	if (uiInfo.uiDC.cursorx < 0)
 		uiInfo.uiDC.cursorx = 0;
 	else if (uiInfo.uiDC.cursorx > SCREEN_WIDTH)
 		uiInfo.uiDC.cursorx = SCREEN_WIDTH;
 
-	uiInfo.uiDC.cursory += dy;
+	uiInfo.uiDC.cursory = dy - (uiInfo.uiDC.glconfig.vidHeight - SCREEN_HEIGHT) / 2);
 	if (uiInfo.uiDC.cursory < 0)
 		uiInfo.uiDC.cursory = 0;
 	else if (uiInfo.uiDC.cursory > SCREEN_HEIGHT)
diff --git a/debian/README b/debian/README
new file mode 100644
index 0000000..a9f5738
--- /dev/null
+++ b/debian/README
@@ -0,0 +1,6 @@
+The Debian Package ioquake3
+----------------------------
+
+Comments regarding the Package
+
+ -- Oliver McFadden <oliver.mcfadden@nokia.com>  Thu, 28 May 2009 18:27:00 +0300
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..10b5d1a
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,5 @@
+ioquake3 (1558-maemo1) unstable; urgency=low
+
+  * Initial Release.
+
+ -- Oliver McFadden <oliver.mcfadden@nokia.com>  Sun, 11 Oct 2009 13:11:09 +0300
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..7ed6ff8
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+5
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..dfdd557
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,19 @@
+Source: ioquake3
+Section: unknown
+Priority: extra
+Maintainer: Oliver McFadden <oliver.mcfadden@nokia.com>
+Build-Depends: debhelper (>= 5), opengles-sgx-img-common, libgles1-sgx-img, perl, libsdl1.2-dev
+Standards-Version: 3.8.1
+Homepage: http://ioquake3.org/
+
+Package: ioquake3
+Architecture: any
+Depends: opengles-sgx-img-common, libgles1-sgx-img, xserver-xomap, ${shlibs:Depends}, ${misc:Depends}
+Description: Quake III Arena
+ Welcome to the Arena, where high-ranking warriors are transformed into
+ spineless mush. Abandoning every ounce of common sense and any trace of doubt,
+ you lunge onto a stage of harrowing landscapes and veiled abysses. Your new
+ environment rejects you with lava pits and atmospheric hazards as legions of
+ foes surround you, testing the gut reaction that brought you here in the first
+ place. Your new mantra: Fight or be finished.
+
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..3160e1e
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,52 @@
+This package was debianized by:
+
+    Oliver McFadden <oliver.mcfadden@nokia.com> on Thu, 28 May 2009 18:27:00 +0300
+
+It was downloaded from:
+
+    <url://example.com>
+
+Upstream Author(s):
+
+    <put author's name and email here>
+    <likewise for another author>
+
+Copyright:
+
+    <Copyright (C) YYYY Firtname Lastname>
+    <likewise for another author>
+
+License:
+
+### SELECT: ###
+    This package is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+### OR ###
+   This package is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License version 2 as
+   published by the Free Software Foundation.
+##########
+
+    This package is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this package; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+
+On Debian systems, the complete text of the GNU General
+Public License version 2 can be found in `/usr/share/common-licenses/GPL-2'.
+
+The Debian packaging is:
+
+    Copyright (C) 2009 Oliver McFadden <oliver.mcfadden@nokia.com>
+
+and is licensed under the GPL version 3, 
+see `/usr/share/common-licenses/GPL-3'.
+
+# Please also look if there are files or directories which have a
+# different copyright/license attached and list them here.
diff --git a/debian/dirs b/debian/dirs
new file mode 100644
index 0000000..ca882bb
--- /dev/null
+++ b/debian/dirs
@@ -0,0 +1,2 @@
+usr/bin
+usr/sbin
diff --git a/debian/docs b/debian/docs
new file mode 100644
index 0000000..347e8db
--- /dev/null
+++ b/debian/docs
@@ -0,0 +1,8 @@
+BUGS
+COPYING.txt
+id-readme.txt
+md4-readme.txt
+NOTTODO
+README
+TODO
+voip-readme.txt
diff --git a/debian/ioquake3.install b/debian/ioquake3.install
new file mode 100644
index 0000000..86999d2
--- /dev/null
+++ b/debian/ioquake3.install
@@ -0,0 +1,6 @@
+build/release-linux-arm/baseq3/*.so	/home/user/baseq3
+build/release-linux-arm/ioquake3.arm	/usr/bin
+misc/32x32/quake3.png	/usr/share/icons/hicolor/32x32/hildon
+misc/48x48/quake3.png	/usr/share/icons/hicolor/48x48/hildon
+misc/64x64/quake3.png	/usr/share/icons/hicolor/64x64/hildon
+misc/quake3.desktop	/usr/share/applications/hildon
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..421105e
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,80 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+
+
+
+
+configure: configure-stamp
+configure-stamp:
+	dh_testdir
+	# Add here commands to configure the package.
+
+	touch configure-stamp
+
+
+build: build-stamp
+
+build-stamp: configure-stamp  
+	dh_testdir
+	$(MAKE) release
+	touch $@
+
+clean: 
+	dh_testdir
+	dh_testroot
+	rm -f build-stamp configure-stamp
+	$(MAKE) distclean
+	dh_clean 
+
+install: build
+	dh_testdir
+	dh_testroot
+	dh_installdirs
+
+
+# Build architecture-independent files here.
+binary-indep: install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: install
+	dh_testdir
+	dh_testroot
+	dh_installchangelogs ChangeLog
+	dh_installdocs
+	dh_installexamples
+	dh_install
+#	dh_installmenu
+#	dh_installdebconf
+#	dh_installlogrotate
+#	dh_installemacsen
+#	dh_installpam
+#	dh_installmime
+#	dh_python
+#	dh_installinit
+#	dh_installcron
+#	dh_installinfo
+	dh_installman
+	dh_link
+	#dh_strip
+	dh_compress
+	dh_fixperms
+#	dh_perl
+#	dh_makeshlibs
+	dh_installdeb
+	dh_shlibdeps
+	dh_gencontrol
+	dh_md5sums
+	dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure
diff --git a/misc/32x32/quake3.png b/misc/32x32/quake3.png
new file mode 100644
index 0000000..33d2949
Binary files /dev/null and b/misc/32x32/quake3.png differ
diff --git a/misc/48x48/quake3.png b/misc/48x48/quake3.png
new file mode 100644
index 0000000..ab83e3b
Binary files /dev/null and b/misc/48x48/quake3.png differ
diff --git a/misc/64x64/quake3.png b/misc/64x64/quake3.png
new file mode 100644
index 0000000..64cdfea
Binary files /dev/null and b/misc/64x64/quake3.png differ
diff --git a/misc/quake3.desktop b/misc/quake3.desktop
new file mode 100644
index 0000000..a8be7e1
--- /dev/null
+++ b/misc/quake3.desktop
@@ -0,0 +1,8 @@
+[Desktop Entry]
+Encoding=UTF-8
+Version=0.1
+Type=Application
+Name=Quake 3
+Exec=/home/user/baseq3/q3.sh
+Icon=quake3
+X-Osso-Type=application/x-executable
