skin.c 5.7 KB

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