diff options
Diffstat (limited to 'QW/client/skin.c')
| -rw-r--r-- | QW/client/skin.c | 301 |
1 files changed, 301 insertions, 0 deletions
diff --git a/QW/client/skin.c b/QW/client/skin.c new file mode 100644 index 0000000..ad90d53 --- /dev/null +++ b/QW/client/skin.c @@ -0,0 +1,301 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program 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. + +This program 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 program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "quakedef.h" + +cvar_t baseskin = {"baseskin", "base"}; +cvar_t noskins = {"noskins", "0"}; + +char allskins[128]; +#define MAX_CACHED_SKINS 128 +skin_t skins[MAX_CACHED_SKINS]; +int numskins; + +/* +================ +Skin_Find + + Determines the best skin for the given scoreboard + slot, and sets scoreboard->skin + +================ +*/ +void Skin_Find (player_info_t *sc) +{ + skin_t *skin; + int i; + char name[128], *s; + + if (allskins[0]) + strcpy (name, allskins); + else + { + s = Info_ValueForKey (sc->userinfo, "skin"); + if (s && s[0]) + strcpy (name, s); + else + strcpy (name, baseskin.string); + } + + if (strstr (name, "..") || *name == '.') + strcpy (name, "base"); + + COM_StripExtension (name, name); + + for (i=0 ; i<numskins ; i++) + { + if (!strcmp (name, skins[i].name)) + { + sc->skin = &skins[i]; + Skin_Cache (sc->skin); + return; + } + } + + if (numskins == MAX_CACHED_SKINS) + { // ran out of spots, so flush everything + Skin_Skins_f (); + return; + } + + skin = &skins[numskins]; + sc->skin = skin; + numskins++; + + memset (skin, 0, sizeof(*skin)); + strncpy(skin->name, name, sizeof(skin->name) - 1); +} + + +/* +========== +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; +} + + +/* +================= +Skin_NextDownload +================= +*/ +void Skin_NextDownload (void) +{ + player_info_t *sc; + int i; + + if (cls.downloadnumber == 0) + Con_Printf ("Checking skins...\n"); + cls.downloadtype = dl_skin; + + for ( + ; cls.downloadnumber != MAX_CLIENTS + ; cls.downloadnumber++) + { + sc = &cl.players[cls.downloadnumber]; + if (!sc->name[0]) + continue; + Skin_Find (sc); + if (noskins.value) + continue; + if (!CL_CheckOrDownloadFile(va("skins/%s.pcx", sc->skin->name))) + return; // started a download + } + + cls.downloadtype = dl_none; + + // now load them in for real + for (i=0 ; i<MAX_CLIENTS ; i++) + { + sc = &cl.players[i]; + if (!sc->name[0]) + continue; + Skin_Cache (sc->skin); +#ifdef GLQUAKE + sc->skin = NULL; +#endif + } + + if (cls.state != ca_active) + { // get next signon phase + MSG_WriteByte (&cls.netchan.message, clc_stringcmd); + MSG_WriteString (&cls.netchan.message, + va("begin %i", cl.servercount)); + Cache_Report (); // print remaining memory + } +} + + +/* +========== +Skin_Skins_f + +Refind all skins, downloading if needed. +========== +*/ +void Skin_Skins_f (void) +{ + int i; + + for (i=0 ; i<numskins ; i++) + { + if (skins[i].cache.data) + Cache_Free (&skins[i].cache); + } + numskins = 0; + + cls.downloadnumber = 0; + cls.downloadtype = dl_skin; + Skin_NextDownload (); +} + + +/* +========== +Skin_AllSkins_f + +Sets all skins to one specific one +========== +*/ +void Skin_AllSkins_f (void) +{ + strcpy (allskins, Cmd_Argv(1)); + Skin_Skins_f (); +} |
