@@ -22,16 +22,37 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2222
2323#include "tr_common.h"
2424
25+ typedef struct gbix {
26+ unsigned int magic ;
27+ unsigned int len ;
28+ } gbix_t ;
29+
2530typedef struct pvr {
26- unsigned char magic [ 4 ] ;
31+ unsigned int magic ;
2732 unsigned int len_file ;
2833 unsigned int type ;
2934 unsigned short width ;
3035 unsigned short height ;
31- unsigned short codebook [1024 ];
32- unsigned char indices [1 ];
3336} pvr_t ;
3437
38+ typedef unsigned int (* pvr_pixel_func_t )(unsigned short color );
39+ typedef byte * (* pvr_image_func_t )(pvr_t * pvr , int offset , qboolean detwiddle , pvr_pixel_func_t pixel_func );
40+
41+ enum {
42+ PVR_PIXEL_TYPE_ARGB1555 = 0 ,
43+ PVR_PIXEL_TYPE_RGB565 = 1 ,
44+ PVR_PIXEL_TYPE_ARGB4444 = 2
45+ };
46+
47+ enum {
48+ PVR_IMAGE_TYPE_TWIDDLED = 1 ,
49+ PVR_IMAGE_TYPE_TWIDDLED_MM = 2 ,
50+ PVR_IMAGE_TYPE_VQ = 3 ,
51+ PVR_IMAGE_TYPE_VQ_MM = 4 ,
52+ PVR_IMAGE_TYPE_RECTANGULAR = 9 ,
53+ PVR_IMAGE_TYPE_RECTANGULAR_MM = 10
54+ };
55+
3556static int log2approx (int x )
3657{
3758 switch (x )
@@ -48,7 +69,7 @@ static int log2approx(int x)
4869 }
4970}
5071
51- static int from_xy (int x , int y , int w , int h )
72+ static int pvr_detwiddle (int x , int y , int w , int h )
5273{
5374 int wmax , hmax ;
5475 int i , idx = 0 ;
@@ -83,7 +104,17 @@ static int from_xy(int x, int y, int w, int h)
83104 return idx ;
84105}
85106
86- static unsigned int rgb565_to_rgba24 (unsigned short color )
107+ static unsigned int argb1555_to_rgba8888 (unsigned short color )
108+ {
109+ unsigned char r , g , b , a ;
110+ r = ((color >> 10 ) & 31 ) << 4 ;
111+ g = ((color >> 5 ) & 31 ) << 4 ;
112+ b = ((color >> 0 ) & 31 ) << 4 ;
113+ a = ((color >> 15 ) & 1 ) * 255 ;
114+ return (a << 24 ) | (b << 16 ) | (g << 8 ) | r ;
115+ }
116+
117+ static unsigned int rgb565_to_rgba8888 (unsigned short color )
87118{
88119 unsigned char r , g , b , a ;
89120 r = ((color >> 11 ) & 31 ) << 3 ;
@@ -93,13 +124,153 @@ static unsigned int rgb565_to_rgba24(unsigned short color)
93124 return (a << 24 ) | (b << 16 ) | (g << 8 ) | r ;
94125}
95126
127+ static unsigned int argb4444_to_rgba8888 (unsigned short color )
128+ {
129+ unsigned char r , g , b , a ;
130+ r = ((color >> 8 ) & 15 ) << 4 ;
131+ g = ((color >> 4 ) & 15 ) << 4 ;
132+ b = ((color >> 0 ) & 15 ) << 4 ;
133+ a = ((color >> 12 ) & 15 ) | 0xF ;
134+ return (a << 24 ) | (b << 16 ) | (g << 8 ) | r ;
135+ }
136+
137+ static int mm_offset (int w )
138+ {
139+ switch (w )
140+ {
141+ case 1 : return 0x00006 ;
142+ case 2 : return 0x00008 ;
143+ case 4 : return 0x00010 ;
144+ case 8 : return 0x00030 ;
145+ case 16 : return 0x000B0 ;
146+ case 32 : return 0x002B0 ;
147+ case 64 : return 0x00AB0 ;
148+ case 128 : return 0x02AB0 ;
149+ case 256 : return 0x0AAB0 ;
150+ case 512 : return 0x2AAB0 ;
151+ case 1024 : return 0xAAAB0 ;
152+ default : return -1 ;
153+ }
154+ }
155+
156+ static int mm_offset_vq (int w )
157+ {
158+ switch (w )
159+ {
160+ case 1 : return 0x00000 ;
161+ case 2 : return 0x00001 ;
162+ case 4 : return 0x00002 ;
163+ case 8 : return 0x00006 ;
164+ case 16 : return 0x00016 ;
165+ case 32 : return 0x00056 ;
166+ case 64 : return 0x00156 ;
167+ case 128 : return 0x00556 ;
168+ case 256 : return 0x01556 ;
169+ case 512 : return 0x05556 ;
170+ case 1024 : return 0x15556 ;
171+ default : return -1 ;
172+ }
173+ }
174+
175+ static byte * decode_mm (pvr_t * pvr , pvr_image_func_t image_func , pvr_pixel_func_t pixel_func , qboolean vq , qboolean detwiddle )
176+ {
177+ int offset = vq ? mm_offset_vq (pvr -> width ) : mm_offset (pvr -> width );
178+ return image_func (pvr , offset , detwiddle , pixel_func );
179+ }
180+
181+ static byte * decode (pvr_t * pvr , int offset , qboolean detwiddle , pvr_pixel_func_t pixel_func )
182+ {
183+ int x , y ;
184+ unsigned int * rgba32 ;
185+ byte * ret ;
186+
187+ ret = (byte * )ri .Malloc (pvr -> width * pvr -> height * sizeof (unsigned int ));
188+ rgba32 = (unsigned int * )ret ;
189+
190+ for (y = 0 ; y < pvr -> height ; y ++ )
191+ {
192+ for (x = 0 ; x < pvr -> width ; x ++ )
193+ {
194+ unsigned short color ;
195+ int ofs ;
196+ if (detwiddle )
197+ ofs = offset + pvr_detwiddle (x , y , pvr -> width , pvr -> height ) * 2 ;
198+ else
199+ ofs = offset + (y * pvr -> width + x ) * 2 ;
200+
201+ if (ofs < 0 )
202+ {
203+ ri .Free (ret );
204+ return NULL ;
205+ }
206+
207+ color = * (unsigned short * )(((byte * )(pvr + 1 )) + ofs );
208+
209+ rgba32 [y * pvr -> width + x ] = pixel_func (color );
210+ }
211+ }
212+
213+ return ret ;
214+ }
215+
216+ static byte * decode_vq (pvr_t * pvr , int offset , qboolean detwiddle , pvr_pixel_func_t pixel_func )
217+ {
218+ int x , y ;
219+ unsigned int * rgba32 ;
220+ unsigned short * codebook ;
221+ unsigned char * indices ;
222+ byte * ret ;
223+
224+ ret = (byte * )ri .Malloc (pvr -> width * pvr -> height * (pixel_func ? sizeof (unsigned int ) : sizeof (unsigned short )));
225+ rgba32 = (unsigned int * )ret ;
226+
227+ codebook = (unsigned short * )(pvr + 1 );
228+ indices = ((unsigned char * )(codebook + 1024 )) + offset ;
229+
230+ for (y = 0 ; y < pvr -> height / 2 ; y ++ )
231+ {
232+ for (x = 0 ; x < pvr -> width / 2 ; x ++ )
233+ {
234+ unsigned short * colors ;
235+ int a , b , c , d ;
236+ int idx ;
237+ if (detwiddle )
238+ idx = pvr_detwiddle (x , y , pvr -> width , pvr -> height );
239+ else
240+ idx = y * (pvr -> width / 2 ) + x ;
241+
242+ if (idx < 0 )
243+ {
244+ ri .Free (ret );
245+ return NULL ;
246+ }
247+
248+ colors = & codebook [indices [idx ] * 4 ];
249+
250+ a = ((y * 2 ) + 0 ) * pvr -> width + ((x * 2 ) + 0 );
251+ b = ((y * 2 ) + 1 ) * pvr -> width + ((x * 2 ) + 0 );
252+ c = ((y * 2 ) + 0 ) * pvr -> width + ((x * 2 ) + 1 );
253+ d = ((y * 2 ) + 1 ) * pvr -> width + ((x * 2 ) + 1 );
254+
255+ rgba32 [a ] = pixel_func (colors [0 ]);
256+ rgba32 [b ] = pixel_func (colors [1 ]);
257+ rgba32 [c ] = pixel_func (colors [2 ]);
258+ rgba32 [d ] = pixel_func (colors [3 ]);
259+ }
260+ }
261+
262+ return ret ;
263+ }
264+
96265void R_LoadPVR (const char * name , byte * * pic , int * width , int * height )
97266{
98267 unsigned int length ;
99268 void * buffer ;
269+ byte * ptr ;
100270 pvr_t * pvr ;
101- unsigned int * rgba ;
102- int x , y ;
271+ int pixel_type , image_type ;
272+ pvr_pixel_func_t pixel_func ;
273+ byte * ret = NULL ;
103274
104275 * pic = NULL ;
105276 if (width )
@@ -112,51 +283,104 @@ void R_LoadPVR(const char *name, byte **pic, int *width, int *height)
112283 if (!buffer || length < 0 )
113284 return ;
114285
286+ ptr = (byte * )buffer ;
287+
288+ // skip global index
289+ if (memcmp (ptr , "GBIX" , 4 ) == 0 )
290+ {
291+ gbix_t * gbix = (gbix_t * )ptr ;
292+ ptr += sizeof (gbix_t ) + LittleLong (gbix -> len );
293+ }
294+
115295 // check magic identifier
116- pvr = (pvr_t * )buffer ;
117- if (memcmp (pvr -> magic , "PVRT" , sizeof (pvr -> magic )) != 0 )
296+ if (memcmp (ptr , "PVRT" , 4 ) != 0 )
118297 ri .Error (ERR_DROP , "LoadPVR: magic identifier does not match expected (%s)" , name );
119298
120299 // fix up header
300+ pvr = (pvr_t * )ptr ;
121301 pvr -> len_file = LittleLong (pvr -> len_file );
122302 pvr -> type = LittleLong (pvr -> type );
123303 pvr -> width = LittleShort (pvr -> width );
124304 pvr -> height = LittleShort (pvr -> height );
125305
126- // allocate rgba buffer
127- rgba = (unsigned int * )ri .Malloc (pvr -> width * pvr -> height * 4 );
306+ // break out type values
307+ pixel_type = pvr -> type & 0xFF ;
308+ image_type = (pvr -> type & 0xFF00 ) >> 8 ;
128309
129- // decompress image
130- for ( y = 0 ; y < pvr -> height / 2 ; y ++ )
310+ // get pixel function
311+ switch ( pixel_type )
131312 {
132- for ( x = 0 ; x < pvr -> width / 2 ; x ++ )
313+ case PVR_PIXEL_TYPE_ARGB1555 :
133314 {
134- unsigned short * colors ;
135- int a , b , c , d ;
136- int idx = from_xy (x , y , pvr -> width , pvr -> height );
137-
138- if (idx < 0 )
139- ri .Error (ERR_DROP , "LoadPVR: invalid data passed to decompressor (%s)" , name );
140-
141- colors = & pvr -> codebook [pvr -> indices [idx ] * 4 ];
142-
143- a = ((y * 2 ) + 0 ) * pvr -> width + ((x * 2 ) + 0 );
144- b = ((y * 2 ) + 1 ) * pvr -> width + ((x * 2 ) + 0 );
145- c = ((y * 2 ) + 0 ) * pvr -> width + ((x * 2 ) + 1 );
146- d = ((y * 2 ) + 1 ) * pvr -> width + ((x * 2 ) + 1 );
315+ pixel_func = argb1555_to_rgba8888 ;
316+ break ;
317+ }
318+ case PVR_PIXEL_TYPE_RGB565 :
319+ {
320+ pixel_func = rgb565_to_rgba8888 ;
321+ break ;
322+ }
323+ case PVR_PIXEL_TYPE_ARGB4444 :
324+ {
325+ pixel_func = argb4444_to_rgba8888 ;
326+ break ;
327+ }
328+ default :
329+ {
330+ ri .Error (ERR_DROP , "LoadPVR: unsupported pixel type 0x%02x (%s)" , pixel_type , name );
331+ break ;
332+ }
333+ }
147334
148- rgba [a ] = rgb565_to_rgba24 (colors [0 ]);
149- rgba [b ] = rgb565_to_rgba24 (colors [1 ]);
150- rgba [c ] = rgb565_to_rgba24 (colors [2 ]);
151- rgba [d ] = rgb565_to_rgba24 (colors [3 ]);
335+ // decompress image
336+ switch (image_type )
337+ {
338+ case PVR_IMAGE_TYPE_TWIDDLED :
339+ {
340+ ret = decode (pvr , 0 , qtrue , pixel_func );
341+ break ;
342+ }
343+ case PVR_IMAGE_TYPE_TWIDDLED_MM :
344+ {
345+ ret = decode_mm (pvr , decode , pixel_func , qfalse , qtrue );
346+ break ;
347+ }
348+ case PVR_IMAGE_TYPE_VQ :
349+ {
350+ ret = decode_vq (pvr , 0 , qtrue , pixel_func );
351+ break ;
352+ }
353+ case PVR_IMAGE_TYPE_VQ_MM :
354+ {
355+ ret = decode_mm (pvr , decode_vq , pixel_func , qtrue , qtrue );
356+ break ;
357+ }
358+ case PVR_IMAGE_TYPE_RECTANGULAR :
359+ {
360+ ret = decode (pvr , 0 , qfalse , pixel_func );
361+ break ;
362+ }
363+ case PVR_IMAGE_TYPE_RECTANGULAR_MM :
364+ {
365+ ret = decode_mm (pvr , decode , pixel_func , qfalse , qfalse );
366+ break ;
367+ }
368+ default :
369+ {
370+ ri .Error (ERR_DROP , "LoadPVR: unsupported image type 0x%02x (%s)" , image_type , name );
371+ break ;
152372 }
153373 }
154374
155375 // clean up
156376 ri .FS_FreeFile (buffer );
157377
378+ // something failed
379+ if (!ret )
380+ return ;
381+
158382 // return stuff
159- * pic = ( byte * ) rgba ;
383+ * pic = ret ;
160384 if (width )
161385 * width = pvr -> width ;
162386 if (height )
0 commit comments