2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 // by Hydra - hydra@hydras-world.com
26 // This module is based on the image module, but just more stripped down.
27 // it still currently supports TGA file loading, even though this is not
28 // required for HalfLife support (unless MD2 files use TGA's)
30 // use the #defines in imagehl.h to enable/disable the various formats.
32 // HLW = Half-Life-WAD, I don't know if the actual in data in the WAD files
33 // has it's own name, so I'm just calling the individal textures .HLW files :)
35 // Thanks to the guys that made Wally for releasing an example WAD loader.
36 // without it this would not have been possible.
46 #define Sys_Printf g_FuncTable.m_pfnSysPrintf
47 #define Sys_FPrintf g_FuncTable.m_pfnSysFPrintf
52 ============================================================================
54 IDSP IMAGE (.spr files)
56 Some code copied straight from the Q1 source, also used the HalfLife SDK as
59 ============================================================================
62 typedef enum {ST_SYNC=0, ST_RAND } synctype_t;
63 typedef enum { SPR_SINGLE=0, SPR_GROUP } spriteframetype_t;
65 typedef struct dspriteheader_s {
101 } dspriteframetype_t;
109 #define IDSPRITEHEADER (('P'<<24)+('S'<<16)+('D'<<8)+'I')
110 // little-endian "IDSP"
118 static void LoadIDSP (const char *name, byte ** pic, int *width, int *height)
123 int columns, rows, numPixels;
129 unsigned char red, green, blue, alphabyte;
131 dspriteheader_t *header;
134 dspriteframetype_t *pframetype;
138 spriteframetype_t frametype;
139 dspriteframe_t *spriteframe;
146 length = vfsLoadFile ((char *) name, (void **) &buffer, 0);
147 if (length == (unsigned int) -1)
150 header = (dspriteheader_t *)buffer;
152 if (header->ident != IDSPRITEHEADER)
154 Sys_Printf ("WARNING: %s has wrong header\n");
155 vfsFreeFile (buffer);
159 version = header->version;
160 if (version != 1 && version != 2 )
162 Sys_Printf ("WARNING: %s has wrong version number "
163 "(%i should be 1 or 2)\n", name, version);
164 vfsFreeFile (buffer);
168 // initialise variables depending on the sprite version.
172 pinv1 = (dspritev1_t *)(header+1);
173 numframes = pinv1->numframes;
174 columns = pinv1->width;
175 rows = pinv1->height;
176 pframetype = (dspriteframetype_t *)(pinv1 + 1);
179 pinv2 = (dspritev2_t *)(header+1);
180 numframes = pinv2->numframes;
181 columns = pinv2->width;
182 rows = pinv2->height;
183 pframetype = (dspriteframetype_t *)(pinv2 + 1);
187 Sys_Printf ("WARNING: %s has multiple frames, only the first frame will be used.\n", name);
189 // palette = buffer+mipdatasize+2;
190 // buf_p = buffer+lpMip->offsets[0];
192 numPixels = columns * rows;
199 bmpRGBA = reinterpret_cast < unsigned char *>(g_malloc (numPixels * 4));
203 frametype = spriteframetype_t(LittleLong(pframetype->type));
204 if (frametype == SPR_SINGLE)
206 Sys_Printf("Single Frame\n");
208 else if (frametype == SPR_GROUP)
210 Sys_Printf("Group of Frames\n");
214 Sys_Printf("Bleh!\n"); // <-- we always get this, wtf!
218 palette = (byte *)(pframetype+1);
219 spriteframe = (dspriteframe_t *)(palette + (256*3) + 4); // what are those 4 extra bytes ? what's missing ?
220 buf_p = (byte *)(spriteframe + 1);
224 temp = buf_p - buffer;
226 for (row = 0; row < rows; row++)
228 pixbuf = bmpRGBA + row * columns * 4;
230 for (column = 0; column < columns; column++)
236 red = *(palette+(palIndex*3));
237 green = *(palette+(palIndex*3)+1);
238 blue = *(palette+(palIndex*3)+2);
240 // HalfLife engine makes pixels that are BLUE transparent. (RGB = 0x0000FF)
241 // So show them that way in the editor.
242 if (blue == 0xff && red == 0x00 && green == 0x00)
244 alphabyte = 0xff; //FIXME: backwards? (so sprite models to render correctly)
245 blue = 0x00; // don't set the resulting pixel to blue
249 alphabyte = 0x00; //FIXME: backwards? (so sprite models to render correctly)
256 *pixbuf++ = alphabyte;
260 vfsFreeFile (buffer);
266 ============================================================================
270 HalfLife WAD files contain files that look like this:
275 First mip (width * height)
276 Second mip (width * height / 4)
277 Third mip (width * height / 16)
278 Fourth mip (width * height / 64)
280 Palette (Palette size * 3)
283 ============================================================================
286 #define GET_MIP_DATA_SIZE(WIDTH, HEIGHT) (sizeof(WAD3_MIP) + (WIDTH * HEIGHT) + (WIDTH * HEIGHT / 4) + (WIDTH * HEIGHT / 16) + (WIDTH * HEIGHT / 64))
292 DWORD offsets[4]; // four mip maps stored
293 } WAD3_MIP, *LPWAD3_MIP;
296 =========================================================
300 Hydra: this code isn't bullet proof and probably won't
301 like corrupt WAD files, but it works for now.
303 TODO: make it more robust.
304 =========================================================
313 static void LoadHLW (const char *name, byte ** pic, int *width, int *height)
318 unsigned long mipdatasize;
319 int columns, rows, numPixels;
325 unsigned char red, green, blue, alphabyte;
332 length = vfsLoadFile ((char *) name, (void **) &buffer, 0);
333 if (length == (unsigned int) -1)
336 lpMip = (LPWAD3_MIP)buffer;
338 mipdatasize = GET_MIP_DATA_SIZE(lpMip->width,lpMip->height);
340 palette = buffer+mipdatasize+2;
342 buf_p = buffer+lpMip->offsets[0];
344 columns = lpMip->width;
345 rows = lpMip->height;
346 numPixels = columns * rows;
353 bmpRGBA = reinterpret_cast < unsigned char *>(g_malloc (numPixels * 4));
356 for (row = 0; row < rows; row++)
358 pixbuf = bmpRGBA + row * columns * 4;
360 for (column = 0; column < columns; column++)
366 red = *(palette+(palIndex*3));
367 green = *(palette+(palIndex*3)+1);
368 blue = *(palette+(palIndex*3)+2);
370 // HalfLife engine makes pixels that are BLUE transparent.
371 // So show them that way in the editor.
372 if (blue == 0xff && red == 0x00 && green == 0x00)
375 blue = 0x00; // don't set the resulting pixel to blue
386 *pixbuf++ = alphabyte;
390 vfsFreeFile (buffer);
396 ============================================================================
400 Quake WAD files contain miptex files that look like this:
405 First mip (width * height)
406 Second mip (width * height / 4)
407 Third mip (width * height / 16)
408 Fourth mip (width * height / 64)
410 ============================================================================
414 =========================================================
418 LordHavoc: this code is based on the HLW code above.
419 =========================================================
423 static const byte quakepalette[768] =
425 0x00,0x00,0x00, 0x0f,0x0f,0x0f, 0x1f,0x1f,0x1f, 0x2f,0x2f,0x2f,
426 0x3f,0x3f,0x3f, 0x4b,0x4b,0x4b, 0x5b,0x5b,0x5b, 0x6b,0x6b,0x6b,
427 0x7b,0x7b,0x7b, 0x8b,0x8b,0x8b, 0x9b,0x9b,0x9b, 0xab,0xab,0xab,
428 0xbb,0xbb,0xbb, 0xcb,0xcb,0xcb, 0xdb,0xdb,0xdb, 0xeb,0xeb,0xeb,
429 0x0f,0x0b,0x07, 0x17,0x0f,0x0b, 0x1f,0x17,0x0b, 0x27,0x1b,0x0f,
430 0x2f,0x23,0x13, 0x37,0x2b,0x17, 0x3f,0x2f,0x17, 0x4b,0x37,0x1b,
431 0x53,0x3b,0x1b, 0x5b,0x43,0x1f, 0x63,0x4b,0x1f, 0x6b,0x53,0x1f,
432 0x73,0x57,0x1f, 0x7b,0x5f,0x23, 0x83,0x67,0x23, 0x8f,0x6f,0x23,
433 0x0b,0x0b,0x0f, 0x13,0x13,0x1b, 0x1b,0x1b,0x27, 0x27,0x27,0x33,
434 0x2f,0x2f,0x3f, 0x37,0x37,0x4b, 0x3f,0x3f,0x57, 0x47,0x47,0x67,
435 0x4f,0x4f,0x73, 0x5b,0x5b,0x7f, 0x63,0x63,0x8b, 0x6b,0x6b,0x97,
436 0x73,0x73,0xa3, 0x7b,0x7b,0xaf, 0x83,0x83,0xbb, 0x8b,0x8b,0xcb,
437 0x00,0x00,0x00, 0x07,0x07,0x00, 0x0b,0x0b,0x00, 0x13,0x13,0x00,
438 0x1b,0x1b,0x00, 0x23,0x23,0x00, 0x2b,0x2b,0x07, 0x2f,0x2f,0x07,
439 0x37,0x37,0x07, 0x3f,0x3f,0x07, 0x47,0x47,0x07, 0x4b,0x4b,0x0b,
440 0x53,0x53,0x0b, 0x5b,0x5b,0x0b, 0x63,0x63,0x0b, 0x6b,0x6b,0x0f,
441 0x07,0x00,0x00, 0x0f,0x00,0x00, 0x17,0x00,0x00, 0x1f,0x00,0x00,
442 0x27,0x00,0x00, 0x2f,0x00,0x00, 0x37,0x00,0x00, 0x3f,0x00,0x00,
443 0x47,0x00,0x00, 0x4f,0x00,0x00, 0x57,0x00,0x00, 0x5f,0x00,0x00,
444 0x67,0x00,0x00, 0x6f,0x00,0x00, 0x77,0x00,0x00, 0x7f,0x00,0x00,
445 0x13,0x13,0x00, 0x1b,0x1b,0x00, 0x23,0x23,0x00, 0x2f,0x2b,0x00,
446 0x37,0x2f,0x00, 0x43,0x37,0x00, 0x4b,0x3b,0x07, 0x57,0x43,0x07,
447 0x5f,0x47,0x07, 0x6b,0x4b,0x0b, 0x77,0x53,0x0f, 0x83,0x57,0x13,
448 0x8b,0x5b,0x13, 0x97,0x5f,0x1b, 0xa3,0x63,0x1f, 0xaf,0x67,0x23,
449 0x23,0x13,0x07, 0x2f,0x17,0x0b, 0x3b,0x1f,0x0f, 0x4b,0x23,0x13,
450 0x57,0x2b,0x17, 0x63,0x2f,0x1f, 0x73,0x37,0x23, 0x7f,0x3b,0x2b,
451 0x8f,0x43,0x33, 0x9f,0x4f,0x33, 0xaf,0x63,0x2f, 0xbf,0x77,0x2f,
452 0xcf,0x8f,0x2b, 0xdf,0xab,0x27, 0xef,0xcb,0x1f, 0xff,0xf3,0x1b,
453 0x0b,0x07,0x00, 0x1b,0x13,0x00, 0x2b,0x23,0x0f, 0x37,0x2b,0x13,
454 0x47,0x33,0x1b, 0x53,0x37,0x23, 0x63,0x3f,0x2b, 0x6f,0x47,0x33,
455 0x7f,0x53,0x3f, 0x8b,0x5f,0x47, 0x9b,0x6b,0x53, 0xa7,0x7b,0x5f,
456 0xb7,0x87,0x6b, 0xc3,0x93,0x7b, 0xd3,0xa3,0x8b, 0xe3,0xb3,0x97,
457 0xab,0x8b,0xa3, 0x9f,0x7f,0x97, 0x93,0x73,0x87, 0x8b,0x67,0x7b,
458 0x7f,0x5b,0x6f, 0x77,0x53,0x63, 0x6b,0x4b,0x57, 0x5f,0x3f,0x4b,
459 0x57,0x37,0x43, 0x4b,0x2f,0x37, 0x43,0x27,0x2f, 0x37,0x1f,0x23,
460 0x2b,0x17,0x1b, 0x23,0x13,0x13, 0x17,0x0b,0x0b, 0x0f,0x07,0x07,
461 0xbb,0x73,0x9f, 0xaf,0x6b,0x8f, 0xa3,0x5f,0x83, 0x97,0x57,0x77,
462 0x8b,0x4f,0x6b, 0x7f,0x4b,0x5f, 0x73,0x43,0x53, 0x6b,0x3b,0x4b,
463 0x5f,0x33,0x3f, 0x53,0x2b,0x37, 0x47,0x23,0x2b, 0x3b,0x1f,0x23,
464 0x2f,0x17,0x1b, 0x23,0x13,0x13, 0x17,0x0b,0x0b, 0x0f,0x07,0x07,
465 0xdb,0xc3,0xbb, 0xcb,0xb3,0xa7, 0xbf,0xa3,0x9b, 0xaf,0x97,0x8b,
466 0xa3,0x87,0x7b, 0x97,0x7b,0x6f, 0x87,0x6f,0x5f, 0x7b,0x63,0x53,
467 0x6b,0x57,0x47, 0x5f,0x4b,0x3b, 0x53,0x3f,0x33, 0x43,0x33,0x27,
468 0x37,0x2b,0x1f, 0x27,0x1f,0x17, 0x1b,0x13,0x0f, 0x0f,0x0b,0x07,
469 0x6f,0x83,0x7b, 0x67,0x7b,0x6f, 0x5f,0x73,0x67, 0x57,0x6b,0x5f,
470 0x4f,0x63,0x57, 0x47,0x5b,0x4f, 0x3f,0x53,0x47, 0x37,0x4b,0x3f,
471 0x2f,0x43,0x37, 0x2b,0x3b,0x2f, 0x23,0x33,0x27, 0x1f,0x2b,0x1f,
472 0x17,0x23,0x17, 0x0f,0x1b,0x13, 0x0b,0x13,0x0b, 0x07,0x0b,0x07,
473 0xff,0xf3,0x1b, 0xef,0xdf,0x17, 0xdb,0xcb,0x13, 0xcb,0xb7,0x0f,
474 0xbb,0xa7,0x0f, 0xab,0x97,0x0b, 0x9b,0x83,0x07, 0x8b,0x73,0x07,
475 0x7b,0x63,0x07, 0x6b,0x53,0x00, 0x5b,0x47,0x00, 0x4b,0x37,0x00,
476 0x3b,0x2b,0x00, 0x2b,0x1f,0x00, 0x1b,0x0f,0x00, 0x0b,0x07,0x00,
477 0x00,0x00,0xff, 0x0b,0x0b,0xef, 0x13,0x13,0xdf, 0x1b,0x1b,0xcf,
478 0x23,0x23,0xbf, 0x2b,0x2b,0xaf, 0x2f,0x2f,0x9f, 0x2f,0x2f,0x8f,
479 0x2f,0x2f,0x7f, 0x2f,0x2f,0x6f, 0x2f,0x2f,0x5f, 0x2b,0x2b,0x4f,
480 0x23,0x23,0x3f, 0x1b,0x1b,0x2f, 0x13,0x13,0x1f, 0x0b,0x0b,0x0f,
481 0x2b,0x00,0x00, 0x3b,0x00,0x00, 0x4b,0x07,0x00, 0x5f,0x07,0x00,
482 0x6f,0x0f,0x00, 0x7f,0x17,0x07, 0x93,0x1f,0x07, 0xa3,0x27,0x0b,
483 0xb7,0x33,0x0f, 0xc3,0x4b,0x1b, 0xcf,0x63,0x2b, 0xdb,0x7f,0x3b,
484 0xe3,0x97,0x4f, 0xe7,0xab,0x5f, 0xef,0xbf,0x77, 0xf7,0xd3,0x8b,
485 0xa7,0x7b,0x3b, 0xb7,0x9b,0x37, 0xc7,0xc3,0x37, 0xe7,0xe3,0x57,
486 0x7f,0xbf,0xff, 0xab,0xe7,0xff, 0xd7,0xff,0xff, 0x67,0x00,0x00,
487 0x8b,0x00,0x00, 0xb3,0x00,0x00, 0xd7,0x00,0x00, 0xff,0x00,0x00,
488 0xff,0xf3,0x93, 0xff,0xf7,0xc7, 0xff,0xff,0xff, 0x9f,0x5b,0x53
497 static void LoadMIP (const char *name, byte ** pic, int *width, int *height)
501 unsigned int length, palettelength;
502 unsigned long mipdatasize;
503 int columns, rows, numPixels;
512 loadedpalette = NULL;
517 length = vfsLoadFile ((char *) name, (void **) &buffer, 0);
518 if (length == (unsigned int) -1)
521 lpMip = (LPWAD3_MIP)buffer;
523 mipdatasize = GET_MIP_DATA_SIZE(lpMip->width,lpMip->height);
525 palettelength = vfsLoadFile ("textures/palette.lmp", (void **) &loadedpalette, 0);
526 if (palettelength == 768)
527 palette = loadedpalette;
530 loadedpalette = NULL;
531 palette = quakepalette;
534 buf_p = buffer+lpMip->offsets[0];
536 columns = lpMip->width;
537 rows = lpMip->height;
538 numPixels = columns * rows;
545 //Sys_Printf("lpMip->width = %i, lpMip->height = %i, lpMip->offsets[0] = %i, lpMip->offsets[1] = %i, lpMip->offsets[2] = %i, lpMip->offsets[3] = %i, numPixels = %i\n", lpMip->width, lpMip->height, lpMip->offsets[0], lpMip->offsets[1], lpMip->offsets[2], lpMip->offsets[3], numPixels);
546 //for (i = 0; i < sizeof(*lpMip); i++)
547 // Sys_Printf("%02x", (int) ((unsigned char *)lpMip)[i]);
549 bmpRGBA = reinterpret_cast < unsigned char *>(g_malloc (numPixels * 4));
553 for (i = 0; i < numPixels; i++)
555 int palIndex = *buf_p++;
556 *pixbuf++ = palette[palIndex*3];
557 *pixbuf++ = palette[palIndex*3+1];
558 *pixbuf++ = palette[palIndex*3+2];
562 vfsFreeFile (buffer);
563 if (loadedpalette != NULL)
564 vfsFreeFile (loadedpalette);
572 Loads any of the supported image types into a cannonical
576 void LoadImage (const char *name, byte ** pic, int *width, int *height)
590 if (*pic == NULL && !g_strcasecmp (name + len - 4, ".hlw"))
592 LoadHLW (name, pic, width, height);
597 if (*pic == NULL && !g_strcasecmp (name + len - 4, ".mip"))
599 LoadMIP (name, pic, width, height);
604 if (*pic == NULL && !g_strcasecmp (name + len - 4, ".spr"))
606 LoadIDSP (name, pic, width, height);