]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - plugins/imagehl/sprite.cpp
Remove trailing spaces after `#` tokens
[xonotic/netradiant.git] / plugins / imagehl / sprite.cpp
1 /*
2    Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3    For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5    This file is part of GtkRadiant.
6
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.
11
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.
16
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
20  */
21
22 // by Hydra - hydra@hydras-world.com
23
24 #include "sprite.h"
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdio.h>
29
30 typedef unsigned char byte;
31
32 #include "ifilesystem.h"
33
34 #include "imagelib.h"
35
36 /*
37    ============================================================================
38
39    IDSP IMAGE (.spr files)
40
41    Some code copied straight from the Q1 source, also used the HalfLife SDK as
42    a reference.
43
44    ============================================================================
45  */
46
47 typedef enum {ST_SYNC = 0, ST_RAND } synctype_t;
48 typedef enum { SPR_SINGLE = 0, SPR_GROUP } spriteframetype_t;
49
50 typedef struct dspriteheader_s {
51         int ident;
52         int version;
53 } dspriteheader_t;
54
55 // Quake1
56 typedef struct {
57         int type;
58         float boundingradius;
59         int width;
60         int height;
61         int numframes;
62         float beamlength;
63         synctype_t synctype;
64 } dspritev1_t;
65
66 // Halflife
67 typedef struct {
68         int type;
69         int texFormat;
70         float boundingradius;
71         int width;
72         int height;
73         int numframes;
74         float beamlength;
75         synctype_t synctype;
76 } dspritev2_t;
77
78 typedef struct {
79         int origin[2];
80         int width;
81         int height;
82 } dspriteframe_t;
83
84 typedef struct {
85         short type;
86 } dspriteframetype_t;
87
88 /*
89    typedef struct {
90    byte rgb[256][3];
91    } dpalette_t;
92  */
93
94 #define IDSPRITEHEADER  ( ( 'P' << 24 ) + ( 'S' << 16 ) + ( 'D' << 8 ) + 'I' )
95 // little-endian "IDSP"
96
97 /*
98    =============
99    LoadIDSP
100    =============
101  */
102
103 Image* LoadIDSPBuff( byte *buffer ){
104         byte *buf_p;
105         int columns, rows;
106         byte *pixbuf;
107
108         int row, column;
109         byte *palette;
110         unsigned char red, green, blue, alphabyte;
111
112         dspriteheader_t *header;
113         dspritev1_t         *pinv1;
114         dspritev2_t         *pinv2;
115         dspriteframetype_t  *pframetype;
116         int version;
117         int numframes;
118         dspriteframe_t *spriteframe;
119
120         header = (dspriteheader_t *)buffer;
121
122         if ( header->ident != IDSPRITEHEADER ) {
123                 globalErrorStream() << "WARNING: IDSP file has wrong header\n";
124                 return 0;
125         }
126
127         version = header->version;
128         if ( version != 1 && version != 2 ) {
129                 globalErrorStream() << "WARNING: IDSP file has wrong version number "
130                                                            "(" << version << " should be 1 or 2)\n";
131                 return 0;
132         }
133
134         // initialise variables depending on the sprite version.
135         switch ( version )
136         {
137         case 1:
138                 pinv1 = (dspritev1_t *)( header + 1 );
139                 numframes = pinv1->numframes;
140                 columns = pinv1->width;
141                 rows = pinv1->height;
142                 pframetype = (dspriteframetype_t *)( pinv1 + 1 );
143                 break;
144         case 2:
145                 pinv2 = (dspritev2_t *)( header + 1 );
146                 numframes = pinv2->numframes;
147                 columns = pinv2->width;
148                 rows = pinv2->height;
149                 pframetype = (dspriteframetype_t *)( pinv2 + 1 );
150                 break;
151         default:
152                 globalErrorStream() << "WARNING: IDSP file has unsupported version\n";
153                 return 0;
154         }
155         if ( numframes > 1 ) {
156                 globalErrorStream() << "WARNING: IDSP file has multiple frames, only the first frame will be used.\n";
157         }
158
159         // palette = buffer+mipdatasize+2;
160         // buf_p = buffer+lpMip->offsets[0];
161
162         RGBAImage* image = new RGBAImage( columns, rows );
163
164 #ifdef DEBUG
165         frametype = spriteframetype_t( pframetype->type );
166         if ( frametype == SPR_SINGLE ) {
167                 globalOutputStream() << "Single Frame\n";
168         }
169         else if ( frametype == SPR_GROUP ) {
170                 globalOutputStream() << "Group of Frames\n";
171         }
172         else
173         {
174                 globalOutputStream() << "Bleh!\n"; // <-- we always get this, wtf!
175         }
176 #endif
177
178         palette = (byte *)( pframetype + 1 );
179         spriteframe = (dspriteframe_t *)( palette + ( 256 * 3 ) + 4 ); // what are those 4 extra bytes ? what's missing ?
180         buf_p = (byte *)( spriteframe + 1 );
181
182         for ( row = 0; row < rows; row++ )
183         {
184                 pixbuf = image->getRGBAPixels() + row * columns * 4;
185
186                 for ( column = 0; column < columns; column++ )
187                 {
188                         int palIndex;
189
190                         palIndex = *buf_p++;
191
192                         red = *( palette + ( palIndex * 3 ) );
193                         green = *( palette + ( palIndex * 3 ) + 1 );
194                         blue = *( palette + ( palIndex * 3 ) + 2 );
195
196                         // HalfLife engine makes pixels that are BLUE transparent. (RGB = 0x0000FF)
197                         // So show them that way in the editor.
198                         if ( blue == 0xff && red == 0x00 && green == 0x00 ) {
199                                 alphabyte = 0xff; //FIXME: backwards? (so sprite models to render correctly)
200                                 blue = 0x00; // don't set the resulting pixel to blue
201                         }
202                         else
203                         {
204                                 alphabyte = 0x00; //FIXME: backwards? (so sprite models to render correctly)
205                         }
206
207                         *pixbuf++ = red;
208                         *pixbuf++ = green;
209                         *pixbuf++ = blue;
210
211                         *pixbuf++ = alphabyte;
212                 }
213         }
214
215         return image;
216 }
217
218 Image* LoadIDSP( ArchiveFile& file ){
219         ScopedArchiveBuffer buffer( file );
220         return LoadIDSPBuff( buffer.buffer );
221 }