diff --git a/include/model.h b/include/model.h
index 99c6587..2ff79b2 100644
--- a/include/model.h
+++ b/include/model.h
@@ -458,5 +458,6 @@ byte	*Mod_LeafPVS (mleaf_t *leaf, model_t *model);
 model_t	*Mod_FindName (char *name);
 void	Mod_ProcessTexture(miptex_t *mt, texture_t *tx);
 void	Mod_LoadLighting (lump_t *l);
+int     Mod_CalcFullbright (byte *in, byte *out, int pixels);
 
 #endif	// _MODEL_H
diff --git a/include/skin.h b/include/skin.h
index 5d9f8fd..ce9f1e8 100644
--- a/include/skin.h
+++ b/include/skin.h
@@ -1,7 +1,7 @@
 /*
-	client.h
+	skin.h
 
-	Client definitions
+	Client skin definitions
 
 	Copyright (C) 1996-1997  Id Software, Inc.
 
@@ -29,21 +29,26 @@
 #ifndef _SKIN_H
 #define _SKIN_H
 
-#include "client.h"
+#define MAX_CACHED_SKINS 128
+
+#define RSSHOT_WIDTH 320
+#define RSSHOT_HEIGHT 200
 
 typedef struct skin_s
 {
 	char		name[16];
 	qboolean	failedload;		// the name isn't a valid skin
 	cache_user_t	cache;
+	int         fb_texture;
 } skin_t;
 
 extern byte player_8bit_texels[320 * 200];
+extern skin_t   skin_cache[MAX_CACHED_SKINS];
 struct tex_s;
 struct player_info_s;
 
 void	Skin_Find (struct player_info_s *sc);
-byte	*Skin_Cache (skin_t *skin);
+struct tex_s *Skin_Cache (skin_t *skin);
 void	Skin_Skins_f (void);
 void	Skin_AllSkins_f (void);
 void	Skin_NextDownload (void);
@@ -54,9 +59,4 @@ void	Skin_Set_Translate (struct player_info_s *player);
 void	Skin_Do_Translation (player_info_t *player);
 void	Skin_Process (skin_t *skin, struct tex_s *);
 
-#define MAX_CACHED_SKINS 128
-
-#define RSSHOT_WIDTH 320
-#define RSSHOT_HEIGHT 200
-
 #endif
diff --git a/source/gl_model_fullbright.c b/source/gl_model_fullbright.c
index 8b3b9dc..eb8a2b0 100644
--- a/source/gl_model_fullbright.c
+++ b/source/gl_model_fullbright.c
@@ -40,41 +40,39 @@
 #include "r_local.h"
 #include "sys.h"
 
+int
+Mod_CalcFullbright (byte *in, byte *out, int pixels)
+{
+	int fb = 0;
+	
+	while (pixels--) {
+		if (*in >= 256 - 32) {
+			fb = 1;
+			*out++ = *in++;
+		} else {
+			*out++ = 255;
+			in++;
+		}
+	}
+	return fb;
+}
+
 int
 Mod_Fullbright (byte * skin, int width, int height, char *name)
 {
-	int         j;
 	int         pixels;
-	qboolean    hasfullbrights = false;
-	int         texnum;
+	int         texnum = 0;
+	byte       *ptexels;
 
 	// Check for fullbright pixels..
 	pixels = width * height;
 
-	for (j = 0; j < pixels; j++) {
-		if (skin[j] >= 256 - 32) {
-			hasfullbrights = true;
-			break;
-		}
-	}
-
-	if (hasfullbrights) {
-		byte       *ptexels;
-
-		// ptexels = Hunk_Alloc(s);
-		ptexels = malloc (pixels);
-
+	// ptexels = Hunk_Alloc(s);
+	ptexels = malloc (pixels);
+	if (Mod_CalcFullbright (skin, ptexels, pixels)) {
 		Con_DPrintf ("FB Model ID: '%s'\n", name);
-		for (j = 0; j < pixels; j++) {
-			if (skin[j] >= 256 - 32) {
-				ptexels[j] = skin[j];
-			} else {
-				ptexels[j] = 255;
-			}
-		}
 		texnum = GL_LoadTexture (name, width, height, ptexels, true, true, 1);
-		free (ptexels);
-		return texnum;
 	}
-	return 0;
+	free (ptexels);
+	return texnum;
 }
diff --git a/source/gl_rmain.c b/source/gl_rmain.c
index fec009f..c58f05b 100644
--- a/source/gl_rmain.c
+++ b/source/gl_rmain.c
@@ -722,6 +722,7 @@ R_DrawAliasModel (entity_t *e)
 	float		an;
 	int 		anim;
 	qboolean	torch = false;
+	int         fb_texture = 0;
 
 	clmodel = currententity->model;
 
@@ -823,19 +824,34 @@ R_DrawAliasModel (entity_t *e)
 	}
 
 	anim = (int) (cl.time * 10) & 3;
-	glBindTexture (GL_TEXTURE_2D,
-				   paliashdr->gl_texturenum[currententity->skinnum][anim]);
 
 	// we can't dynamically colormap textures, so they are cached
 	// seperately for the players.  Heads are just uncolored.
 	if (currententity->scoreboard && !gl_nocolors->int_val) {
+		skin_t *skin;
+
 		i = currententity->scoreboard - cl.players;
 		if (!currententity->scoreboard->skin) {
 			Skin_Find (currententity->scoreboard);
 			CL_NewTranslation (i);
 		}
+		skin = currententity->scoreboard->skin;
 		if (i >= 0 && i < MAX_CLIENTS)
 			glBindTexture (GL_TEXTURE_2D, playertextures + i);
+		if (gl_fb_models->int_val) {
+			if (skin)
+				fb_texture = skin->fb_texture;
+			else
+				fb_texture = paliashdr->gl_fb_texturenum[currententity->skinnum]
+				                                                    [anim];
+		}
+	} else {
+		glBindTexture (GL_TEXTURE_2D,
+					   paliashdr->gl_texturenum[currententity->skinnum][anim]);
+		if (clmodel->hasfullbrights && gl_fb_models->int_val &&
+			paliashdr->gl_fb_texturenum[currententity->skinnum][anim])
+			fb_texture = paliashdr->gl_fb_texturenum[currententity->skinnum]
+			                                        [anim];
 	}
 
 	if (gl_affinemodels->int_val)
@@ -848,11 +864,11 @@ R_DrawAliasModel (entity_t *e)
 	}
 
 	// This block is GL fullbright support for objects...
-	if (clmodel->hasfullbrights && gl_fb_models->int_val &&
-		paliashdr->gl_fb_texturenum[currententity->skinnum][anim]) {
-		glBindTexture (GL_TEXTURE_2D, paliashdr->gl_fb_texturenum[currententity->skinnum][anim]);
+	if (fb_texture) {
+		glBindTexture (GL_TEXTURE_2D, fb_texture);
 		if (gl_lerp_anim->int_val) {
-			R_SetupAliasBlendedFrame (currententity->frame, paliashdr, currententity, true);
+			R_SetupAliasBlendedFrame (currententity->frame, paliashdr,
+			                          currententity, true);
 		} else {
 			R_SetupAliasFrame (currententity->frame, paliashdr, true);
 		}
diff --git a/source/gl_skin.c b/source/gl_skin.c
index 50ba1e9..353bbdc 100644
--- a/source/gl_skin.c
+++ b/source/gl_skin.c
@@ -136,33 +136,19 @@ build_skin_32 (byte * original, int tinwidth, int tinheight,
 	glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 }
 
-void
-Skin_Do_Translation (player_info_t *player)
+static void
+build_skin (int texnum, byte *ptexels, int width, int height)
 {
-	int         inwidth, inheight;
 	int         tinwidth, tinheight;
 	unsigned int scaled_width, scaled_height;
-	byte       *original;
 
 	// locate the original skin pixels
 	tinwidth = 296;						// real model width
 	tinheight = 194;					// real model height
 
-	if (!player->skin)
-		Skin_Find (player);
-	if ((original = Skin_Cache (player->skin)) != NULL) {
-		// skin data width
-		inwidth = 320;
-		inheight = 200;
-	} else {
-		original = player_8bit_texels;
-		inwidth = 296;
-		inheight = 194;
-	}
-
 	// because this happens during gameplay, do it fast
 	// instead of sending it through GL_Upload8()
-	glBindTexture (GL_TEXTURE_2D, playertextures + (player - cl.players));
+	glBindTexture (GL_TEXTURE_2D, texnum);
 
 	// FIXME deek: This 512x256 limit sucks!
 	scaled_width = min (gl_max_size->int_val, 512);
@@ -173,13 +159,37 @@ Skin_Do_Translation (player_info_t *player)
 	scaled_height >>= gl_playermip->int_val;
 
 	if (VID_Is8bit ()) {				// 8bit texture upload
-		build_skin_8 (original, tinwidth, tinheight, scaled_width,
-					  scaled_height, inwidth);
+		build_skin_8 (ptexels, tinwidth, tinheight, scaled_width,
+					  scaled_height, width);
 	} else {
-		build_skin_32 (original, tinwidth, tinheight, scaled_width,
-					   scaled_height, inwidth);
+		build_skin_32 (ptexels, tinwidth, tinheight, scaled_width,
+					   scaled_height, width);
 	}
+}
 
+void
+Skin_Do_Translation (player_info_t *player)
+{
+	int         texnum;
+	int         inwidth, inheight;
+	byte       *original;
+	tex_t      *skin;
+
+	if (!player->skin)
+		Skin_Find (player);
+
+	if ((skin = (tex_t*)Skin_Cache (player->skin)) != NULL) {
+		// skin data width
+		inwidth = 320;
+		inheight = 200;
+		original = skin->data;
+	} else {
+		original = player_8bit_texels;
+		inwidth = 296;
+		inheight = 194;
+	}
+	texnum = playertextures + (player - cl.players);
+	build_skin (texnum, original, inwidth, inheight);
 }
 
 void
@@ -196,4 +206,11 @@ Skin_Init_Translation (void)
 void
 Skin_Process (skin_t *skin, tex_t *tex)
 {
+	int pixels = tex->width * tex->height;
+	byte *ptexels = Hunk_TempAlloc (pixels);
+
+	if (Mod_CalcFullbright (tex->data, ptexels, pixels)) {
+		skin->fb_texture = player_fb_textures + (skin - skin_cache);
+		build_skin (skin->fb_texture, ptexels, tex->width, tex->height);
+	}
 }
diff --git a/source/r_alias.c b/source/r_alias.c
index b84e2f8..db53697 100644
--- a/source/r_alias.c
+++ b/source/r_alias.c
@@ -35,6 +35,7 @@
 #include "r_local.h"
 #include "skin.h"
 #include "sys.h"
+#include "texture.h"
 
 #define LIGHT_MIN	5					// lowest light value we'll allow, to 
 										// avoid the
@@ -608,13 +609,13 @@ R_AliasSetupSkin (void)
 	r_affinetridesc.skinheight = pmdl->skinheight;
 
 	if (currententity->scoreboard) {
-		byte       *base;
+		tex_t      *base;
 
 		if (!currententity->scoreboard->skin)
 			Skin_Find (currententity->scoreboard);
 		base = Skin_Cache (currententity->scoreboard->skin);
 		if (base) {
-			r_affinetridesc.pskin = base;
+			r_affinetridesc.pskin = base->data;
 			r_affinetridesc.skinwidth = 320;
 			r_affinetridesc.skinheight = 200;
 		}
diff --git a/source/skin.c b/source/skin.c
index a094c21..2749cb9 100644
--- a/source/skin.c
+++ b/source/skin.c
@@ -38,6 +38,7 @@
 #endif
 
 #include "cl_parse.h"
+#include "client.h"
 #include "console.h"
 #include "cmd.h"
 #include "host.h"
@@ -58,7 +59,7 @@ cvar_t     *bottomcolor;
 
 char        allskins[128];
 
-skin_t      skins[MAX_CACHED_SKINS];
+skin_t      skin_cache[MAX_CACHED_SKINS];
 int         numskins;
 
 /*
@@ -90,8 +91,8 @@ Skin_Find (player_info_t *sc)
 	COM_StripExtension (name, name);
 
 	for (i = 0; i < numskins; i++) {
-		if (!strcmp (name, skins[i].name)) {
-			sc->skin = &skins[i];
+		if (!strcmp (name, skin_cache[i].name)) {
+			sc->skin = &skin_cache[i];
 			Skin_Cache (sc->skin);
 			return;
 		}
@@ -103,7 +104,7 @@ Skin_Find (player_info_t *sc)
 		return;
 	}
 
-	skin = &skins[numskins];
+	skin = &skin_cache[numskins];
 	sc->skin = skin;
 	numskins++;
 
@@ -117,13 +118,14 @@ Skin_Find (player_info_t *sc)
 
 	Returns a pointer to the skin bitmap, or NULL to use the default
 */
-byte *
+tex_t *
 Skin_Cache (skin_t *skin)
 {
 	char        name[1024];
-	byte       *out;
+	tex_t      *out;
 	QFile      *file;
 	tex_t      *tex;
+	int         pixels;
 
 	if (cls.downloadtype == dl_skin)
 		return NULL;					// use base until downloaded
@@ -159,14 +161,15 @@ Skin_Cache (skin_t *skin)
 		Con_Printf ("Bad skin %s\n", name);
 		return NULL;
 	}
+	pixels = tex->width * tex->height;
 
-	out = Cache_Alloc (&skin->cache, 320 * 200, skin->name);
+	out = Cache_Alloc (&skin->cache, sizeof (tex_t) + pixels, skin->name);
 	if (!out)
 		Sys_Error ("Skin_Cache: couldn't allocate");
 
-	memcpy (out, tex->data, tex->width * tex->height);
+	memcpy (out, tex, sizeof (tex_t) + pixels);
 
-	Skin_Process (skin, tex);
+	Skin_Process (skin, out);
 
 	skin->failedload = false;
 
@@ -230,8 +233,8 @@ Skin_Skins_f (void)
 	int         i;
 
 	for (i = 0; i < numskins; i++) {
-		if (skins[i].cache.data)
-			Cache_Free (&skins[i].cache);
+		if (skin_cache[i].cache.data)
+			Cache_Free (&skin_cache[i].cache);
 	}
 	numskins = 0;