home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quakeworld_src / client / skin.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-17  |  6.3 KB  |  305 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20.  
  21. #include "quakedef.h"
  22.  
  23. cvar_t    baseskin = {"baseskin", "base"};
  24. cvar_t    noskins = {"noskins", "0"};
  25.  
  26. char    allskins[128];
  27. #define MAX_CACHED_SKINS    128
  28. skin_t    skins[MAX_CACHED_SKINS];
  29. int     numskins;
  30.  
  31. /*
  32. ================
  33. Skin_Find
  34.  
  35.   Determines the best skin for the given scoreboard
  36.   slot, and sets scoreboard->skin
  37.  
  38. ================
  39. */
  40. void Skin_Find (player_info_t *sc)
  41. {
  42.   skin_t    *skin;
  43.   int     i;
  44.   char    name[128], *s;
  45.  
  46.   if (allskins[0])
  47.     strcpy (name, allskins);
  48.   else
  49.   {
  50.     s = Info_ValueForKey (sc->userinfo, "skin");
  51.     if (s && s[0])
  52.       strcpy (name, s);
  53.     else
  54.       strcpy (name, baseskin.string);
  55.   }
  56.  
  57.   if (strstr (name, "..") || *name == '.')
  58.     strcpy (name, "base");
  59.  
  60.   COM_StripExtension (name, name);
  61.  
  62.   for (i=0 ; i<numskins ; i++)
  63.   {
  64.     if (!strcmp (name, skins[i].name))
  65.     {
  66.       sc->skin = &skins[i];
  67.       Skin_Cache (sc->skin);
  68.       return;
  69.     }
  70.   }
  71.  
  72.   if (numskins == MAX_CACHED_SKINS)
  73.   { // ran out of spots, so flush everything
  74.     Skin_Skins_f ();
  75.     return;
  76.   }
  77.  
  78.   skin = &skins[numskins];
  79.   sc->skin = skin;
  80.   numskins++;
  81.  
  82.   memset (skin, 0, sizeof(*skin));
  83.   strncpy(skin->name, name, sizeof(skin->name) - 1);
  84. }
  85.  
  86.  
  87. /*
  88. ==========
  89. Skin_Cache
  90.  
  91. Returns a pointer to the skin bitmap, or NULL to use the default
  92. ==========
  93. */
  94. byte  *Skin_Cache (skin_t *skin)
  95. {
  96.   char  name[1024];
  97.   byte  *raw;
  98.   byte  *out, *pix;
  99.   pcx_t *pcx;
  100.   int   x, y;
  101.   int   dataByte;
  102.   int   runLength;
  103.  
  104.   if (cls.downloadtype == dl_skin)
  105.     return NULL;    // use base until downloaded
  106.  
  107.   if (noskins.value==1) // JACK: So NOSKINS > 1 will show skins, but
  108.     return NULL;    // not download new ones.
  109.  
  110.   if (skin->failedload)
  111.     return NULL;
  112.  
  113.   out = Cache_Check (&skin->cache);
  114.   if (out)
  115.     return out;
  116.  
  117. //
  118. // load the pic from disk
  119. //
  120.   sprintf (name, "skins/%s.pcx", skin->name);
  121.   raw = COM_LoadTempFile (name);
  122.   if (!raw)
  123.   {
  124.     Con_Printf ("Couldn't load skin %s\n", name);
  125.     sprintf (name, "skins/%s.pcx", baseskin.string);
  126.     raw = COM_LoadTempFile (name);
  127.     if (!raw)
  128.     {
  129.       skin->failedload = true;
  130.       return NULL;
  131.     }
  132.   }
  133.  
  134. //
  135. // parse the PCX file
  136. //
  137.   pcx = (pcx_t *)raw;
  138.   raw = &pcx->data;
  139.  
  140.   /* Bug fix! PCX uses little endian format! (phx) */
  141.   if (pcx->manufacturer != 0x0a
  142.     || pcx->version != 5
  143.     || pcx->encoding != 1
  144.     || pcx->bits_per_pixel != 8
  145.     || (unsigned short)LittleShort(pcx->xmax) >= 320
  146.     || (unsigned short)LittleShort(pcx->ymax) >= 200)
  147.   {
  148.     skin->failedload = true;
  149.     Con_Printf ("Bad skin %s\n", name);
  150.     return NULL;
  151.   }
  152.   
  153.   out = Cache_Alloc (&skin->cache, 320*200, skin->name);
  154.   if (!out)
  155.     Sys_Error ("Skin_Cache: couldn't allocate");
  156.  
  157.   pix = out;
  158.   memset (out, 0, 320*200);
  159.  
  160.   /* Bug fix! PCX uses little endian format! (phx) */
  161.   for (y=0 ; y<LittleShort(pcx->ymax) ; y++, pix += 320)
  162.   {
  163.     for (x=0 ; x<=LittleShort(pcx->xmax) ; )
  164.     {
  165.       if (raw - (byte*)pcx > com_filesize) 
  166.       {
  167.         Cache_Free (&skin->cache);
  168.         skin->failedload = true;
  169.         Con_Printf ("Skin %s was malformed.  You should delete it.\n", name);
  170.         return NULL;
  171.       }
  172.       dataByte = *raw++;
  173.  
  174.       if((dataByte & 0xC0) == 0xC0)
  175.       {
  176.         runLength = dataByte & 0x3F;
  177.         if (raw - (byte*)pcx > com_filesize) 
  178.         {
  179.           Cache_Free (&skin->cache);
  180.           skin->failedload = true;
  181.           Con_Printf ("Skin %s was malformed.  You should delete it.\n", name);
  182.           return NULL;
  183.         }
  184.         dataByte = *raw++;
  185.       }
  186.       else
  187.         runLength = 1;
  188.  
  189.       // skin sanity check
  190.       /* Bug fix! PCX uses little endian format! (phx) */
  191.       if (runLength + x > LittleShort(pcx->xmax) + 2) {
  192.         Cache_Free (&skin->cache);
  193.         skin->failedload = true;
  194.         Con_Printf ("Skin %s was malformed.  You should delete it.\n", name);
  195.         return NULL;
  196.       }
  197.       while(runLength-- > 0)
  198.         pix[x++] = dataByte;
  199.     }
  200.  
  201.   }
  202.  
  203.   if ( raw - (byte *)pcx > com_filesize)
  204.   {
  205.     Cache_Free (&skin->cache);
  206.     skin->failedload = true;
  207.     Con_Printf ("Skin %s was malformed.  You should delete it.\n", name);
  208.     return NULL;
  209.   }
  210.  
  211.   skin->failedload = false;
  212.  
  213.   return out;
  214. }
  215.  
  216.  
  217. /*
  218. =================
  219. Skin_NextDownload
  220. =================
  221. */
  222. void Skin_NextDownload (void)
  223. {
  224.   player_info_t *sc;
  225.   int     i;
  226.  
  227.   if (cls.downloadnumber == 0)
  228.     Con_Printf ("Checking skins...\n");
  229.   cls.downloadtype = dl_skin;
  230.  
  231.   for ( 
  232.     ; cls.downloadnumber != MAX_CLIENTS
  233.     ; cls.downloadnumber++)
  234.   {
  235.     sc = &cl.players[cls.downloadnumber];
  236.     if (!sc->name[0])
  237.       continue;
  238.     Skin_Find (sc);
  239.     if (noskins.value)
  240.       continue;
  241.     if (!CL_CheckOrDownloadFile(va("skins/%s.pcx", sc->skin->name)))
  242.       return;   // started a download
  243.   }
  244.  
  245.   cls.downloadtype = dl_none;
  246.  
  247.   // now load them in for real
  248.   for (i=0 ; i<MAX_CLIENTS ; i++)
  249.   {
  250.     sc = &cl.players[i];
  251.     if (!sc->name[0])
  252.       continue;
  253.     Skin_Cache (sc->skin);
  254. #ifdef GLQUAKE
  255.     sc->skin = NULL;
  256. #endif
  257.   }
  258.  
  259.   if (cls.state != ca_active)
  260.   { // get next signon phase
  261.     MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
  262.     MSG_WriteString (&cls.netchan.message,
  263.       va("begin %i", cl.servercount));
  264.     Cache_Report ();    // print remaining memory
  265.   }
  266. }
  267.  
  268.  
  269. /*
  270. ==========
  271. Skin_Skins_f
  272.  
  273. Refind all skins, downloading if needed.
  274. ==========
  275. */
  276. void  Skin_Skins_f (void)
  277. {
  278.   int   i;
  279.  
  280.   for (i=0 ; i<numskins ; i++)
  281.   {
  282.     if (skins[i].cache.data)
  283.       Cache_Free (&skins[i].cache);
  284.   }
  285.   numskins = 0;
  286.  
  287.   cls.downloadnumber = 0;
  288.   cls.downloadtype = dl_skin;
  289.   Skin_NextDownload ();
  290. }
  291.  
  292.  
  293. /*
  294. ==========
  295. Skin_AllSkins_f
  296.  
  297. Sets all skins to one specific one
  298. ==========
  299. */
  300. void  Skin_AllSkins_f (void)
  301. {
  302.   strcpy (allskins, Cmd_Argv(1));
  303.   Skin_Skins_f ();
  304. }
  305.