示例#1
0
void TextMessageInit( void )
{
	int fileSize;
	byte *pMemFile;

	// Clear out any old data that's sitting around.
	if ( gMessageTable )
	{
		free( gMessageTable );
		gMessageTable = NULL;
	}

	pMemFile = COM_LoadTempFile( "scripts/titles.txt", &fileSize );

	if ( pMemFile )
		TextMessageParse( pMemFile, fileSize );

	int i;

	for ( i = 0; i < MAX_NETMESSAGE; i++ )
	{
		gNetworkTextMessage[ i ].pMessage = 
			gNetworkTextMessageBuffer[ i ];
	}
}
示例#2
0
void CL_LoadLocs(void)
{
	location_t *newloc;
	vec3_t pos;

	char *file;
	char *end;
	char name[MAX_QPATH];
//	if (!strcmp(LocationLevel, cl.model_name[1]))
//		return;

	while(location)
	{
		newloc = location->next;
		Z_Free(location);
		location = newloc;
	}

	strcpy(LocationLevel, cl.model_name[1]);

	COM_StripExtension(COM_SkipPath(LocationLevel), name);
	file = COM_LoadTempFile(va("locs/%s.loc", name));

	if (!file)
		return;
	for(;;)
	{
		file = COM_Parse(file);
		pos[0] = atof(com_token)/8;
		file = COM_Parse(file);
		pos[1] = atof(com_token)/8;
		file = COM_Parse(file);
		pos[2] = atof(com_token)/8;

		while(*file && *file <= '\0')
			file++;

		if (!file)
			return;
		end = strchr(file, '\n');	
		if (!end)
		{
			end = file + strlen(file);
		}
		newloc = Z_Malloc(sizeof(location_t) + end-file+1);
		newloc->next = location;
		location = newloc;

		Q_strncpyz(newloc->name, file, end-file);
		VectorCopy(pos, newloc->pos);


		if (!*end)
			return;
		file = end+1;
	}
}
示例#3
0
void Chat_GetTag(const char *filename, float tag, char **text, char **condition, char **options)
{	
	char *file; char *s;
	file = COM_LoadTempFile(va("dialog/%s.dlg", filename), NULL);
	if (!file)
	{
		*text = "ERROR: File not found";
		*condition = "";
		*options = "";
		return;
	}
	for (;*file;file++)
	{
		if (*file == '\n')
		{
			if (file[1] == '{')
			{
				if(atof(file+2)==tag)
				{
					*condition = strchr(file+2, '{')+1;

					s = strchr(file, '|');
					if (s && s < *condition)
					{
						*text = strchr(s, '}');
						**text = '\0';

						if (!SV_ChatFunc(s+1))
						{
							**text='}';
							continue;
						}
					}

					s = strchr(*condition, '}');
					*s = '\0';

					*text = strchr(s+1, '{')+1;	
					s = strchr(*text, '}');
					*s = '\0';

					*options = strchr(s+1, '{')+1;
					s = strchr(*options, '}');
					*s = '\0';
					return;
				}
			}
		}		
	}
	*text = va("Chat Tag %f not found in file %s", tag, host_client->chat.filename);
	*condition = "";
	*options = "";
	return;
}
示例#4
0
/* <c5b2e> ../engine/tmessage.c:464 */
NOXREF void TextMessageInit(void)
{
	int fileSize;
	unsigned char *pMemFile;

	if (gMessageTable)
	{
		Mem_Free(gMessageTable);
		gMessageTable = NULL;
	}

	pMemFile = COM_LoadTempFile("titles.txt", &fileSize);

	if (pMemFile)
		TextMessageParse(pMemFile, fileSize);
}
示例#5
0
/*
================
Draw_CachePic
================
*/
qpic_t	*Draw_CachePic (const char *path)
{
	cachepic_t	*pic;
	int			i;
	qpic_t		*dat;
	glpic_t		gl;

	for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++)
	{
		if (!strcmp (path, pic->name))
			return &pic->pic;
	}
	if (menu_numcachepics == MAX_CACHED_PICS)
		Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
	menu_numcachepics++;
	strcpy (pic->name, path);

//
// load the pic from disk
//
	dat = (qpic_t *)COM_LoadTempFile (path, NULL);
	if (!dat)
		Sys_Error ("Draw_CachePic: failed to load %s", path);
	SwapPic (dat);

	// HACK HACK HACK --- we need to keep the bytes for
	// the translatable player picture just for the menu
	// configuration dialog
	if (!strcmp (path, "gfx/menuplyr.lmp"))
		memcpy (menuplyr_pixels, dat->data, dat->width*dat->height);

	pic->pic.width = dat->width;
	pic->pic.height = dat->height;

	gl.gltexture = TexMgr_LoadImage (NULL, path, dat->width, dat->height, SRC_INDEXED, dat->data, path,
									  sizeof(int)*2, TEXPREF_ALPHA | TEXPREF_PAD | TEXPREF_NOPICMIP); //johnfitz -- TexMgr
	gl.sl = 0;
	gl.sh = (float)dat->width/(float)TexMgr_PadConditional(dat->width); //johnfitz
	gl.tl = 0;
	gl.th = (float)dat->height/(float)TexMgr_PadConditional(dat->height); //johnfitz
	memcpy (pic->pic.data, &gl, sizeof(glpic_t));

	return &pic->pic;
}
示例#6
0
void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void)
{
	int entnum, style, islight, skin, pflags, effects, type, n;
	char *entfiledata;
	const char *data;
	float origin[3], angles[3], radius, color[3], light[4], fadescale, lightscale, originhack[3], overridecolor[3], vec[4];
	char key[256], value[16384];
	R_ShaderLight_Definition s_light;

	shaderlight = R_DROPLIGHT_MAX_LIGHTS;

	if (cl.worldmodel == NULL)
	{
		Con_Print("No map loaded.\n");
		return;
	}
	// try to load a .ent file first
	COM_StripExtension (cl.worldmodel->name, key);
	strlcat (key, ".ent", sizeof (key));
	data = entfiledata = (char *)COM_LoadTempFile(key);
	// and if that is not found, fall back to the bsp file entity string
	if (!data)
		data = cl.worldmodel->entities;
	if (!data)
		return;
	for (entnum = 0;COM_ParseTokenConsole(&data) && com_token[0] == '{';entnum++)
	{
		type = LIGHTTYPE_MINUSX;
		origin[0] = origin[1] = origin[2] = 0;
		originhack[0] = originhack[1] = originhack[2] = 0;
		angles[0] = angles[1] = angles[2] = 0;
		color[0] = color[1] = color[2] = 1;
		light[0] = light[1] = light[2] = 1;light[3] = 300;
		overridecolor[0] = overridecolor[1] = overridecolor[2] = 1;
		fadescale = 1;
		lightscale = 1;
		style = 0;
		skin = 0;
		pflags = 0;
		effects = 0;
		islight = false;
		while (1)
		{
			if (!COM_ParseTokenConsole(&data))
				break; // error
			if (com_token[0] == '}')
				break; // end of entity
			if (com_token[0] == '_')
				strlcpy(key, com_token + 1, sizeof(key));
			else
				strlcpy(key, com_token, sizeof(key));
			while (key[strlen(key)-1] == ' ') // remove trailing spaces
				key[strlen(key)-1] = 0;
			if (!COM_ParseTokenConsole(&data))
				break; // error
			strlcpy(value, com_token, sizeof(value));

			// now that we have the key pair worked out...
			if (!strcmp("light", key))
			{
				n = sscanf(value, "%f %f %f %f", &vec[0], &vec[1], &vec[2], &vec[3]);
				if (n == 1)
				{
					// quake
					light[0] = vec[0] * (1.0f / 256.0f);
					light[1] = vec[0] * (1.0f / 256.0f);
					light[2] = vec[0] * (1.0f / 256.0f);
					light[3] = vec[0];
				}
				else if (n == 4)
				{
					// halflife
					light[0] = vec[0] * (1.0f / 255.0f);
					light[1] = vec[1] * (1.0f / 255.0f);
					light[2] = vec[2] * (1.0f / 255.0f);
					light[3] = vec[3];
				}
			}
			else if (!strcmp("delay", key))
				type = atoi(value);
			else if (!strcmp("origin", key))
				sscanf(value, "%f %f %f", &origin[0], &origin[1], &origin[2]);
			else if (!strcmp("angle", key))
				angles[0] = 0, angles[1] = atof(value), angles[2] = 0;
			else if (!strcmp("angles", key))
				sscanf(value, "%f %f %f", &angles[0], &angles[1], &angles[2]);
			else if (!strcmp("color", key))
				sscanf(value, "%f %f %f", &color[0], &color[1], &color[2]);
			else if (!strcmp("wait", key))
				fadescale = atof(value);
			else if (!strcmp("classname", key))
			{
				if (!strncmp(value, "light", 5))
				{
					islight = true;
					if (!strcmp(value, "light_fluoro"))
					{
						originhack[0] = 0;
						originhack[1] = 0;
						originhack[2] = 0;
						overridecolor[0] = 1;
						overridecolor[1] = 1;
						overridecolor[2] = 1;
					}
					if (!strcmp(value, "light_fluorospark"))
					{
						originhack[0] = 0;
						originhack[1] = 0;
						originhack[2] = 0;
						overridecolor[0] = 1;
						overridecolor[1] = 1;
						overridecolor[2] = 1;
					}
					if (!strcmp(value, "light_globe"))
					{
						originhack[0] = 0;
						originhack[1] = 0;
						originhack[2] = 0;
						overridecolor[0] = 1.0f;
						overridecolor[1] = 0.8f;
						overridecolor[2] = 0.4f;
					}
					if (!strcmp(value, "light_flame_large_yellow"))
					{
						originhack[0] = 0;
						originhack[1] = 0;
						originhack[2] = 0;
						overridecolor[0] = 1.0f;
						overridecolor[1] = 0.5f;
						overridecolor[2] = 0.1f;
					}
					if (!strcmp(value, "light_flame_small_yellow"))
					{
						originhack[0] = 0;
						originhack[1] = 0;
						originhack[2] = 0;
						overridecolor[0] = 1;
						overridecolor[1] = 0.5f;
						overridecolor[2] = 0.1f;
					}
					if (!strcmp(value, "light_torch_small_white"))
					{
						originhack[0] = 0;
						originhack[1] = 0;
						originhack[2] = 0;
						overridecolor[0] = 1;
						overridecolor[1] = 0.5f;
						overridecolor[2] = 0.1f;
					}
					if (!strcmp(value, "light_torch_small_walltorch"))
					{
						originhack[0] = 0;
						originhack[1] = 0;
						originhack[2] = 0;
						overridecolor[0] = 1;
						overridecolor[1] = 0.5f;
						overridecolor[2] = 0.1f;
					}
				}
			}
			else if (!strcmp("style", key))
				style = atoi(value);
			else if (!strcmp("skin", key))
				skin = (int)atof(value);
			else if (!strcmp("pflags", key))
				pflags = (int)atof(value);
			else if (!strcmp("effects", key))
				effects = (int)atof(value);
/*			else if (cl.worldmodel->type == mod_brushq3)
			{
				if (!strcmp("scale", key))
					lightscale = atof(value);
				if (!strcmp("fade", key))
					fadescale = atof(value);
			}*/
		}
		if (!islight)
			continue;
		if (lightscale <= 0)
			lightscale = 1;
		if (fadescale <= 0)
			fadescale = 1;
		if (color[0] == color[1] && color[0] == color[2])
		{
			color[0] *= overridecolor[0];
			color[1] *= overridecolor[1];
			color[2] *= overridecolor[2];
		}
		radius = light[3] * r_editlights_quakelightsizescale.value * lightscale / fadescale;
		color[0] = color[0] * light[0];
		color[1] = color[1] * light[1];
		color[2] = color[2] * light[2];
		switch (type)
		{
		case LIGHTTYPE_MINUSX:
			break;
		case LIGHTTYPE_RECIPX:
			radius *= 2;
			VectorScale(color, (1.0f / 16.0f), color);
			break;
		case LIGHTTYPE_RECIPXX:
			radius *= 2;
			VectorScale(color, (1.0f / 16.0f), color);
			break;
		default:
		case LIGHTTYPE_NONE:
			break;
		case LIGHTTYPE_SUN:
			break;
		case LIGHTTYPE_MINUSXX:
			break;
		}
		VectorAdd(origin, originhack, origin);
		if (radius >= 1 && shaderlight < R_MIN_SHADER_DLIGHTS)
		{
//			R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), origin, angles, color, radius, (pflags & PFLAGS_CORONA) != 0, style, (pflags & PFLAGS_NOSHADOW) == 0, skin >= 16 ? va("cubemaps/%i", skin) : NULL, 0.25, 0, 1, 1, LIGHTFLAG_REALTIMEMODE);
			VectorCopy (color, s_light.color);
			s_light.maxDistance = radius;
			VectorCopy(origin, s_light.origin);
			VectorCopy(angles, s_light.angles);
			s_light.corona = 0;
			s_light.style = style;
			s_light.shadow = 1;
			sprintf (s_light.cubemapname, skin >= 16 ? va("cubemaps/%i", skin) : "");
			s_light.coronasizescale = 1;
			s_light.ambientscale = 1;
			s_light.diffusescale = 1;
			s_light.specularscale = 1;
			s_light.flags = 0;
			R_Shader_SetLight( shaderlight, &s_light );
			shaderlight++;
		}
	}
//	if (entfiledata)
//		free(entfiledata);
}
示例#7
0
// From DP, edited by Entar
int R_LoadWorldLights(void)
{
	int n, a, style, shadow, flags;
	char tempchar, *lightsstring, *s, *t, name[MAX_QPATH], cubemapname[MAX_QPATH];
	float origin[3], radius, color[3], angles[3], corona, coronasizescale, ambientscale, diffusescale, specularscale;
	R_ShaderLight_Definition light;

	shaderlight = R_DROPLIGHT_MAX_LIGHTS;

	if (cl.worldmodel == NULL)
	{
		Con_Print("No map loaded.\n");
		return false;
	}
	COM_StripExtension (cl.worldmodel->name, name);
	strlcat (name, ".rtlights", sizeof (name));
//	lightsstring = (char *)FS_LoadFile(name, tempmempool, false, NULL);
	lightsstring = (char *)COM_LoadTempFile(name);
	if (lightsstring)
	{
		s = lightsstring;
		n = 0;
		while (*s)
		{
			t = s;
			/*
			shadow = true;
			for (;COM_Parse(t, true) && strcmp(
			if (COM_Parse(t, true))
			{
				if (com_token[0] == '!')
				{
					shadow = false;
					origin[0] = atof(com_token+1);
				}
				else
					origin[0] = atof(com_token);
				if (Com_Parse(t
			}
			*/
			t = s;
			while (*s && *s != '\n' && *s != '\r')
				s++;
			if (!*s)
				break;
			tempchar = *s;
			shadow = true;
			// check for modifier flags
			if (*t == '!')
			{
				shadow = false;
				t++;
			}
			*s = 0;
			a = sscanf(t, "%f %f %f %f %f %f %f %d %s %f %f %f %f %f %f %f %f %i", &origin[0], &origin[1], &origin[2], &radius, &color[0], &color[1], &color[2], &style, cubemapname, &corona, &angles[0], &angles[1], &angles[2], &coronasizescale, &ambientscale, &diffusescale, &specularscale, &flags);
			*s = tempchar;
//			if (a < 18)
//				flags = LIGHTFLAG_REALTIMEMODE;
			if (a < 17)
				specularscale = 1;
			if (a < 16)
				diffusescale = 1;
			if (a < 15)
				ambientscale = 0;
			if (a < 14)
				coronasizescale = 0.25f;
			if (a < 13)
				VectorClear(angles);
			if (a < 10)
				corona = 0;
			if (a < 9 || !strcmp(cubemapname, "\"\""))
				cubemapname[0] = 0;
			// remove quotes on cubemapname
			if (cubemapname[0] == '"' && cubemapname[strlen(cubemapname) - 1] == '"')
			{
				size_t namelen;
				namelen = strlen(cubemapname) - 2;
				memmove(cubemapname, cubemapname + 1, namelen);
				cubemapname[namelen] = '\0';
			}
			if (a < 8)
			{
				Con_Printf("found %d parameters on line %i, should be 8 or more parameters (origin[0] origin[1] origin[2] radius color[0] color[1] color[2] style \"cubemapname\" corona angles[0] angles[1] angles[2] coronasizescale ambientscale diffusescale specularscale flags)\n", a, n + 1);
				break;
			}
			// check if we've hit our limit
			if (shaderlight < R_MIN_SHADER_DLIGHTS)
			{
//				R_Shadow_UpdateWorldLight(R_Shadow_NewWorldLight(), origin, angles, color, radius, corona, style, shadow, cubemapname, coronasizescale, ambientscale, diffusescale, specularscale, flags);
				VectorCopy (color, light.color);
				light.maxDistance = radius;
				VectorCopy(origin, light.origin);
				VectorCopy(angles, light.angles);
				light.corona = corona;
				light.style = style;
				light.shadow = shadow;
				sprintf (light.cubemapname, cubemapname);
				light.coronasizescale = coronasizescale;
				light.ambientscale = ambientscale;
				light.diffusescale = diffusescale;
				light.specularscale = specularscale;
				light.flags = flags;
				R_Shader_SetLight( shaderlight, &light );
				shaderlight++;
			}
			if (*s == '\r')
				s++;
			if (*s == '\n')
				s++;
			n++;
		}
		if (*s)
			Con_Printf("invalid rtlights file \"%s\"\n", name);
//		free(lightsstring);
		return true;
	}
	return false;
}
示例#8
0
/*
=====================
R_InitParticleEffects

  Parse the particle effects out of the script file
=====================
*/
void R_AddEffectsScript(const char *filename) {

//	FILE *fin;
    int token, var, i;
    ParticleEffect_t *effect;
	char *buffer;
	//char	newname[256];
	char* str;

	buffer = (char*) COM_LoadTempFile (filename);

	if (!buffer) {
		Con_Printf("\002Can't load particle effects from: %s\n",filename);
		return;
	}

	SC_Start(buffer,(int)strlen(buffer));

	Con_Printf("Loading particle effects from: %s\n",filename);

    while ( (token = SC_ParseToken()) != TOK_FILE_END) {
    
		if (token == TOK_PARTICLE) {
    		str = SC_ParseIdent();

			//if it already exists just overwrite the old one...
			effect = ParticleEffectDefinedForName(str);
			if (!effect) {
				effect = (ParticleEffect_t *)Hunk_Alloc(sizeof(ParticleEffect_t));			
  				DefaultEffect(effect);
				effect->next = particleEffects;
				particleEffects = effect;
				strcpy(effect->name,str);
				//Con_Printf("effect %s\n",effect->name);
			} else {
				//Con_Printf("redifinition %s\n",effect->name);
			}
			
    		if (SC_ParseToken() != '{') PARSERERROR("'{' expected");
  
  			while ((var = SC_ParseToken()) != '}' && (var != TOK_FILE_END) ) {
  				switch (var) {
					case TOK_EMITTER:
						//parse emmiter shape
						str = SC_ParseIdent();
						
						if (!strcmp(str,"box")) {
							effect->emmiterType = emt_box;
						} else {
							PARSERERROR("Unknown emmiter shape");	
						}

						//parse emmiter values
						for (i=0; i<3; i++)
							effect->emmiterParams1[i] = SC_ParseFloat();
							
						for (i=0; i<3; i++) 
							effect->emmiterParams2[i] = SC_ParseFloat();	
					break;
					case TOK_VELOCITY:
						//parse velocity mins maxs
						for (i=0; i<3; i++)
							effect->velocitymin[i] = SC_ParseFloat();
						for (i=0; i<3; i++) 
							effect->velocitymax[i] = SC_ParseFloat();
					break;
					case TOK_STARTCOLOR:
						//parse color mins maxs
						for (i=0; i<3; i++)
							effect->startcolormin[i] = SC_ParseFloat();
						for (i=0; i<3; i++) 
							effect->startcolormax[i] = SC_ParseFloat();
					break;
					case TOK_ENDCOLOR:
						//parse color mins maxs
						for (i=0; i<3; i++) 
							effect->endcolormin[i] = SC_ParseFloat();
						for (i=0; i<3; i++) 
							effect->endcolormax[i] = SC_ParseFloat();
					break;
					case TOK_LIFETIME:
						//parse lifetime mins maxs
						effect->lifemin = SC_ParseFloat();
						effect->lifemax = SC_ParseFloat();
					break;
					case TOK_FLAGS:
						str = SC_ParseIdent();
					break;
					case TOK_GRAVITY:
						for (i=0; i<3; i++) 
							effect->gravity[i] = SC_ParseFloat();	
					break;
					case TOK_ROTATION:
						effect->rotmin = SC_ParseFloat();
						effect->rotmax = SC_ParseFloat();
					break;
					case TOK_GROW:
						effect->growmin = SC_ParseFloat();
						effect->growmax = SC_ParseFloat();
					break;
					case TOK_SIZE:
						effect->sizemin = SC_ParseFloat();
						effect->sizemax = SC_ParseFloat();
					break;
					case TOK_DRAG:
						for (i=0; i<3; i++) 
							effect->drag[i] = SC_ParseFloat();
					break;
					case TOK_BLENDFUNC:
						effect->srcblend = SC_BlendModeForName(SC_ParseIdent());
						effect->dstblend = SC_BlendModeForName(SC_ParseIdent());
					break;
					case TOK_BOUNCES:
						effect->numbounces = (int)SC_ParseFloat();
					break;
					case TOK_MAP:
						effect->texture = EasyTgaLoad(SC_ParseString());
						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
					break;
					case TOK_ORIENTATION:
						str = SC_ParseIdent();
						if (!strcmp(str,"view")) {
							effect->align = align_view;
						} else if (!strcmp(str,"vel")) {
							//Con_Printf("Velocity aligned\n");
							effect->align = align_vel;
							effect->velscale = SC_ParseFloat();
						} else if (!strcmp(str,"surface")) {
							//Con_Printf("Velocity aligned\n");
							effect->align = align_surf;
						} else {
							Con_Printf("\002Script error at line %i: Unknown orientation type %s\n",line_num,str);	
						}
					break;
					case TOK_ONHIT:
						str = SC_ParseIdent();
						effect->spawn = ParticleEffectForName(str);
						if (!effect->spawn)
							printf("\002Script error at line %i: Particle %s not defined yet \n",line_num,str);
					break;
					default:
						Con_Printf("\002Script error at line %i: Unknown field (id%i/%s) for particle definition\n",line_num,var,str);
				}
  			}
		} else if (token == TOK_DECAL) {
            extern int yylex (void);
            
  			while ((var = yylex()) != '}') {
			//do nothing yet...
  			}	
		} else {
			Con_Printf("\002Script error at line %i: Expected definiton (found id%i/%s)\n",line_num,var,str);
		}
    }

	SC_End();
}
示例#9
0
文件: skin.c 项目: DaneTheory/quake
/*
==========
Skin_Cache

Returns a pointer to the skin bitmap, or NULL to use the default
==========
*/
byte	*Skin_Cache (skin_t *skin)
{
	char	name[1024];
	byte	*raw;
	byte	*out, *pix;
	pcx_t	*pcx;
	int		x, y;
	int		dataByte;
	int		runLength;

	if (cls.downloadtype == dl_skin)
		return NULL;		// use base until downloaded

	if (noskins.value==1) // JACK: So NOSKINS > 1 will show skins, but
		return NULL;	  // not download new ones.

	if (skin->failedload)
		return NULL;

	out = Cache_Check (&skin->cache);
	if (out)
		return out;

//
// load the pic from disk
//
	sprintf (name, "skins/%s.pcx", skin->name);
	raw = COM_LoadTempFile (name);
	if (!raw)
	{
		Con_Printf ("Couldn't load skin %s\n", name);
		sprintf (name, "skins/%s.pcx", baseskin.string);
		raw = COM_LoadTempFile (name);
		if (!raw)
		{
			skin->failedload = true;
			return NULL;
		}
	}

//
// parse the PCX file
//
	pcx = (pcx_t *)raw;
	raw = &pcx->data;

	if (pcx->manufacturer != 0x0a
		|| pcx->version != 5
		|| pcx->encoding != 1
		|| pcx->bits_per_pixel != 8
		|| pcx->xmax >= 320
		|| pcx->ymax >= 200)
	{
		skin->failedload = true;
		Con_Printf ("Bad skin %s\n", name);
		return NULL;
	}
	
	out = Cache_Alloc (&skin->cache, 320*200, skin->name);
	if (!out)
		Sys_Error ("Skin_Cache: couldn't allocate");

	pix = out;
	memset (out, 0, 320*200);

	for (y=0 ; y<pcx->ymax ; y++, pix += 320)
	{
		for (x=0 ; x<=pcx->xmax ; )
		{
			if (raw - (byte*)pcx > com_filesize) 
			{
				Cache_Free (&skin->cache);
				skin->failedload = true;
				Con_Printf ("Skin %s was malformed.  You should delete it.\n", name);
				return NULL;
			}
			dataByte = *raw++;

			if((dataByte & 0xC0) == 0xC0)
			{
				runLength = dataByte & 0x3F;
				if (raw - (byte*)pcx > com_filesize) 
				{
					Cache_Free (&skin->cache);
					skin->failedload = true;
					Con_Printf ("Skin %s was malformed.  You should delete it.\n", name);
					return NULL;
				}
				dataByte = *raw++;
			}
			else
				runLength = 1;

			// skin sanity check
			if (runLength + x > pcx->xmax + 2) {
				Cache_Free (&skin->cache);
				skin->failedload = true;
				Con_Printf ("Skin %s was malformed.  You should delete it.\n", name);
				return NULL;
			}
			while(runLength-- > 0)
				pix[x++] = dataByte;
		}

	}

	if ( raw - (byte *)pcx > com_filesize)
	{
		Cache_Free (&skin->cache);
		skin->failedload = true;
		Con_Printf ("Skin %s was malformed.  You should delete it.\n", name);
		return NULL;
	}

	skin->failedload = false;

	return out;
}