From fc70d429bbce489001aae57ba5f6b76a96995d96 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 18 Jan 2001 10:20:36 +0000 Subject: [PATCH] skin.c: Rip out the pcx loading code and use LoadPCX instead. pcx.h: remove the data field from pcx_t: it was messing with gcc's idea of the structure size. also, update LoadPCX's prototype pcx.c: change LoadPCX to return tex_t (new type in texture.h) and take a new param: convert. LoadPCX will now wither load raw 8 bit or convert to rgba on loading depending on convert. Also, make LoadPCX WORK and use Hunk_TempAlloc to store the resulting texture. texture.h: define tex_t. defines an in-memory texture (either 8 or 32 bit, depending on the presense of a palette). Data comes immediately after the sturcture. eg tex_t *tex = Hunk_TempAlloc (sizeof (tex_t) + count) --- include/pcx.h | 3 +- include/texture.h | 47 +++++++++++++++++++ source/pcx.c | 84 +++++++++++++++++++++++---------- source/skin.c | 117 +++++++++------------------------------------- 4 files changed, 129 insertions(+), 122 deletions(-) create mode 100644 include/texture.h diff --git a/include/pcx.h b/include/pcx.h index 5427b43..9a989d6 100644 --- a/include/pcx.h +++ b/include/pcx.h @@ -45,12 +45,11 @@ typedef struct unsigned short bytes_per_line; unsigned short palette_type; char filler[58]; - unsigned char data; // unbounded } pcx_t; void WritePCXfile (char *filename, byte * data, int width, int height, int rowbytes, byte * palette, qboolean upload, qboolean flip); -void LoadPCX (QFile *f); +struct tex_s *LoadPCX (QFile *f, int convert); // tex is from Hunk_TempAlloc #endif // __pcx_h diff --git a/include/texture.h b/include/texture.h new file mode 100644 index 0000000..c9458b3 --- /dev/null +++ b/include/texture.h @@ -0,0 +1,47 @@ +/* + texture.h + + texture definition + + Copyright (C) 2000 Bill Currie + + Author: Bill Currie + Date: 2000-01-18 + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifndef __texture_h +#define __texture_h + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +// could not use texture_t as that is used for models. +typedef struct tex_s { + int width; + int height; + unsigned char *palette; // 0 = 32 bit, otherise 8 + unsigned char data[ZERO_LENGTH_ARRAY]; +} tex_t; + +#endif // __texture_h diff --git a/source/pcx.c b/source/pcx.c index dbcb1c5..1114add 100644 --- a/source/pcx.c +++ b/source/pcx.c @@ -39,26 +39,27 @@ #include "cl_parse.h" #include "console.h" +#include "host.h" #include "pcx.h" #include "qendian.h" #include "qtypes.h" #include "quakefs.h" +#include "texture.h" #include "zone.h" -byte *pcx_rgb; - /* LoadPCX */ -void -LoadPCX (QFile *f) +tex_t * +LoadPCX (QFile *f, int convert) { pcx_t *pcx, pcxbuf; byte palette[768]; byte *pix; int x, y; - int dataByte, runLength; + int dataByte, runLength = 1; int count; + tex_t *tex; // // parse the PCX file @@ -81,39 +82,74 @@ LoadPCX (QFile *f) || pcx->encoding != 1 || pcx->bits_per_pixel != 8 || pcx->xmax >= 320 || pcx->ymax >= 256) { Con_Printf ("Bad pcx file\n"); - return; + return 0; } - // seek to palette - Qseek (f, -768, SEEK_END); - Qread (f, palette, 768); - Qseek (f, sizeof (pcxbuf) - 4, SEEK_SET); + if (convert) { + // seek to palette + Qseek (f, -768, SEEK_END); + Qread (f, palette, 768); + } + + Qseek (f, sizeof (pcxbuf), SEEK_SET); count = (pcx->xmax + 1) * (pcx->ymax + 1); - pcx_rgb = malloc (count * 4); + if (convert) + count *= 4; + tex = Hunk_TempAlloc (sizeof (tex_t) + count); + tex->width = pcx->xmax + 1; + tex->height = pcx->ymax + 1; + if (convert) { + tex->palette = 0; + } else { + tex->palette = host_basepal; + } + pix = tex->data; - for (y = 0; y <= pcx->ymax; y++) { - pix = pcx_rgb + 4 * y * (pcx->xmax + 1); - for (x = 0; x <= pcx->ymax;) { + for (y = 0; y < tex->height; y++) { + for (x = 0; x < tex->width;) { + runLength = 1; dataByte = Qgetc (f); + if (dataByte == EOF) + break; if ((dataByte & 0xC0) == 0xC0) { runLength = dataByte & 0x3F; dataByte = Qgetc (f); - } else { - runLength = 1; + if (dataByte == EOF) + break; } - while (runLength-- > 0) { - pix[0] = palette[dataByte * 3]; - pix[1] = palette[dataByte * 3 + 1]; - pix[2] = palette[dataByte * 3 + 2]; - pix[3] = 255; - pix += 4; - x++; + if (convert) { + while (count && runLength > 0) { + pix[0] = palette[dataByte * 3]; + pix[1] = palette[dataByte * 3 + 1]; + pix[2] = palette[dataByte * 3 + 2]; + pix[3] = 255; + pix += 4; + count -= 4; + runLength--; + x++; + } + } else { + while (count && runLength > 0) { + *pix++ = dataByte; + count--; + runLength--; + x++; + } } + if (runLength) + break; } + if (runLength) + break; } + if (count || runLength) { + Con_Printf ("PCX was malformed. You should delete it.\n"); + return 0; + } + return tex; } /* @@ -150,7 +186,7 @@ WritePCXfile (char *filename, byte * data, int width, int height, memset (pcx->filler, 0, sizeof (pcx->filler)); // pack the image - pack = &pcx->data; + pack = (byte*)&pcx[1]; if (flip) data += rowbytes * (height - 1); diff --git a/source/skin.c b/source/skin.c index efd2796..11e7b40 100644 --- a/source/skin.c +++ b/source/skin.c @@ -47,6 +47,7 @@ #include "screen.h" #include "skin.h" #include "sys.h" +#include "texture.h" #include "va.h" cvar_t *baseskin; @@ -62,13 +63,10 @@ skin_t skins[MAX_CACHED_SKINS]; int numskins; /* -================ -Skin_Find + Skin_Find - Determines the best skin for the given scoreboard - slot, and sets scoreboard->skin - -================ + Determines the best skin for the given scoreboard + slot, and sets scoreboard->skin */ void Skin_Find (player_info_t *sc) @@ -116,22 +114,17 @@ Skin_Find (player_info_t *sc) /* -========== -Skin_Cache + Skin_Cache -Returns a pointer to the skin bitmap, or NULL to use the default -========== + 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; + byte *out; + QFile *file; + tex_t *tex; if (cls.downloadtype == dl_skin) return NULL; // use base until downloaded @@ -149,34 +142,19 @@ Skin_Cache (skin_t *skin) // load the pic from disk snprintf (name, sizeof (name), "skins/%s.pcx", skin->name); - raw = COM_LoadTempFile (name); - if (!raw) { + COM_FOpenFile (name, &file); + if (!file) { Con_Printf ("Couldn't load skin %s\n", name); snprintf (name, sizeof (name), "skins/%s.pcx", baseskin->string); - raw = COM_LoadTempFile (name); - if (!raw) { + COM_FOpenFile (name, &file); + if (!file) { skin->failedload = true; return NULL; } } + tex = LoadPCX (file, 0); - // parse the PCX file - pcx = (pcx_t *) raw; - raw = &pcx->data; - - pcx->xmax = LittleShort (pcx->xmax); - pcx->xmin = LittleShort (pcx->xmin); - pcx->ymax = LittleShort (pcx->ymax); - pcx->ymin = LittleShort (pcx->ymin); - pcx->hres = LittleShort (pcx->hres); - pcx->vres = LittleShort (pcx->vres); - pcx->bytes_per_line = LittleShort (pcx->bytes_per_line); - pcx->palette_type = LittleShort (pcx->palette_type); - - if (pcx->manufacturer != 0x0a - || pcx->version != 5 - || pcx->encoding != 1 - || pcx->bits_per_pixel != 8 || pcx->xmax >= 320 || pcx->ymax >= 200) { + if (!tex || tex->width > 320 || tex->height > 200) { skin->failedload = true; Con_Printf ("Bad skin %s\n", name); return NULL; @@ -186,54 +164,7 @@ Skin_Cache (skin_t *skin) 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; - } + memcpy (out, tex->data, tex->width * tex->height); skin->failedload = false; @@ -242,9 +173,7 @@ Skin_Cache (skin_t *skin) /* -================= -Skin_NextDownload -================= + Skin_NextDownload */ void Skin_NextDownload (void) @@ -289,11 +218,9 @@ Skin_NextDownload (void) /* -========== -Skin_Skins_f + Skin_Skins_f -Refind all skins, downloading if needed. -========== + Refind all skins, downloading if needed. */ void Skin_Skins_f (void) @@ -313,11 +240,9 @@ Skin_Skins_f (void) /* -========== -Skin_AllSkins_f + Skin_AllSkins_f -Sets all skins to one specific one -========== + Sets all skins to one specific one */ void Skin_AllSkins_f (void)