home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 14 / MA_Cover_14.iso / source / c / q1source_amy / qw / client / skin.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-21  |  5.7 KB  |  302 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.     if (pcx->manufacturer != 0x0a
  141.         || pcx->version != 5
  142.         || pcx->encoding != 1
  143.         || pcx->bits_per_pixel != 8
  144.         || pcx->xmax >= 320
  145.         || pcx->ymax >= 200)
  146.     {
  147.         skin->failedload = true;
  148.         Con_Printf ("Bad skin %s\n", name);
  149.         return NULL;
  150.     }
  151.     
  152.     out = Cache_Alloc (&skin->cache, 320*200, skin->name);
  153.     if (!out)
  154.         Sys_Error ("Skin_Cache: couldn't allocate");
  155.  
  156.     pix = out;
  157.     memset (out, 0, 320*200);
  158.  
  159.     for (y=0 ; y<pcx->ymax ; y++, pix += 320)
  160.     {
  161.         for (x=0 ; x<=pcx->xmax ; )
  162.         {
  163.             if (raw - (byte*)pcx > com_filesize) 
  164.             {
  165.                 Cache_Free (&skin->cache);
  166.                 skin->failedload = true;
  167.                 Con_Printf ("Skin %s was malformed.  You should delete it.\n", name);
  168.                 return NULL;
  169.             }
  170.             dataByte = *raw++;
  171.  
  172.             if((dataByte & 0xC0) == 0xC0)
  173.             {
  174.                 runLength = dataByte & 0x3F;
  175.                 if (raw - (byte*)pcx > com_filesize) 
  176.                 {
  177.                     Cache_Free (&skin->cache);
  178.                     skin->failedload = true;
  179.                     Con_Printf ("Skin %s was malformed.  You should delete it.\n", name);
  180.                     return NULL;
  181.                 }
  182.                 dataByte = *raw++;
  183.             }
  184.             else
  185.                 runLength = 1;
  186.  
  187.             // skin sanity check
  188.             if (runLength + x > pcx->xmax + 2) {
  189.                 Cache_Free (&skin->cache);
  190.                 skin->failedload = true;
  191.                 Con_Printf ("Skin %s was malformed.  You should delete it.\n", name);
  192.                 return NULL;
  193.             }
  194.             while(runLength-- > 0)
  195.                 pix[x++] = dataByte;
  196.         }
  197.  
  198.     }
  199.  
  200.     if ( raw - (byte *)pcx > com_filesize)
  201.     {
  202.         Cache_Free (&skin->cache);
  203.         skin->failedload = true;
  204.         Con_Printf ("Skin %s was malformed.  You should delete it.\n", name);
  205.         return NULL;
  206.     }
  207.  
  208.     skin->failedload = false;
  209.  
  210.     return out;
  211. }
  212.  
  213.  
  214. /*
  215. =================
  216. Skin_NextDownload
  217. =================
  218. */
  219. void Skin_NextDownload (void)
  220. {
  221.     player_info_t    *sc;
  222.     int            i;
  223.  
  224.     if (cls.downloadnumber == 0)
  225.         Con_Printf ("Checking skins...\n");
  226.     cls.downloadtype = dl_skin;
  227.  
  228.     for ( 
  229.         ; cls.downloadnumber != MAX_CLIENTS
  230.         ; cls.downloadnumber++)
  231.     {
  232.         sc = &cl.players[cls.downloadnumber];
  233.         if (!sc->name[0])
  234.             continue;
  235.         Skin_Find (sc);
  236.         if (noskins.value)
  237.             continue;
  238.         if (!CL_CheckOrDownloadFile(va("skins/%s.pcx", sc->skin->name)))
  239.             return;        // started a download
  240.     }
  241.  
  242.     cls.downloadtype = dl_none;
  243.  
  244.     // now load them in for real
  245.     for (i=0 ; i<MAX_CLIENTS ; i++)
  246.     {
  247.         sc = &cl.players[i];
  248.         if (!sc->name[0])
  249.             continue;
  250.         Skin_Cache (sc->skin);
  251. #ifdef GLQUAKE
  252.         sc->skin = NULL;
  253. #endif
  254.     }
  255.  
  256.     if (cls.state != ca_active)
  257.     {    // get next signon phase
  258.         MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
  259.         MSG_WriteString (&cls.netchan.message,
  260.             va("begin %i", cl.servercount));
  261.         Cache_Report ();        // print remaining memory
  262.     }
  263. }
  264.  
  265.  
  266. /*
  267. ==========
  268. Skin_Skins_f
  269.  
  270. Refind all skins, downloading if needed.
  271. ==========
  272. */
  273. void    Skin_Skins_f (void)
  274. {
  275.     int        i;
  276.  
  277.     for (i=0 ; i<numskins ; i++)
  278.     {
  279.         if (skins[i].cache.data)
  280.             Cache_Free (&skins[i].cache);
  281.     }
  282.     numskins = 0;
  283.  
  284.     cls.downloadnumber = 0;
  285.     cls.downloadtype = dl_skin;
  286.     Skin_NextDownload ();
  287. }
  288.  
  289.  
  290. /*
  291. ==========
  292. Skin_AllSkins_f
  293.  
  294. Sets all skins to one specific one
  295. ==========
  296. */
  297. void    Skin_AllSkins_f (void)
  298. {
  299.     strcpy (allskins, Cmd_Argv(1));
  300.     Skin_Skins_f ();
  301. }
  302.