Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

r_image.c (13129B)


      1 /*
      2 Copyright (C) 1997-2001 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 "r_local.h"
     22 
     23 
     24 #define	MAX_RIMAGES	1024
     25 image_t		r_images[MAX_RIMAGES];
     26 int			numr_images;
     27 
     28 
     29 /*
     30 ===============
     31 R_ImageList_f
     32 ===============
     33 */
     34 void	R_ImageList_f (void)
     35 {
     36 	int		i;
     37 	image_t	*image;
     38 	int		texels;
     39 
     40 	ri.Con_Printf (PRINT_ALL, "------------------\n");
     41 	texels = 0;
     42 
     43 	for (i=0, image=r_images ; i<numr_images ; i++, image++)
     44 	{
     45 		if (image->registration_sequence <= 0)
     46 			continue;
     47 		texels += image->width*image->height;
     48 		switch (image->type)
     49 		{
     50 		case it_skin:
     51 			ri.Con_Printf (PRINT_ALL, "M");
     52 			break;
     53 		case it_sprite:
     54 			ri.Con_Printf (PRINT_ALL, "S");
     55 			break;
     56 		case it_wall:
     57 			ri.Con_Printf (PRINT_ALL, "W");
     58 			break;
     59 		case it_pic:
     60 			ri.Con_Printf (PRINT_ALL, "P");
     61 			break;
     62 		default:
     63 			ri.Con_Printf (PRINT_ALL, " ");
     64 			break;
     65 		}
     66 
     67 		ri.Con_Printf (PRINT_ALL,  " %3i %3i : %s\n",
     68 			image->width, image->height, image->name);
     69 	}
     70 	ri.Con_Printf (PRINT_ALL, "Total texel count: %i\n", texels);
     71 }
     72 
     73 
     74 /*
     75 =================================================================
     76 
     77 PCX LOADING
     78 
     79 =================================================================
     80 */
     81 
     82 /*
     83 ==============
     84 LoadPCX
     85 ==============
     86 */
     87 void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height)
     88 {
     89 	byte	*raw;
     90 	pcx_t	*pcx;
     91 	int		x, y;
     92 	int		len;
     93 	int		dataByte, runLength;
     94 	byte	*out, *pix;
     95 
     96 	*pic = NULL;
     97 
     98 	//
     99 	// load the file
    100 	//
    101 	len = ri.FS_LoadFile (filename, (void **)&raw);
    102 	if (!raw)
    103 	{
    104 		ri.Con_Printf (PRINT_DEVELOPER, "Bad pcx file %s\n", filename);
    105 		return;
    106 	}
    107 
    108 	//
    109 	// parse the PCX file
    110 	//
    111 	pcx = (pcx_t *)raw;
    112 
    113     pcx->xmin = LittleShort(pcx->xmin);
    114     pcx->ymin = LittleShort(pcx->ymin);
    115     pcx->xmax = LittleShort(pcx->xmax);
    116     pcx->ymax = LittleShort(pcx->ymax);
    117     pcx->hres = LittleShort(pcx->hres);
    118     pcx->vres = LittleShort(pcx->vres);
    119     pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
    120     pcx->palette_type = LittleShort(pcx->palette_type);
    121 
    122 	raw = &pcx->data;
    123 
    124 	if (pcx->manufacturer != 0x0a
    125 		|| pcx->version != 5
    126 		|| pcx->encoding != 1
    127 		|| pcx->bits_per_pixel != 8
    128 		|| pcx->xmax >= 640
    129 		|| pcx->ymax >= 480)
    130 	{
    131 		ri.Con_Printf (PRINT_ALL, "Bad pcx file %s\n", filename);
    132 		return;
    133 	}
    134 
    135 	out = malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
    136 
    137 	*pic = out;
    138 
    139 	pix = out;
    140 
    141 	if (palette)
    142 	{
    143 		*palette = malloc(768);
    144 		memcpy (*palette, (byte *)pcx + len - 768, 768);
    145 	}
    146 
    147 	if (width)
    148 		*width = pcx->xmax+1;
    149 	if (height)
    150 		*height = pcx->ymax+1;
    151 
    152 	for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1)
    153 	{
    154 		for (x=0 ; x<=pcx->xmax ; )
    155 		{
    156 			dataByte = *raw++;
    157 
    158 			if((dataByte & 0xC0) == 0xC0)
    159 			{
    160 				runLength = dataByte & 0x3F;
    161 				dataByte = *raw++;
    162 			}
    163 			else
    164 				runLength = 1;
    165 
    166 			while(runLength-- > 0)
    167 				pix[x++] = dataByte;
    168 		}
    169 
    170 	}
    171 
    172 	if ( raw - (byte *)pcx > len)
    173 	{
    174 		ri.Con_Printf (PRINT_DEVELOPER, "PCX file %s was malformed", filename);
    175 		free (*pic);
    176 		*pic = NULL;
    177 	}
    178 
    179 	ri.FS_FreeFile (pcx);
    180 }
    181 
    182 /*
    183 =========================================================
    184 
    185 TARGA LOADING
    186 
    187 =========================================================
    188 */
    189 
    190 typedef struct _TargaHeader {
    191 	unsigned char 	id_length, colormap_type, image_type;
    192 	unsigned short	colormap_index, colormap_length;
    193 	unsigned char	colormap_size;
    194 	unsigned short	x_origin, y_origin, width, height;
    195 	unsigned char	pixel_size, attributes;
    196 } TargaHeader;
    197 
    198 
    199 /*
    200 =============
    201 LoadTGA
    202 =============
    203 */
    204 void LoadTGA (char *name, byte **pic, int *width, int *height)
    205 {
    206 	int		columns, rows, numPixels;
    207 	byte	*pixbuf;
    208 	int		row, column;
    209 	byte	*buf_p;
    210 	byte	*buffer;
    211 	int		length;
    212 	TargaHeader		targa_header;
    213 	byte			*targa_rgba;
    214 
    215 	*pic = NULL;
    216 
    217 	//
    218 	// load the file
    219 	//
    220 	length = ri.FS_LoadFile (name, (void **)&buffer);
    221 	if (!buffer)
    222 	{
    223 		ri.Con_Printf (PRINT_DEVELOPER, "Bad tga file %s\n", name);
    224 		return;
    225 	}
    226 
    227 	buf_p = buffer;
    228 
    229 	targa_header.id_length = *buf_p++;
    230 	targa_header.colormap_type = *buf_p++;
    231 	targa_header.image_type = *buf_p++;
    232 	
    233 	targa_header.colormap_index = LittleShort ( *((short *)buf_p) );
    234 	buf_p+=2;
    235 	targa_header.colormap_length = LittleShort ( *((short *)buf_p) );
    236 	buf_p+=2;
    237 	targa_header.colormap_size = *buf_p++;
    238 	targa_header.x_origin = LittleShort ( *((short *)buf_p) );
    239 	buf_p+=2;
    240 	targa_header.y_origin = LittleShort ( *((short *)buf_p) );
    241 	buf_p+=2;
    242 	targa_header.width = LittleShort ( *((short *)buf_p) );
    243 	buf_p+=2;
    244 	targa_header.height = LittleShort ( *((short *)buf_p) );
    245 	buf_p+=2;
    246 	targa_header.pixel_size = *buf_p++;
    247 	targa_header.attributes = *buf_p++;
    248 
    249 	if (targa_header.image_type!=2 
    250 		&& targa_header.image_type!=10) 
    251 		ri.Sys_Error (ERR_DROP, "LoadTGA: Only type 2 and 10 targa RGB images supported\n");
    252 
    253 	if (targa_header.colormap_type !=0 
    254 		|| (targa_header.pixel_size!=32 && targa_header.pixel_size!=24))
    255 		ri.Sys_Error (ERR_DROP, "LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
    256 
    257 	columns = targa_header.width;
    258 	rows = targa_header.height;
    259 	numPixels = columns * rows;
    260 
    261 	if (width)
    262 		*width = columns;
    263 	if (height)
    264 		*height = rows;
    265 
    266 	targa_rgba = malloc (numPixels*4);
    267 	*pic = targa_rgba;
    268 
    269 	if (targa_header.id_length != 0)
    270 		buf_p += targa_header.id_length;  // skip TARGA image comment
    271 	
    272 	if (targa_header.image_type==2) {  // Uncompressed, RGB images
    273 		for(row=rows-1; row>=0; row--) {
    274 			pixbuf = targa_rgba + row*columns*4;
    275 			for(column=0; column<columns; column++) {
    276 				unsigned char red,green,blue,alphabyte;
    277 				switch (targa_header.pixel_size) {
    278 					case 24:
    279 							
    280 							blue = *buf_p++;
    281 							green = *buf_p++;
    282 							red = *buf_p++;
    283 							*pixbuf++ = red;
    284 							*pixbuf++ = green;
    285 							*pixbuf++ = blue;
    286 							*pixbuf++ = 255;
    287 							break;
    288 					case 32:
    289 							blue = *buf_p++;
    290 							green = *buf_p++;
    291 							red = *buf_p++;
    292 							alphabyte = *buf_p++;
    293 							*pixbuf++ = red;
    294 							*pixbuf++ = green;
    295 							*pixbuf++ = blue;
    296 							*pixbuf++ = alphabyte;
    297 							break;
    298 				}
    299 			}
    300 		}
    301 	}
    302 	else if (targa_header.image_type==10) {   // Runlength encoded RGB images
    303 		unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
    304 		for(row=rows-1; row>=0; row--) {
    305 			pixbuf = targa_rgba + row*columns*4;
    306 			for(column=0; column<columns; ) {
    307 				packetHeader= *buf_p++;
    308 				packetSize = 1 + (packetHeader & 0x7f);
    309 				if (packetHeader & 0x80) {        // run-length packet
    310 					switch (targa_header.pixel_size) {
    311 						case 24:
    312 								blue = *buf_p++;
    313 								green = *buf_p++;
    314 								red = *buf_p++;
    315 								alphabyte = 255;
    316 								break;
    317 						case 32:
    318 								blue = *buf_p++;
    319 								green = *buf_p++;
    320 								red = *buf_p++;
    321 								alphabyte = *buf_p++;
    322 								break;
    323 					}
    324 	
    325 					for(j=0;j<packetSize;j++) {
    326 						*pixbuf++=red;
    327 						*pixbuf++=green;
    328 						*pixbuf++=blue;
    329 						*pixbuf++=alphabyte;
    330 						column++;
    331 						if (column==columns) { // run spans across rows
    332 							column=0;
    333 							if (row>0)
    334 								row--;
    335 							else
    336 								goto breakOut;
    337 							pixbuf = targa_rgba + row*columns*4;
    338 						}
    339 					}
    340 				}
    341 				else {                            // non run-length packet
    342 					for(j=0;j<packetSize;j++) {
    343 						switch (targa_header.pixel_size) {
    344 							case 24:
    345 									blue = *buf_p++;
    346 									green = *buf_p++;
    347 									red = *buf_p++;
    348 									*pixbuf++ = red;
    349 									*pixbuf++ = green;
    350 									*pixbuf++ = blue;
    351 									*pixbuf++ = 255;
    352 									break;
    353 							case 32:
    354 									blue = *buf_p++;
    355 									green = *buf_p++;
    356 									red = *buf_p++;
    357 									alphabyte = *buf_p++;
    358 									*pixbuf++ = red;
    359 									*pixbuf++ = green;
    360 									*pixbuf++ = blue;
    361 									*pixbuf++ = alphabyte;
    362 									break;
    363 						}
    364 						column++;
    365 						if (column==columns) { // pixel packet run spans across rows
    366 							column=0;
    367 							if (row>0)
    368 								row--;
    369 							else
    370 								goto breakOut;
    371 							pixbuf = targa_rgba + row*columns*4;
    372 						}						
    373 					}
    374 				}
    375 			}
    376 			breakOut:;
    377 		}
    378 	}
    379 
    380 	ri.FS_FreeFile (buffer);
    381 }
    382 
    383 
    384 //=======================================================
    385 
    386 image_t *R_FindFreeImage (void)
    387 {
    388 	image_t		*image;
    389 	int			i;
    390 
    391 	// find a free image_t
    392 	for (i=0, image=r_images ; i<numr_images ; i++,image++)
    393 	{
    394 		if (!image->registration_sequence)
    395 			break;
    396 	}
    397 	if (i == numr_images)
    398 	{
    399 		if (numr_images == MAX_RIMAGES)
    400 			ri.Sys_Error (ERR_DROP, "MAX_RIMAGES");
    401 		numr_images++;
    402 	}
    403 	image = &r_images[i];
    404 
    405 	return image;
    406 }
    407 
    408 /*
    409 ================
    410 GL_LoadPic
    411 
    412 ================
    413 */
    414 image_t *GL_LoadPic (char *name, byte *pic, int width, int height, imagetype_t type)
    415 {
    416 	image_t		*image;
    417 	int			i, c, b;
    418 
    419 	image = R_FindFreeImage ();
    420 	if (strlen(name) >= sizeof(image->name))
    421 		ri.Sys_Error (ERR_DROP, "Draw_LoadPic: \"%s\" is too long", name);
    422 	strcpy (image->name, name);
    423 	image->registration_sequence = registration_sequence;
    424 
    425 	image->width = width;
    426 	image->height = height;
    427 	image->type = type;
    428 
    429 	c = width*height;
    430 	image->pixels[0] = malloc (c);
    431 	image->transparent = false;
    432 	for (i=0 ; i<c ; i++)
    433 	{
    434 		b = pic[i];
    435 		if (b == 255)
    436 			image->transparent = true;
    437 		image->pixels[0][i] = b;
    438 	}
    439 
    440 	return image;
    441 }
    442 
    443 /*
    444 ================
    445 R_LoadWal
    446 ================
    447 */
    448 image_t *R_LoadWal (char *name)
    449 {
    450 	miptex_t	*mt;
    451 	int			ofs;
    452 	image_t		*image;
    453 	int			size;
    454 
    455 	ri.FS_LoadFile (name, (void **)&mt);
    456 	if (!mt)
    457 	{
    458 		ri.Con_Printf (PRINT_ALL, "R_LoadWal: can't load %s\n", name);
    459 		return r_notexture_mip;
    460 	}
    461 
    462 	image = R_FindFreeImage ();
    463 	strcpy (image->name, name);
    464 	image->width = LittleLong (mt->width);
    465 	image->height = LittleLong (mt->height);
    466 	image->type = it_wall;
    467 	image->registration_sequence = registration_sequence;
    468 
    469 	size = image->width*image->height * (256+64+16+4)/256;
    470 	image->pixels[0] = malloc (size);
    471 	image->pixels[1] = image->pixels[0] + image->width*image->height;
    472 	image->pixels[2] = image->pixels[1] + image->width*image->height/4;
    473 	image->pixels[3] = image->pixels[2] + image->width*image->height/16;
    474 
    475 	ofs = LittleLong (mt->offsets[0]);
    476 	memcpy ( image->pixels[0], (byte *)mt + ofs, size);
    477 
    478 	ri.FS_FreeFile ((void *)mt);
    479 
    480 	return image;
    481 }
    482 
    483 
    484 /*
    485 ===============
    486 R_FindImage
    487 
    488 Finds or loads the given image
    489 ===============
    490 */
    491 image_t	*R_FindImage (char *name, imagetype_t type)
    492 {
    493 	image_t	*image;
    494 	int		i, len;
    495 	byte	*pic, *palette;
    496 	int		width, height;
    497 
    498 	if (!name)
    499 		return NULL;	// ri.Sys_Error (ERR_DROP, "R_FindImage: NULL name");
    500 	len = strlen(name);
    501 	if (len<5)
    502 		return NULL;	// ri.Sys_Error (ERR_DROP, "R_FindImage: bad name: %s", name);
    503 
    504 	// look for it
    505 	for (i=0, image=r_images ; i<numr_images ; i++,image++)
    506 	{
    507 		if (!strcmp(name, image->name))
    508 		{
    509 			image->registration_sequence = registration_sequence;
    510 			return image;
    511 		}
    512 	}
    513 
    514 	//
    515 	// load the pic from disk
    516 	//
    517 	pic = NULL;
    518 	palette = NULL;
    519 	if (!strcmp(name+len-4, ".pcx"))
    520 	{
    521 		LoadPCX (name, &pic, &palette, &width, &height);
    522 		if (!pic)
    523 			return NULL;	// ri.Sys_Error (ERR_DROP, "R_FindImage: can't load %s", name);
    524 		image = GL_LoadPic (name, pic, width, height, type);
    525 	}
    526 	else if (!strcmp(name+len-4, ".wal"))
    527 	{
    528 		image = R_LoadWal (name);
    529 	}
    530 	else if (!strcmp(name+len-4, ".tga"))
    531 		return NULL;	// ri.Sys_Error (ERR_DROP, "R_FindImage: can't load %s in software renderer", name);
    532 	else
    533 		return NULL;	// ri.Sys_Error (ERR_DROP, "R_FindImage: bad extension on: %s", name);
    534 
    535 	if (pic)
    536 		free(pic);
    537 	if (palette)
    538 		free(palette);
    539 
    540 	return image;
    541 }
    542 
    543 
    544 
    545 /*
    546 ===============
    547 R_RegisterSkin
    548 ===============
    549 */
    550 struct image_s *R_RegisterSkin (char *name)
    551 {
    552 	return R_FindImage (name, it_skin);
    553 }
    554 
    555 
    556 /*
    557 ================
    558 R_FreeUnusedImages
    559 
    560 Any image that was not touched on this registration sequence
    561 will be freed.
    562 ================
    563 */
    564 void R_FreeUnusedImages (void)
    565 {
    566 	int		i;
    567 	image_t	*image;
    568 
    569 	for (i=0, image=r_images ; i<numr_images ; i++, image++)
    570 	{
    571 		if (image->registration_sequence == registration_sequence)
    572 		{
    573 			Com_PageInMemory ((byte *)image->pixels[0], image->width*image->height);
    574 			continue;		// used this sequence
    575 		}
    576 		if (!image->registration_sequence)
    577 			continue;		// free texture
    578 		if (image->type == it_pic)
    579 			continue;		// don't free pics
    580 		// free it
    581 		free (image->pixels[0]);	// the other mip levels just follow
    582 		memset (image, 0, sizeof(*image));
    583 	}
    584 }
    585 
    586 
    587 
    588 /*
    589 ===============
    590 R_InitImages
    591 ===============
    592 */
    593 void	R_InitImages (void)
    594 {
    595 	registration_sequence = 1;
    596 }
    597 
    598 /*
    599 ===============
    600 R_ShutdownImages
    601 ===============
    602 */
    603 void	R_ShutdownImages (void)
    604 {
    605 	int		i;
    606 	image_t	*image;
    607 
    608 	for (i=0, image=r_images ; i<numr_images ; i++, image++)
    609 	{
    610 		if (!image->registration_sequence)
    611 			continue;		// free texture
    612 		// free it
    613 		free (image->pixels[0]);	// the other mip levels just follow
    614 		memset (image, 0, sizeof(*image));
    615 	}
    616 }
    617