mirror of
https://git.code.sf.net/p/quake/newtree
synced 2024-11-24 21:12:27 +00:00
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)
This commit is contained in:
parent
6aecae38e6
commit
fc70d429bb
4 changed files with 129 additions and 122 deletions
|
@ -45,12 +45,11 @@ typedef struct
|
||||||
unsigned short bytes_per_line;
|
unsigned short bytes_per_line;
|
||||||
unsigned short palette_type;
|
unsigned short palette_type;
|
||||||
char filler[58];
|
char filler[58];
|
||||||
unsigned char data; // unbounded
|
|
||||||
} pcx_t;
|
} pcx_t;
|
||||||
|
|
||||||
void WritePCXfile (char *filename, byte * data, int width, int height,
|
void WritePCXfile (char *filename, byte * data, int width, int height,
|
||||||
int rowbytes, byte * palette, qboolean upload,
|
int rowbytes, byte * palette, qboolean upload,
|
||||||
qboolean flip);
|
qboolean flip);
|
||||||
void LoadPCX (QFile *f);
|
struct tex_s *LoadPCX (QFile *f, int convert); // tex is from Hunk_TempAlloc
|
||||||
|
|
||||||
#endif // __pcx_h
|
#endif // __pcx_h
|
||||||
|
|
47
include/texture.h
Normal file
47
include/texture.h
Normal file
|
@ -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
|
84
source/pcx.c
84
source/pcx.c
|
@ -39,26 +39,27 @@
|
||||||
|
|
||||||
#include "cl_parse.h"
|
#include "cl_parse.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
|
#include "host.h"
|
||||||
#include "pcx.h"
|
#include "pcx.h"
|
||||||
#include "qendian.h"
|
#include "qendian.h"
|
||||||
#include "qtypes.h"
|
#include "qtypes.h"
|
||||||
#include "quakefs.h"
|
#include "quakefs.h"
|
||||||
|
#include "texture.h"
|
||||||
#include "zone.h"
|
#include "zone.h"
|
||||||
|
|
||||||
byte *pcx_rgb;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
LoadPCX
|
LoadPCX
|
||||||
*/
|
*/
|
||||||
void
|
tex_t *
|
||||||
LoadPCX (QFile *f)
|
LoadPCX (QFile *f, int convert)
|
||||||
{
|
{
|
||||||
pcx_t *pcx, pcxbuf;
|
pcx_t *pcx, pcxbuf;
|
||||||
byte palette[768];
|
byte palette[768];
|
||||||
byte *pix;
|
byte *pix;
|
||||||
int x, y;
|
int x, y;
|
||||||
int dataByte, runLength;
|
int dataByte, runLength = 1;
|
||||||
int count;
|
int count;
|
||||||
|
tex_t *tex;
|
||||||
|
|
||||||
//
|
//
|
||||||
// parse the PCX file
|
// parse the PCX file
|
||||||
|
@ -81,39 +82,74 @@ LoadPCX (QFile *f)
|
||||||
|| pcx->encoding != 1
|
|| pcx->encoding != 1
|
||||||
|| pcx->bits_per_pixel != 8 || pcx->xmax >= 320 || pcx->ymax >= 256) {
|
|| pcx->bits_per_pixel != 8 || pcx->xmax >= 320 || pcx->ymax >= 256) {
|
||||||
Con_Printf ("Bad pcx file\n");
|
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);
|
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++) {
|
for (y = 0; y < tex->height; y++) {
|
||||||
pix = pcx_rgb + 4 * y * (pcx->xmax + 1);
|
for (x = 0; x < tex->width;) {
|
||||||
for (x = 0; x <= pcx->ymax;) {
|
runLength = 1;
|
||||||
dataByte = Qgetc (f);
|
dataByte = Qgetc (f);
|
||||||
|
if (dataByte == EOF)
|
||||||
|
break;
|
||||||
|
|
||||||
if ((dataByte & 0xC0) == 0xC0) {
|
if ((dataByte & 0xC0) == 0xC0) {
|
||||||
runLength = dataByte & 0x3F;
|
runLength = dataByte & 0x3F;
|
||||||
dataByte = Qgetc (f);
|
dataByte = Qgetc (f);
|
||||||
} else {
|
if (dataByte == EOF)
|
||||||
runLength = 1;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (runLength-- > 0) {
|
if (convert) {
|
||||||
pix[0] = palette[dataByte * 3];
|
while (count && runLength > 0) {
|
||||||
pix[1] = palette[dataByte * 3 + 1];
|
pix[0] = palette[dataByte * 3];
|
||||||
pix[2] = palette[dataByte * 3 + 2];
|
pix[1] = palette[dataByte * 3 + 1];
|
||||||
pix[3] = 255;
|
pix[2] = palette[dataByte * 3 + 2];
|
||||||
pix += 4;
|
pix[3] = 255;
|
||||||
x++;
|
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));
|
memset (pcx->filler, 0, sizeof (pcx->filler));
|
||||||
|
|
||||||
// pack the image
|
// pack the image
|
||||||
pack = &pcx->data;
|
pack = (byte*)&pcx[1];
|
||||||
|
|
||||||
if (flip)
|
if (flip)
|
||||||
data += rowbytes * (height - 1);
|
data += rowbytes * (height - 1);
|
||||||
|
|
117
source/skin.c
117
source/skin.c
|
@ -47,6 +47,7 @@
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "skin.h"
|
#include "skin.h"
|
||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
|
#include "texture.h"
|
||||||
#include "va.h"
|
#include "va.h"
|
||||||
|
|
||||||
cvar_t *baseskin;
|
cvar_t *baseskin;
|
||||||
|
@ -62,13 +63,10 @@ skin_t skins[MAX_CACHED_SKINS];
|
||||||
int numskins;
|
int numskins;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================
|
Skin_Find
|
||||||
Skin_Find
|
|
||||||
|
|
||||||
Determines the best skin for the given scoreboard
|
Determines the best skin for the given scoreboard
|
||||||
slot, and sets scoreboard->skin
|
slot, and sets scoreboard->skin
|
||||||
|
|
||||||
================
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
Skin_Find (player_info_t *sc)
|
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 *
|
byte *
|
||||||
Skin_Cache (skin_t *skin)
|
Skin_Cache (skin_t *skin)
|
||||||
{
|
{
|
||||||
char name[1024];
|
char name[1024];
|
||||||
byte *raw;
|
byte *out;
|
||||||
byte *out, *pix;
|
QFile *file;
|
||||||
pcx_t *pcx;
|
tex_t *tex;
|
||||||
int x, y;
|
|
||||||
int dataByte;
|
|
||||||
int runLength;
|
|
||||||
|
|
||||||
if (cls.downloadtype == dl_skin)
|
if (cls.downloadtype == dl_skin)
|
||||||
return NULL; // use base until downloaded
|
return NULL; // use base until downloaded
|
||||||
|
@ -149,34 +142,19 @@ Skin_Cache (skin_t *skin)
|
||||||
|
|
||||||
// load the pic from disk
|
// load the pic from disk
|
||||||
snprintf (name, sizeof (name), "skins/%s.pcx", skin->name);
|
snprintf (name, sizeof (name), "skins/%s.pcx", skin->name);
|
||||||
raw = COM_LoadTempFile (name);
|
COM_FOpenFile (name, &file);
|
||||||
if (!raw) {
|
if (!file) {
|
||||||
Con_Printf ("Couldn't load skin %s\n", name);
|
Con_Printf ("Couldn't load skin %s\n", name);
|
||||||
snprintf (name, sizeof (name), "skins/%s.pcx", baseskin->string);
|
snprintf (name, sizeof (name), "skins/%s.pcx", baseskin->string);
|
||||||
raw = COM_LoadTempFile (name);
|
COM_FOpenFile (name, &file);
|
||||||
if (!raw) {
|
if (!file) {
|
||||||
skin->failedload = true;
|
skin->failedload = true;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
tex = LoadPCX (file, 0);
|
||||||
|
|
||||||
// parse the PCX file
|
if (!tex || tex->width > 320 || tex->height > 200) {
|
||||||
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) {
|
|
||||||
skin->failedload = true;
|
skin->failedload = true;
|
||||||
Con_Printf ("Bad skin %s\n", name);
|
Con_Printf ("Bad skin %s\n", name);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -186,54 +164,7 @@ Skin_Cache (skin_t *skin)
|
||||||
if (!out)
|
if (!out)
|
||||||
Sys_Error ("Skin_Cache: couldn't allocate");
|
Sys_Error ("Skin_Cache: couldn't allocate");
|
||||||
|
|
||||||
pix = out;
|
memcpy (out, tex->data, tex->width * tex->height);
|
||||||
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;
|
skin->failedload = false;
|
||||||
|
|
||||||
|
@ -242,9 +173,7 @@ Skin_Cache (skin_t *skin)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
Skin_NextDownload
|
||||||
Skin_NextDownload
|
|
||||||
=================
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
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
|
void
|
||||||
Skin_Skins_f (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
|
void
|
||||||
Skin_AllSkins_f (void)
|
Skin_AllSkins_f (void)
|
||||||
|
|
Loading…
Reference in a new issue