Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
ddsfile.cpp
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** 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, see <http://www.gnu.org/licenses/>.
17*/
18
19// 08/06/02 KM Added cube map and volume texture support
20#include "ddsfile.h"
21#include "ffactory.h"
22#include "bufffile.h"
23#include "formconv.h"
24#include "dx8wrapper.h"
25#include "bitmaphandler.h"
26#include "colorspace.h"
27#include <string.h>
28#include <ddraw.h>
29
30#ifndef DDSCAPS2_CUBEMAP
31#define DDSCAPS2_CUBEMAP 0x00000200L
32#endif
33
34#ifndef DDSCAPS2_VOLUME
35#define DDSCAPS2_VOLUME 0x00200000L
36#endif
37// ----------------------------------------------------------------------------
38
39DDSFileClass::DDSFileClass(const char* name,unsigned reduction_factor)
40 :
41 DDSMemory(NULL),
42 Width(0),
43 Height(0),
44 Depth(0),
45 FullWidth(0),
46 FullHeight(0),
47 FullDepth(0),
48 LevelSizes(NULL),
49 LevelOffsets(NULL),
50 MipLevels(0),
51 ReductionFactor(reduction_factor),
52 Format(WW3D_FORMAT_UNKNOWN),
53 Type(DDS_TEXTURE),
54 DateTime(0),
55 CubeFaceSize(0)
56{
57 strncpy(Name,name,sizeof(Name));
58 // The name could be given in .tga or .dds format, so ensure we're opening .dds...
59 int len=strlen(Name);
60 Name[len-3]='d';
61 Name[len-2]='d';
62 Name[len-1]='s';
63
65 if (!file->Is_Available())
66 {
67 return;
68 }
69
70 int result=file->Open();
71 if (!result)
72 {
73 WWASSERT("File would not open\n");
74 return;
75 }
76
77 DateTime=file->Get_Date_Time();
78 char header[4];
79
80 unsigned read_bytes=file->Read(header,4);
81 if (!read_bytes)
82 {
83 WWASSERT("File loading failed trying to read header\n");
84 return;
85 }
86 // Now, we read DDSURFACEDESC2 defining the compressed data
87 read_bytes=file->Read(&SurfaceDesc,sizeof(LegacyDDSURFACEDESC2));
88 // Verify the structure size matches the read size
89 if (read_bytes==0 || read_bytes!=SurfaceDesc.Size)
90 {
91 StringClass tmp(0,true);
92 tmp.Format("File %s loading failed.\nTried to read %d bytes, got %d. (SurfDesc.size=%d)\n",name,sizeof(LegacyDDSURFACEDESC2),read_bytes,SurfaceDesc.Size);
93 WWASSERT_PRINT(0,tmp);
94 return;
95 }
96
97 Format=D3DFormat_To_WW3DFormat((D3DFORMAT)SurfaceDesc.PixelFormat.FourCC);
99 Format==WW3D_FORMAT_DXT1 ||
100 Format==WW3D_FORMAT_DXT2 ||
101 Format==WW3D_FORMAT_DXT3 ||
102 Format==WW3D_FORMAT_DXT4 ||
103 Format==WW3D_FORMAT_DXT5);
104
105 MipLevels=SurfaceDesc.MipMapCount;
106 if (MipLevels==0) MipLevels=1;
107
108 if (MipLevels>ReductionFactor) MipLevels-=ReductionFactor;
109 else {
110 MipLevels=1;
111 ReductionFactor=ReductionFactor-MipLevels;
112 }
113
114 // Drop the two lowest miplevels!
115 if (MipLevels>2) MipLevels-=2;
116 else MipLevels=1;
117
118 // check texture type, normal, cube or volume
119 if (SurfaceDesc.Caps.Caps2&DDSCAPS2_CUBEMAP)
120 {
121 Type=DDS_CUBEMAP;
122 }
123 else if (SurfaceDesc.Caps.Caps2&DDSCAPS2_VOLUME)
124 {
125 Type=DDS_VOLUME;
126 }
127
128
129 FullWidth=SurfaceDesc.Width;
130 FullHeight=SurfaceDesc.Height;
131 FullDepth=SurfaceDesc.Depth;
132 Width=SurfaceDesc.Width>>ReductionFactor;
133 Height=SurfaceDesc.Height>>ReductionFactor;
134 Depth=SurfaceDesc.Depth;
135
136 unsigned level_size=Calculate_DXTC_Surface_Size
137 (
138 SurfaceDesc.Width,
139 SurfaceDesc.Height,
140 Format
141 );
142 unsigned level_offset=0;
143
144 unsigned level_mip_dec=4;
145 if (Type==DDS_VOLUME)
146 {
147 // add slices to level data size
148 level_size*=SurfaceDesc.Depth;
149 level_mip_dec=8;
150 }
151
152 LevelSizes=W3DNEWARRAY unsigned[MipLevels];
153 LevelOffsets=W3DNEWARRAY unsigned[MipLevels];
154 for (unsigned level=0;level<ReductionFactor;++level)
155 {
156 if (level_size>16)
157 { // If surface is bigger than one block (8 or 16 bytes)...
158 level_size/=level_mip_dec;
159 }
160 }
161 for (level=0;level<MipLevels;++level)
162 {
163 LevelSizes[level]=level_size;
164 LevelOffsets[level]=level_offset;
165 level_offset+=level_size;
166 if (level_size>16)
167 { // If surface is bigger than one block (8 or 16 bytes)...
168 level_size/=level_mip_dec;
169 }
170 }
171
172 if (Type==DDS_CUBEMAP)
173 {
174 for (level=0; level<MipLevels;++level)
175 {
176 CubeFaceSize+=LevelSizes[level];
177 }
178
179 // this accounts for dropping 2 lowest mip levels
180 if (MipLevels>2)
181 CubeFaceSize+=16;
182 }
183 file->Close();
184}
185
186// ----------------------------------------------------------------------------
187
189{
190 delete[] DDSMemory;
191 delete[] LevelSizes;
192 delete[] LevelOffsets;
193}
194
195unsigned DDSFileClass::Get_Width(unsigned level) const
196{
197 WWASSERT(level<MipLevels);
198 unsigned width=Width>>level;
199 if (width<4) width=4;
200 return width;
201}
202
203unsigned DDSFileClass::Get_Height(unsigned level) const
204{
205 WWASSERT(level<MipLevels);
206 unsigned height=Height>>level;
207 if (height<4) height=4;
208 return height;
209}
210
211unsigned DDSFileClass::Get_Depth(unsigned level) const
212{
213 WWASSERT(level<MipLevels);
214 unsigned depth=Depth>>level;
215 if (depth<4) depth=4;
216 return depth;
217}
218
219const unsigned char* DDSFileClass::Get_Memory_Pointer(unsigned level) const
220{
221 WWASSERT(level<MipLevels);
222 return DDSMemory+LevelOffsets[level];
223}
224
225unsigned DDSFileClass::Get_Level_Size(unsigned level) const
226{
227 WWASSERT(level<MipLevels);
228 return LevelSizes[level];
229}
230
231// For some reason DX-Tex tool doesn't fill the surface size field, so we need to calculate it...
232unsigned DDSFileClass::Calculate_DXTC_Surface_Size
233(
234 unsigned width,
235 unsigned height,
236 WW3DFormat format
237)
238{
239 unsigned level_size=(width/4)*(height/4);
240 switch (format)
241 {
242 case WW3D_FORMAT_DXT1:
243 level_size*=8;
244 break;
245 case WW3D_FORMAT_DXT2:
246 case WW3D_FORMAT_DXT3:
247 case WW3D_FORMAT_DXT4:
248 case WW3D_FORMAT_DXT5:
249 level_size*=16;
250 break;
251 }
252
253 return level_size;
254}
255
256// ----------------------------------------------------------------------------
257
259{
260 if (DDSMemory) return false;
261 if (!LevelSizes || !LevelOffsets) return false;
262
263 file_auto_ptr file(_TheFileFactory,Name);
264 if (!file->Is_Available())
265 {
266 return false;
267 }
268
269 file->Open();
270 // Data size is file size minus the header and info block
271 unsigned size=file->Size()-SurfaceDesc.Size-4;
272
273 if (!size)
274 {
275 return false;
276 }
277
278 // Skip mip levels if reduction factor is not zero
279 unsigned level_size=Calculate_DXTC_Surface_Size
280 (
281 SurfaceDesc.Width,
282 SurfaceDesc.Height,
283 Format
284 );
285
286 unsigned skipped_offset=0;
287 for (unsigned i=0;i<ReductionFactor;++i)
288 {
289 skipped_offset+=level_size;
290 size-=level_size;
291 if (level_size>16)
292 { // If surface is bigger than one block (8 or 16 bytes)...
293 level_size/=4;
294 }
295 }
296
297 // Skip the header and info block and possible unused mip levels
298 unsigned seek_size=file->Seek(SurfaceDesc.Size+4+skipped_offset);
299 WWASSERT(seek_size==(SurfaceDesc.Size+4+skipped_offset));
300
301 if (size && size<0x80000000)
302 {
303 // Allocate memory for the data excluding the headers
304 DDSMemory=MSGW3DNEWARRAY("DDSMemory") unsigned char[size];
305 // Read data
306 unsigned read_size=file->Read(DDSMemory,size);
307 // Verify we got all the data
308 WWASSERT(read_size==size);
309 }
310 file->Close();
311 return true;
312}
313
314// ----------------------------------------------------------------------------
315
316WWINLINE static unsigned RGB565_To_ARGB8888(unsigned short rgb)
317{
318 unsigned rgba=0;
319 rgba|=unsigned(rgb&0x001f)<<3;
320 rgba|=unsigned(rgb&0x07e0)<<5;
321 rgba|=unsigned(rgb&0xf800)<<8;
322 return rgba;
323}
324
325WWINLINE static unsigned short ARGB8888_To_RGB565(unsigned argb_)
326{
327 unsigned char* argb=(unsigned char*)&argb_;
328 unsigned short rgb;
329 rgb=((argb[2])&0xf8)<<8;
330 rgb|=((argb[1])&0xfc)<<3;
331 rgb|=((argb[0])&0xf8)>>3;
332 return rgb;
333}
334
335
336// ----------------------------------------------------------------------------
337//
338// Copy mipmap level to D3D surface. The copying is performed using another
339// Copy_Level_To_Surface function (see below).
340//
341// ----------------------------------------------------------------------------
342
343void DDSFileClass::Copy_Level_To_Surface(unsigned level,IDirect3DSurface8* d3d_surface,const Vector3& hsv_shift)
344{
345 WWASSERT(d3d_surface);
346 // Verify that the destination surface size matches the source surface size
347 D3DSURFACE_DESC surface_desc;
348 DX8_ErrorCode(d3d_surface->GetDesc(&surface_desc));
349
350 // First lock the surface
351 D3DLOCKED_RECT locked_rect;
352 DX8_ErrorCode(d3d_surface->LockRect(&locked_rect,NULL,0));
353
355 level,
356 D3DFormat_To_WW3DFormat(surface_desc.Format),
357 surface_desc.Width,
358 surface_desc.Height,
359 reinterpret_cast<unsigned char*>(locked_rect.pBits),
360 locked_rect.Pitch,
361 hsv_shift);
362
363 // Finally, unlock the surface
364 DX8_ErrorCode(d3d_surface->UnlockRect());
365}
366
367// ----------------------------------------------------------------------------
368//
369// Copy one mipmap level of texture to a memory surface. Surface type conversion
370// is performed if the destination is of different format. Scaling will be done
371// one of these days as well. Conversions between different types of compressed
372// surfaces are not performed and scaling of compressed surfaces is also not
373// possible.
374//
375// ----------------------------------------------------------------------------
376
378(
379 unsigned level,
380 WW3DFormat dest_format,
381 unsigned dest_width,
382 unsigned dest_height,
383 unsigned char* dest_surface,
384 unsigned dest_pitch,
385 const Vector3& hsv_shift
386)
387{
388 WWASSERT(DDSMemory);
389 WWASSERT(dest_surface);
390
391 if (!DDSMemory || !Get_Memory_Pointer(level))
392 {
393 WWASSERT_PRINT(DDSMemory,"Surface mip level pointer is missing\n");
394 return;
395 }
396
397 // If the format and size is a match just copy the contents
398 bool has_hsv_shift = hsv_shift[0]!=0.0f || hsv_shift[1]!=0.0f || hsv_shift[2]!=0.0f;
399 if (dest_format==Format && dest_width==Get_Width(level) && dest_height==Get_Height(level)) {
400 // If hue shift, we can't just copy...
401 if (has_hsv_shift) {
402 if (Format==WW3D_FORMAT_DXT1) {
403 const unsigned* src_ptr=reinterpret_cast<const unsigned*>(Get_Memory_Pointer(level));
404 unsigned* dest_ptr=reinterpret_cast<unsigned*>(dest_surface);
405 for (unsigned y=0;y<dest_height;y+=4) {
406 for (unsigned x=0;x<dest_width;x+=4) {
407 unsigned cols=*src_ptr++; // Bytes 1-4 of color block
408 unsigned col0=RGB565_To_ARGB8888(unsigned short(cols>>16));
409 unsigned col1=RGB565_To_ARGB8888(unsigned short(cols&0xffff));
410 Recolor(col0,hsv_shift);
411 Recolor(col1,hsv_shift);
412 col0=ARGB8888_To_RGB565(col0);
413 col1=ARGB8888_To_RGB565(col1);
414 cols=unsigned(col0)<<16|col1;
415 *dest_ptr++=cols;
416
417 *dest_ptr++=*src_ptr++; // Bytes 5-8 of color block
418 }
419 }
420 }
421 else if (Format==WW3D_FORMAT_DXT5) {
422 const unsigned* src_ptr=reinterpret_cast<const unsigned*>(Get_Memory_Pointer(level));
423 unsigned* dest_ptr=reinterpret_cast<unsigned*>(dest_surface);
424 for (unsigned y=0;y<dest_height;y+=4) {
425 for (unsigned x=0;x<dest_width;x+=4) {
426 *dest_ptr++=*src_ptr++; // Bytes 1-4 of alpha block
427 *dest_ptr++=*src_ptr++; // Bytes 5-8 of alpha block
428 unsigned cols=*src_ptr++; // Bytes 1-4 of color block
429 unsigned col0=RGB565_To_ARGB8888(unsigned short(cols>>16));
430 unsigned col1=RGB565_To_ARGB8888(unsigned short(cols&0xffff));
431 Recolor(col0,hsv_shift);
432 Recolor(col1,hsv_shift);
433 col0=ARGB8888_To_RGB565(col0);
434 col1=ARGB8888_To_RGB565(col1);
435 cols=unsigned(col0)<<16|col1;
436 *dest_ptr++=cols;
437
438 *dest_ptr++=*src_ptr++; // Bytes 5-8 of color block
439 }
440 }
441 }
442 else {
443 WWASSERT(0);
444 }
445
446 }
447 else {
448 unsigned compressed_size=Get_Level_Size(level);
449 memcpy(dest_surface,Get_Memory_Pointer(level),compressed_size);
450 }
451 }
452 else {
453 // If size matches, copy each pixel linearly with color space conversion
454 if (dest_width==Get_Width(level) && dest_height==Get_Height(level)) {
455 // An exception here - if the source format is DXT1 and the destination
456 // is DXT2, just copy the contents and create an empty alpha channel.
457 // This is needed on NVidia cards that have problems with DXT1 compression.
458 if (Format==WW3D_FORMAT_DXT1 && dest_format==WW3D_FORMAT_DXT2) {
459 // If hue shift, we can't just copy...
460 if (has_hsv_shift) {
461 const unsigned* src_ptr=reinterpret_cast<const unsigned*>(Get_Memory_Pointer(level));
462 unsigned* dest_ptr=reinterpret_cast<unsigned*>(dest_surface);
463 for (unsigned y=0;y<dest_height;y+=4) {
464 for (unsigned x=0;x<dest_width;x+=4) {
465 *dest_ptr++=0xffffffff; // Bytes 1-4 of alpha block
466 *dest_ptr++=0xffffffff; // Bytes 5-8 of alpha block
467// *dest_ptr++=*src_ptr++; // Bytes 1-4 of color block
468
469 unsigned cols=*src_ptr++; // Bytes 1-4 of color block
470 unsigned col0=RGB565_To_ARGB8888(unsigned short(cols>>16));
471 unsigned col1=RGB565_To_ARGB8888(unsigned short(cols&0xffff));
472 Recolor(col0,hsv_shift);
473 Recolor(col1,hsv_shift);
474 col0=ARGB8888_To_RGB565(col0);
475 col1=ARGB8888_To_RGB565(col1);
476 cols=unsigned(col0)<<16|col1;
477 *dest_ptr++=cols;
478
479 *dest_ptr++=*src_ptr++; // Bytes 5-8 of color block
480 }
481 }
482 }
483 else {
484 const unsigned* src_ptr=reinterpret_cast<const unsigned*>(Get_Memory_Pointer(level));
485 unsigned* dest_ptr=reinterpret_cast<unsigned*>(dest_surface);
486 for (unsigned y=0;y<dest_height;y+=4) {
487 for (unsigned x=0;x<dest_width;x+=4) {
488 *dest_ptr++=0xffffffff; // Bytes 1-4 of alpha block
489 *dest_ptr++=0xffffffff; // Bytes 5-8 of alpha block
490 *dest_ptr++=*src_ptr++; // Bytes 1-4 of color block
491 *dest_ptr++=*src_ptr++; // Bytes 5-8 of color block
492 }
493 }
494 }
495 }
496 else {
497 unsigned dest_bpp=Get_Bytes_Per_Pixel(dest_format);
498
499 // Copy 4x4 block at a time
500 bool contains_alpha=false;
501 for (unsigned y=0;y<dest_height;y+=4) {
502 unsigned char* dest_ptr=dest_surface;
503 dest_ptr+=y*dest_pitch;
504 for (unsigned x=0;x<dest_width;x+=4,dest_ptr+=dest_bpp*4) {
505 contains_alpha|=Get_4x4_Block(dest_ptr,dest_pitch,dest_format,level,x,y,hsv_shift);
506 }
507 }
508 if (Format==WW3D_FORMAT_DXT1 && contains_alpha) {
509 WWDEBUG_SAY(("Warning: DXT1 format should not contain alpha information - file %s\n",Name));
510 }
511 }
512 }
513 }
514}
515
516// cube map
518(
519 unsigned int face,
520 unsigned int level
521) const
522{
523 return &DDSMemory[CubeFaceSize*face+LevelOffsets[level]];
524}
525
526
528(
529 unsigned face,
530 unsigned level,
531 WW3DFormat dest_format,
532 unsigned dest_width,
533 unsigned dest_height,
534 unsigned char* dest_surface,
535 unsigned dest_pitch,
536 const Vector3& hsv_shift
537)
538{
539 WWASSERT(DDSMemory);
540 WWASSERT(dest_surface);
541
542 if (!DDSMemory || !Get_CubeMap_Memory_Pointer(face,level))
543 {
544 WWASSERT_PRINT(DDSMemory,"Surface mip level pointer is missing\n");
545 return;
546 }
547
548 // If the format and size is a match just copy the contents
549 bool has_hsv_shift = hsv_shift[0]!=0.0f || hsv_shift[1]!=0.0f || hsv_shift[2]!=0.0f;
550 if (dest_format==Format && dest_width==Get_Width(level) && dest_height==Get_Height(level))
551 {
552 // If hue shift, we can't just copy...
553 if (has_hsv_shift)
554 {
555 if (Format==WW3D_FORMAT_DXT1)
556 {
557 const unsigned* src_ptr=reinterpret_cast<const unsigned*>(Get_CubeMap_Memory_Pointer(face,level));
558 unsigned* dest_ptr=reinterpret_cast<unsigned*>(dest_surface);
559 for (unsigned y=0;y<dest_height;y+=4)
560 {
561 for (unsigned x=0;x<dest_width;x+=4)
562 {
563 unsigned cols=*src_ptr++; // Bytes 1-4 of color block
564 unsigned col0=RGB565_To_ARGB8888(unsigned short(cols>>16));
565 unsigned col1=RGB565_To_ARGB8888(unsigned short(cols&0xffff));
566 Recolor(col0,hsv_shift);
567 Recolor(col1,hsv_shift);
568 col0=ARGB8888_To_RGB565(col0);
569 col1=ARGB8888_To_RGB565(col1);
570 cols=unsigned(col0)<<16|col1;
571 *dest_ptr++=cols;
572
573 *dest_ptr++=*src_ptr++; // Bytes 5-8 of color block
574 }
575 }
576 }
577 else if (Format==WW3D_FORMAT_DXT5)
578 {
579 const unsigned* src_ptr=reinterpret_cast<const unsigned*>(Get_CubeMap_Memory_Pointer(face,level));
580 unsigned* dest_ptr=reinterpret_cast<unsigned*>(dest_surface);
581 for (unsigned y=0;y<dest_height;y+=4)
582 {
583 for (unsigned x=0;x<dest_width;x+=4)
584 {
585 *dest_ptr++=*src_ptr++; // Bytes 1-4 of alpha block
586 *dest_ptr++=*src_ptr++; // Bytes 5-8 of alpha block
587 unsigned cols=*src_ptr++; // Bytes 1-4 of color block
588 unsigned col0=RGB565_To_ARGB8888(unsigned short(cols>>16));
589 unsigned col1=RGB565_To_ARGB8888(unsigned short(cols&0xffff));
590 Recolor(col0,hsv_shift);
591 Recolor(col1,hsv_shift);
592 col0=ARGB8888_To_RGB565(col0);
593 col1=ARGB8888_To_RGB565(col1);
594 cols=unsigned(col0)<<16|col1;
595 *dest_ptr++=cols;
596
597 *dest_ptr++=*src_ptr++; // Bytes 5-8 of color block
598 }
599 }
600 }
601 else
602 {
603 WWASSERT(0);
604 }
605
606 }
607 else
608 {
609 unsigned compressed_size=Get_Level_Size(level);
610 memcpy(dest_surface,Get_CubeMap_Memory_Pointer(face,level),compressed_size);
611 }
612 }
613 else
614 {
615 // If size matches, copy each pixel linearly with color space conversion
616 if (dest_width==Get_Width(level) && dest_height==Get_Height(level))
617 {
618 // An exception here - if the source format is DXT1 and the destination
619 // is DXT2, just copy the contents and create an empty alpha channel.
620 // This is needed on NVidia cards that have problems with DXT1 compression.
621 if (Format==WW3D_FORMAT_DXT1 && dest_format==WW3D_FORMAT_DXT2)
622 {
623 // If hue shift, we can't just copy...
624 if (has_hsv_shift)
625 {
626 const unsigned* src_ptr=reinterpret_cast<const unsigned*>(Get_CubeMap_Memory_Pointer(face,level));
627 unsigned* dest_ptr=reinterpret_cast<unsigned*>(dest_surface);
628 for (unsigned y=0;y<dest_height;y+=4)
629 {
630 for (unsigned x=0;x<dest_width;x+=4)
631 {
632 *dest_ptr++=0xffffffff; // Bytes 1-4 of alpha block
633 *dest_ptr++=0xffffffff; // Bytes 5-8 of alpha block
634// *dest_ptr++=*src_ptr++; // Bytes 1-4 of color block
635
636 unsigned cols=*src_ptr++; // Bytes 1-4 of color block
637 unsigned col0=RGB565_To_ARGB8888(unsigned short(cols>>16));
638 unsigned col1=RGB565_To_ARGB8888(unsigned short(cols&0xffff));
639 Recolor(col0,hsv_shift);
640 Recolor(col1,hsv_shift);
641 col0=ARGB8888_To_RGB565(col0);
642 col1=ARGB8888_To_RGB565(col1);
643 cols=unsigned(col0)<<16|col1;
644 *dest_ptr++=cols;
645
646 *dest_ptr++=*src_ptr++; // Bytes 5-8 of color block
647 }
648 }
649 }
650 else
651 {
652 const unsigned* src_ptr=reinterpret_cast<const unsigned*>(Get_CubeMap_Memory_Pointer(face,level));
653 unsigned* dest_ptr=reinterpret_cast<unsigned*>(dest_surface);
654 for (unsigned y=0;y<dest_height;y+=4)
655 {
656 for (unsigned x=0;x<dest_width;x+=4)
657 {
658 *dest_ptr++=0xffffffff; // Bytes 1-4 of alpha block
659 *dest_ptr++=0xffffffff; // Bytes 5-8 of alpha block
660 *dest_ptr++=*src_ptr++; // Bytes 1-4 of color block
661 *dest_ptr++=*src_ptr++; // Bytes 5-8 of color block
662 }
663 }
664 }
665 }
666 else
667 {
668 unsigned dest_bpp=Get_Bytes_Per_Pixel(dest_format);
669
670 // Copy 4x4 block at a time
671 bool contains_alpha=false;
672 for (unsigned y=0;y<dest_height;y+=4)
673 {
674 unsigned char* dest_ptr=dest_surface;
675 dest_ptr+=y*dest_pitch;
676 for (unsigned x=0;x<dest_width;x+=4,dest_ptr+=dest_bpp*4)
677 {
678 contains_alpha|=Get_4x4_Block(dest_ptr,dest_pitch,dest_format,level,x,y,hsv_shift);
679 }
680 }
681 if (Format==WW3D_FORMAT_DXT1 && contains_alpha)
682 {
683 WWDEBUG_SAY(("Warning: DXT1 format should not contain alpha information - file %s\n",Name));
684 }
685 }
686 }
687 }
688}
689
690// volume texture copy
691const unsigned char* DDSFileClass::Get_Volume_Memory_Pointer(unsigned int level) const
692{
693 return NULL;//DDSMemory[
694}
695
697(
698 unsigned level,
699 unsigned depth,
700 WW3DFormat dest_format,
701 unsigned dest_width,
702 unsigned dest_height,
703 unsigned char* dest_surface,
704 unsigned row_pitch,
705 unsigned slice_pitch,
706 const Vector3& hsv_shift
707)
708{
709 WWASSERT(DDSMemory);
710 WWASSERT(dest_surface);
711
712 if (!DDSMemory || !Get_Volume_Memory_Pointer(level))
713 {
714 WWASSERT_PRINT(DDSMemory,"Surface mip level pointer is missing\n");
715 return;
716 }
717
718 // get 'dest_surface'
719
720
721 // If the format and size is a match just copy the contents
722 bool has_hsv_shift = hsv_shift[0]!=0.0f || hsv_shift[1]!=0.0f || hsv_shift[2]!=0.0f;
723 if (dest_format==Format && dest_width==Get_Width(level) && dest_height==Get_Height(level))
724 {
725 // If hue shift, we can't just copy...
726 if (has_hsv_shift)
727 {
728 if (Format==WW3D_FORMAT_DXT1)
729 {
730 const unsigned* src_ptr=reinterpret_cast<const unsigned*>(Get_Volume_Memory_Pointer(level));
731 unsigned* dest_ptr=reinterpret_cast<unsigned*>(dest_surface);
732 for (unsigned y=0;y<dest_height;y+=4)
733 {
734 for (unsigned x=0;x<dest_width;x+=4)
735 {
736 unsigned cols=*src_ptr++; // Bytes 1-4 of color block
737 unsigned col0=RGB565_To_ARGB8888(unsigned short(cols>>16));
738 unsigned col1=RGB565_To_ARGB8888(unsigned short(cols&0xffff));
739 Recolor(col0,hsv_shift);
740 Recolor(col1,hsv_shift);
741 col0=ARGB8888_To_RGB565(col0);
742 col1=ARGB8888_To_RGB565(col1);
743 cols=unsigned(col0)<<16|col1;
744 *dest_ptr++=cols;
745
746 *dest_ptr++=*src_ptr++; // Bytes 5-8 of color block
747 }
748 }
749 }
750 else if (Format==WW3D_FORMAT_DXT5)
751 {
752 const unsigned* src_ptr=reinterpret_cast<const unsigned*>(Get_Volume_Memory_Pointer(level));
753 unsigned* dest_ptr=reinterpret_cast<unsigned*>(dest_surface);
754 for (unsigned y=0;y<dest_height;y+=4)
755 {
756 for (unsigned x=0;x<dest_width;x+=4)
757 {
758 *dest_ptr++=*src_ptr++; // Bytes 1-4 of alpha block
759 *dest_ptr++=*src_ptr++; // Bytes 5-8 of alpha block
760 unsigned cols=*src_ptr++; // Bytes 1-4 of color block
761 unsigned col0=RGB565_To_ARGB8888(unsigned short(cols>>16));
762 unsigned col1=RGB565_To_ARGB8888(unsigned short(cols&0xffff));
763 Recolor(col0,hsv_shift);
764 Recolor(col1,hsv_shift);
765 col0=ARGB8888_To_RGB565(col0);
766 col1=ARGB8888_To_RGB565(col1);
767 cols=unsigned(col0)<<16|col1;
768 *dest_ptr++=cols;
769
770 *dest_ptr++=*src_ptr++; // Bytes 5-8 of color block
771 }
772 }
773 }
774 else
775 {
776 WWASSERT(0);
777 }
778
779 }
780 else
781 {
782 unsigned compressed_size=Get_Level_Size(level);
783 memcpy(dest_surface,Get_Volume_Memory_Pointer(level),compressed_size);
784 }
785 }
786 else
787 {
788 // If size matches, copy each pixel linearly with color space conversion
789 if (dest_width==Get_Width(level) && dest_height==Get_Height(level))
790 {
791 // An exception here - if the source format is DXT1 and the destination
792 // is DXT2, just copy the contents and create an empty alpha channel.
793 // This is needed on NVidia cards that have problems with DXT1 compression.
794 if (Format==WW3D_FORMAT_DXT1 && dest_format==WW3D_FORMAT_DXT2)
795 {
796 // If hue shift, we can't just copy...
797 if (has_hsv_shift)
798 {
799 const unsigned* src_ptr=reinterpret_cast<const unsigned*>(Get_Volume_Memory_Pointer(level));
800 unsigned* dest_ptr=reinterpret_cast<unsigned*>(dest_surface);
801 for (unsigned y=0;y<dest_height;y+=4)
802 {
803 for (unsigned x=0;x<dest_width;x+=4)
804 {
805 *dest_ptr++=0xffffffff; // Bytes 1-4 of alpha block
806 *dest_ptr++=0xffffffff; // Bytes 5-8 of alpha block
807// *dest_ptr++=*src_ptr++; // Bytes 1-4 of color block
808
809 unsigned cols=*src_ptr++; // Bytes 1-4 of color block
810 unsigned col0=RGB565_To_ARGB8888(unsigned short(cols>>16));
811 unsigned col1=RGB565_To_ARGB8888(unsigned short(cols&0xffff));
812 Recolor(col0,hsv_shift);
813 Recolor(col1,hsv_shift);
814 col0=ARGB8888_To_RGB565(col0);
815 col1=ARGB8888_To_RGB565(col1);
816 cols=unsigned(col0)<<16|col1;
817 *dest_ptr++=cols;
818
819 *dest_ptr++=*src_ptr++; // Bytes 5-8 of color block
820 }
821 }
822 }
823 else
824 {
825 const unsigned* src_ptr=reinterpret_cast<const unsigned*>(Get_Volume_Memory_Pointer(level));
826 unsigned* dest_ptr=reinterpret_cast<unsigned*>(dest_surface);
827 for (unsigned y=0;y<dest_height;y+=4)
828 {
829 for (unsigned x=0;x<dest_width;x+=4)
830 {
831 *dest_ptr++=0xffffffff; // Bytes 1-4 of alpha block
832 *dest_ptr++=0xffffffff; // Bytes 5-8 of alpha block
833 *dest_ptr++=*src_ptr++; // Bytes 1-4 of color block
834 *dest_ptr++=*src_ptr++; // Bytes 5-8 of color block
835 }
836 }
837 }
838 }
839 else
840 {
841 WWASSERT(0);
842 /* todo
843 unsigned dest_bpp=Get_Bytes_Per_Pixel(dest_format);
844
845 // Copy 4x4 block at a time
846 bool contains_alpha=false;
847 for (unsigned z=0;z<dest_depth;z++)
848 {
849 for (unsigned y=0;y<dest_height;y+=4)
850 {
851 unsigned char* dest_ptr=dest_surface;
852 row_ptr+=y*row_pitch;
853 for (unsigned x=0;x<dest_width;x+=4,dest_ptr+=dest_bpp*4)
854 {
855 contains_alpha|=Get_4x4_Block(dest_ptr,dest_pitch,dest_format,level,x,y,hsv_shift);
856 }
857 }
858 if (Format==WW3D_FORMAT_DXT1 && contains_alpha)
859 {
860 WWDEBUG_SAY(("Warning: DXT1 format should not contain alpha information - file %s\n",Name));
861 }
862 }*/
863 }
864 }
865 }
866}
867
868// ----------------------------------------------------------------------------
869
870WWINLINE static unsigned Combine_Colors(unsigned col1, unsigned col2, unsigned rel)
871{
872 const unsigned R_B_MASK=0x00ff00ff;
873 const unsigned G_MASK=0x0000ff00;
874
875 unsigned rel2=255-rel;
876
877 unsigned r_b_col1=col1&R_B_MASK;
878 r_b_col1*=rel;
879 unsigned r_b_col2=col2&R_B_MASK;
880 r_b_col2*=rel2;
881 r_b_col1+=r_b_col2;
882 r_b_col1>>=8;
883 r_b_col1&=R_B_MASK;
884
885
886 unsigned g_col1=col1&G_MASK;
887 g_col1*=rel;
888 unsigned g_col2=col2&G_MASK;
889 g_col2*=rel2;
890 g_col1+=g_col2;
891 g_col1>>=8;
892 g_col1&=G_MASK;
893
894 return r_b_col1|g_col1;
895
896/* float f=float(rel)/256.0f;
897
898 unsigned new_col=0;
899 new_col|=int(float(int(col1&0x00ff0000))*f+float(int(col2&0x00ff0000))*(1.0f-f))&0x00ff0000;
900 new_col|=int(float(int(col1&0x0000ff00))*f+float(int(col2&0x0000ff00))*(1.0f-f))&0x0000ff00;
901 new_col|=int(float(int(col1&0x000000ff))*f+float(int(col2&0x000000ff))*(1.0f-f))&0x000000ff;
902 return new_col;
903*/
904}
905
906// ----------------------------------------------------------------------------
907//
908// Note that this is NOT an efficient way of extracting pixels from compressed image - we should implement
909// faster block-copy method for non-scaled copying.
910//
911// ----------------------------------------------------------------------------
912
913unsigned DDSFileClass::Get_Pixel(unsigned level,unsigned x,unsigned y) const
914{
915 WWASSERT(level<MipLevels);
916 WWASSERT(x<Get_Width(level));
917 WWASSERT(y<Get_Height(level));
918
919 switch (Format) {
920 // Note that we don't currently really support alpha on DXT1 - all alpha textures should use DXT5.
921 // The reason for this is that when converting from DXT1 to 16 bit uncompressed texture we want
922 // to be able to use RGB565 format instead of ARGB4444. As the alpha is encoded in DXT1 per-block
923 // basis there isn't really a way to tell if the surface has an alpha or not so either we use alpha
924 // or we don't.
925 case WW3D_FORMAT_DXT1:
926 {
927 const unsigned char* block_memory=Get_Memory_Pointer(level)+(x/4)*8+((y/4)*(Get_Width(level)/4))*8;
928
929 unsigned col0=RGB565_To_ARGB8888(*(unsigned short*)&block_memory[0]);
930 unsigned col1=RGB565_To_ARGB8888(*(unsigned short*)&block_memory[2]);
931 unsigned char line=block_memory[4+(y%4)];
932 line>>=(x%4)*2;
933 line=(line&3);
934 if (col0>col1) {
935 switch (line) {
936 case 0: return col0|0xff000000;
937 case 1: return col1|0xff000000;
938 case 2: return Combine_Colors(col1,col0,85)|0xff000000;
939 case 3: return Combine_Colors(col0,col1,85)|0xff000000;
940 }
941 }
942 else {
943 switch (line) {
944 case 0: return col0|0xff000000;
945 case 1: return col1|0xff000000;
946 case 2: return Combine_Colors(col1,col0,128)|0xff000000;
947 case 3: return 0x00000000;
948 }
949 }
950 }
951 break;
952 case WW3D_FORMAT_DXT2:
953 return 0xffffffff;
954 case WW3D_FORMAT_DXT3:
955 return 0xffffffff;
956 case WW3D_FORMAT_DXT4:
957 return 0xffffffff;
958 case WW3D_FORMAT_DXT5:
959 {
960 const unsigned char* alpha_block=Get_Memory_Pointer(level)+(x/4)*16+((y/4)*(Get_Width(level)/4))*16;
961
962 unsigned alpha0=alpha_block[0];
963 unsigned alpha1=alpha_block[1];
964
965 unsigned bit_idx=((x%4)+4*(y%4))*3;
966 unsigned byte_idx=bit_idx/8;
967 bit_idx%=8;
968 unsigned alpha_index=0;
969 for (int i=0;i<3;++i) {
970 WWASSERT(byte_idx<6);
971 unsigned alpha_bit=(alpha_block[2+byte_idx]>>(bit_idx))&1;
972 alpha_index|=alpha_bit<<(i);
973 bit_idx++;
974 if (bit_idx>=8) {
975 bit_idx=0;
976 byte_idx++;
977 }
978 }
979 WWASSERT(alpha_index<8);
980
981 // 8-alpha or 6-alpha block?
982 unsigned alpha_value=0;
983 if (alpha0>alpha1) {
984 // 8-alpha block: derive the other six alphas.
985 // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
986 switch (alpha_index) {
987 case 0: alpha_value=alpha0; break;
988 case 1: alpha_value=alpha1; break;
989 case 2: alpha_value=(6*alpha0+1*alpha1+3) / 7; break; // bit code 010
990 case 3: alpha_value=(5*alpha0+2*alpha1+3) / 7; break; // bit code 011
991 case 4: alpha_value=(4*alpha0+3*alpha1+3) / 7; break; // bit code 100
992 case 5: alpha_value=(3*alpha0+4*alpha1+3) / 7; break; // bit code 101
993 case 6: alpha_value=(2*alpha0+5*alpha1+3) / 7; break; // bit code 110
994 case 7: alpha_value=(1*alpha0+6*alpha1+3) / 7; break; // bit code 111
995 }
996 }
997 else {
998 // 6-alpha block.
999 // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
1000 switch (alpha_index) {
1001 case 0: alpha_value=alpha0; break;
1002 case 1: alpha_value=alpha1; break;
1003 case 2: alpha_value=(4*alpha0+1*alpha1+2) / 5; break; // Bit code 010
1004 case 3: alpha_value=(3*alpha0+2*alpha1+2) / 5; break; // Bit code 011
1005 case 4: alpha_value=(2*alpha0+3*alpha1+2) / 5; break; // Bit code 100
1006 case 5: alpha_value=(1*alpha0+4*alpha1+2) / 5; break; // Bit code 101
1007 case 6: alpha_value=0; break; // Bit code 110
1008 case 7: alpha_value=255; break; // Bit code 111
1009 }
1010 }
1011 alpha_value<<=24;
1012
1013 // Extract color
1014
1015 const unsigned char* color_block=alpha_block+8;
1016 unsigned col0=RGB565_To_ARGB8888(*(unsigned short*)&color_block[0]);
1017 unsigned col1=RGB565_To_ARGB8888(*(unsigned short*)&color_block[2]);
1018 unsigned char line=color_block[4+(y%4)];
1019 line>>=(x%4)*2;
1020 line=(line&3);
1021 switch (line) {
1022 case 0: return col0|alpha_value;
1023 case 1: return col1|alpha_value;
1024 case 2: return Combine_Colors(col1,col0,85)|alpha_value;
1025 case 3: return Combine_Colors(col0,col1,85)|alpha_value;
1026 }
1027 }
1028 break;
1029 }
1030 return 0xffffffff;
1031}
1032
1033// ----------------------------------------------------------------------------
1034//
1035// Uncompress one 4x4 block from the compressed image.
1036//
1037// Returns: true if block contained alpha, false is not
1038//
1039// Note: Destination can't be DXT or paletted surface!
1040//
1041// ----------------------------------------------------------------------------
1042
1044 unsigned char* dest_ptr, // Destination surface pointer
1045 unsigned dest_pitch, // Destination surface pitch, in bytes
1046 WW3DFormat dest_format, // Destination surface format, A8R8G8B8 is fastest
1047 unsigned level, // DDS mipmap level to copy from
1048 unsigned source_x, // DDS x offset to copy from, must be aligned by 4!
1049 unsigned source_y, // DDS y offset to copy from, must be aligned by 4!
1050 const Vector3& hsv_shift) const
1051{
1052 // Verify the block alignment
1053 WWASSERT((source_x&3)==0);
1054 WWASSERT((source_y&3)==0);
1055 // Verify level
1056 WWASSERT(level<MipLevels);
1057 // Verify coordinate bounds
1058 WWASSERT(source_x<Get_Width(level));
1059 WWASSERT(source_y<Get_Height(level));
1060
1061 unsigned dest_bpp=Get_Bytes_Per_Pixel(dest_format);
1062
1063 bool has_hsv_shift = hsv_shift[0]!=0.0f || hsv_shift[1]!=0.0f || hsv_shift[2]!=0.0f;
1064 switch (Format) {
1065 // Note that we don't currently really support alpha on DXT1 - all alpha textures should use DXT5.
1066 // The reason for this is that when converting from DXT1 to 16 bit uncompressed texture we want
1067 // to be able to use RGB565 format instead of ARGB4444. As the alpha is encoded in DXT1 per-block
1068 // basis there isn't really a way to tell if the surface has an alpha or not so either we use alpha
1069 // or we don't.
1070 case WW3D_FORMAT_DXT1:
1071 {
1072 const unsigned char* block_memory=Get_Memory_Pointer(level)+(source_x/4)*8+((source_y/4)*(Get_Width(level)/4))*8;
1073
1074 unsigned col0=RGB565_To_ARGB8888(*(unsigned short*)&block_memory[0]);
1075 unsigned col1=RGB565_To_ARGB8888(*(unsigned short*)&block_memory[2]);
1076 // Even if we don't support alpha, decompression is different if source has alpha
1077 unsigned dest_pixel=0;
1078 if (col0>col1) {
1079 if (has_hsv_shift) {
1080 Recolor(col0,hsv_shift);
1081 Recolor(col1,hsv_shift);
1082 }
1083
1084 for (int y=0;y<4;++y) {
1085 unsigned char* tmp_dest_ptr=dest_ptr;
1086 dest_ptr+=dest_pitch;
1087 unsigned char line=block_memory[4+y];
1088 for (int x=0;x<4;++x) {
1089 switch (line&3) {
1090 case 0: dest_pixel=col0|0xff000000; break;
1091 case 1: dest_pixel=col1|0xff000000; break;
1092 case 2: dest_pixel=Combine_Colors(col1,col0,85)|0xff000000; break;
1093 case 3: dest_pixel=Combine_Colors(col0,col1,85)|0xff000000; break;
1094 }
1095 line>>=2;
1096
1097 BitmapHandlerClass::Write_B8G8R8A8(tmp_dest_ptr,dest_format,dest_pixel);
1098 tmp_dest_ptr+=dest_bpp;
1099 }
1100 }
1101 return false; // No alpha found in the block
1102 }
1103 else {
1104 if (has_hsv_shift) {
1105 Recolor(col0,hsv_shift);
1106 Recolor(col1,hsv_shift);
1107 }
1108 bool contains_alpha=false;
1109 for (int y=0;y<4;++y) {
1110 unsigned char* tmp_dest_ptr=dest_ptr;
1111 dest_ptr+=dest_pitch;
1112 unsigned char line=block_memory[4+y];
1113 for (int x=0;x<4;++x) {
1114 switch (line&3) {
1115 case 0: dest_pixel=col0|0xff000000; break;
1116 case 1: dest_pixel=col1|0xff000000; break;
1117 case 2: dest_pixel=Combine_Colors(col1,col0,128)|0xff000000; break;
1118 case 3: dest_pixel=0x00000000; contains_alpha=true; break;
1119 }
1120 line>>=2;
1121
1122 BitmapHandlerClass::Write_B8G8R8A8(tmp_dest_ptr,dest_format,dest_pixel);
1123 tmp_dest_ptr+=dest_bpp;
1124 }
1125 }
1126 return contains_alpha; // Alpha block...?
1127 }
1128 }
1129 break;
1130 case WW3D_FORMAT_DXT2:
1131 return false;
1132 case WW3D_FORMAT_DXT3:
1133 return false;
1134 case WW3D_FORMAT_DXT4:
1135 return false;
1136 case WW3D_FORMAT_DXT5:
1137 {
1138 // Init alphas
1139 const unsigned char* alpha_block=Get_Memory_Pointer(level)+(source_x/4)*16+((source_y/4)*(Get_Width(level)/4))*16;
1140
1141 unsigned alphas[8];
1142 alphas[0]=alpha_block[0];
1143 alphas[1]=alpha_block[1];
1144
1145 // 8-alpha or 6-alpha block?
1146 if (alphas[0]>alphas[1]) {
1147 alphas[2]=(6*alphas[0]+1*alphas[1]+3) / 7; // bit code 010
1148 alphas[3]=(5*alphas[0]+2*alphas[1]+3) / 7; // bit code 011
1149 alphas[4]=(4*alphas[0]+3*alphas[1]+3) / 7; // bit code 100
1150 alphas[5]=(3*alphas[0]+4*alphas[1]+3) / 7; // bit code 101
1151 alphas[6]=(2*alphas[0]+5*alphas[1]+3) / 7; // bit code 110
1152 alphas[7]=(1*alphas[0]+6*alphas[1]+3) / 7; // bit code 111
1153 }
1154 else {
1155 alphas[2]=(4*alphas[0]+1*alphas[1]+2) / 5; // Bit code 010
1156 alphas[3]=(3*alphas[0]+2*alphas[1]+2) / 5; // Bit code 011
1157 alphas[4]=(2*alphas[0]+3*alphas[1]+2) / 5; // Bit code 100
1158 alphas[5]=(1*alphas[0]+4*alphas[1]+2) / 5; // Bit code 101
1159 alphas[6]=0; // Bit code 110
1160 alphas[7]=255; // Bit code 111
1161 }
1162
1163 // Init colors
1164 const unsigned char* color_block=alpha_block+8;
1165 unsigned col0=RGB565_To_ARGB8888(*(unsigned short*)&color_block[0]);
1166 unsigned col1=RGB565_To_ARGB8888(*(unsigned short*)&color_block[2]);
1167 if (has_hsv_shift) {
1168 Recolor(col0,hsv_shift);
1169 Recolor(col1,hsv_shift);
1170 }
1171
1172 unsigned dest_pixel=0;
1173 unsigned bit_idx=0;
1174 unsigned contains_alpha=0xff;
1175
1176 unsigned alpha_indices[16];
1177 unsigned* ai_ptr=alpha_indices;
1178 for (int a=0;a<2;++a) {
1179 ai_ptr[0]=alpha_block[2]&0x7;
1180 ai_ptr[1]=(alpha_block[2]>>3)&0x7;
1181 ai_ptr[2]=(alpha_block[2]>>6)|((alpha_block[3]&1)<<2);
1182 ai_ptr[3]=(alpha_block[3]>>1)&0x7;
1183 ai_ptr[4]=(alpha_block[3]>>4)&0x7;
1184 ai_ptr[5]=(alpha_block[3]>>7)|((alpha_block[4]&3)<<1);
1185 ai_ptr[6]=(alpha_block[4]>>2)&0x7;
1186 ai_ptr[7]=(alpha_block[4]>>5);
1187 ai_ptr+=8;
1188 alpha_block+=3;
1189 }
1190
1191 unsigned aii=0;
1192 for (int y=0;y<4;++y) {
1193 unsigned char* tmp_dest_ptr=dest_ptr;
1194 dest_ptr+=dest_pitch;
1195 unsigned char line=color_block[4+y];
1196 for (int x=0;x<4;++x,bit_idx+=3) {
1197 unsigned alpha_value=alphas[alpha_indices[aii++]];
1198 contains_alpha&=alpha_value;
1199 alpha_value<<=24;
1200
1201 // Extract color
1202
1203 switch (line&3) {
1204 case 0: dest_pixel=col0|alpha_value; break;
1205 case 1: dest_pixel=col1|alpha_value; break;
1206 case 2: dest_pixel=Combine_Colors(col1,col0,85)|alpha_value; break;
1207 case 3: dest_pixel=Combine_Colors(col0,col1,85)|alpha_value; break;
1208 }
1209 line>>=2;
1210
1211 BitmapHandlerClass::Write_B8G8R8A8(tmp_dest_ptr,dest_format,dest_pixel);
1212 tmp_dest_ptr+=dest_bpp;
1213 }
1214 }
1215
1216
1217
1218
1219/*
1220 for (int y=0;y<4;++y) {
1221 unsigned char* tmp_dest_ptr=dest_ptr;
1222 dest_ptr+=dest_pitch;
1223 unsigned char line=color_block[4+y];
1224 for (int x=0;x<4;++x,bit_idx+=3) {
1225 unsigned byte_idx=bit_idx/8;
1226 unsigned tmp_bit_idx=bit_idx&7;
1227 unsigned alpha_index=0;
1228 for (int i=0;i<3;++i) {
1229 WWASSERT(byte_idx<6);
1230 unsigned alpha_bit=(alpha_block[2+byte_idx]>>(tmp_bit_idx))&1;
1231 alpha_index|=alpha_bit<<(i);
1232 tmp_bit_idx++;
1233 if (tmp_bit_idx>=8) {
1234 tmp_bit_idx=0;
1235 byte_idx++;
1236 }
1237 }
1238 WWASSERT(alpha_index<8);
1239 unsigned alpha_value=alphas[alpha_index];
1240 contains_alpha&=alpha_value;
1241 alpha_value<<=24;
1242
1243 // Extract color
1244
1245 switch (line&3) {
1246 case 0: dest_pixel=col0|alpha_value; break;
1247 case 1: dest_pixel=col1|alpha_value; break;
1248 case 2: dest_pixel=Combine_Colors(col1,col0,85)|alpha_value; break;
1249 case 3: dest_pixel=Combine_Colors(col0,col1,85)|alpha_value; break;
1250 }
1251 line>>=2;
1252
1253 BitmapHandlerClass::Write_B8G8R8A8(tmp_dest_ptr,dest_format,dest_pixel);
1254 tmp_dest_ptr+=dest_bpp;
1255 }
1256 }
1257*/
1258 return contains_alpha!=0xff; // Alpha block... DXT5 should only be used when the image needs alpha
1259 // but for now check anyway...
1260 }
1261 }
1262 return false;
1263
1264}
#define NULL
Definition BaseType.h:92
#define WWASSERT
#define W3DNEWARRAY
Definition always.h:110
#define WWINLINE
Definition always.h:172
#define MSGW3DNEWARRAY(MSG)
Definition always.h:108
static WWINLINE void Write_B8G8R8A8(unsigned char *dest_ptr, WW3DFormat dest_format, const unsigned char *argb)
const unsigned char * Get_Memory_Pointer(unsigned level) const
Definition ddsfile.cpp:219
DDSFileClass(const char *name, unsigned reduction_factor)
Definition ddsfile.cpp:39
const unsigned char * Get_Volume_Memory_Pointer(unsigned level) const
Definition ddsfile.cpp:691
unsigned Get_Height(unsigned level) const
Definition ddsfile.cpp:203
bool Get_4x4_Block(unsigned char *dest_ptr, unsigned dest_pitch, WW3DFormat dest_format, unsigned level, unsigned source_x, unsigned source_y, const Vector3 &hsv_shift=Vector3(0.0f, 0.0f, 0.0f)) const
Definition ddsfile.cpp:1043
bool Load()
Definition ddsfile.cpp:258
unsigned Get_Width(unsigned level) const
Definition ddsfile.cpp:195
unsigned Get_Depth(unsigned level) const
Definition ddsfile.cpp:211
void Copy_Level_To_Surface(unsigned level, IDirect3DSurface8 *d3d_surface, const Vector3 &hsv_shift=Vector3(0.0f, 0.0f, 0.0f))
Definition ddsfile.cpp:343
unsigned Get_Level_Size(unsigned level) const
Definition ddsfile.cpp:225
const unsigned char * Get_CubeMap_Memory_Pointer(unsigned face, unsigned level) const
Definition ddsfile.cpp:518
unsigned Get_Pixel(unsigned level, unsigned x, unsigned y) const
Definition ddsfile.cpp:913
void Copy_CubeMap_Level_To_Surface(unsigned face, unsigned level, WW3DFormat dest_format, unsigned width, unsigned height, unsigned char *surf, unsigned pitch, const Vector3 &hsv_shift=Vector3(0.0f, 0.0f, 0.0f))
Definition ddsfile.cpp:528
void Copy_Volume_Level_To_Surface(unsigned level, unsigned depth, WW3DFormat dest_format, unsigned width, unsigned height, unsigned char *vol, unsigned row_pitch, unsigned slice_pitch, const Vector3 &hsv_shift=Vector3(0.0f, 0.0f, 0.0f))
Definition ddsfile.cpp:697
virtual int Seek(int pos, int dir=SEEK_CUR)=0
virtual unsigned long Get_Date_Time(void)
Definition WWFILE.H:91
virtual int Size(void)=0
virtual bool Is_Available(int forced=false)=0
virtual int Read(void *buffer, int size)=0
virtual void Close(void)=0
virtual int Open(char const *filename, int rights=READ)=0
int _cdecl Format(const TCHAR *format,...)
Definition wwstring.cpp:273
void Recolor(Vector3 &rgb, const Vector3 &hsv_shift)
Definition colorspace.h:131
#define DDSCAPS2_CUBEMAP
Definition ddsfile.cpp:31
#define DDSCAPS2_VOLUME
Definition ddsfile.cpp:35
@ DDS_TEXTURE
Definition ddsfile.h:163
@ DDS_VOLUME
Definition ddsfile.h:165
@ DDS_CUBEMAP
Definition ddsfile.h:164
WWINLINE void DX8_ErrorCode(unsigned res)
Definition dx8wrapper.h:125
FileFactoryClass * _TheFileFactory
Definition ffactory.cpp:51
WW3DFormat D3DFormat_To_WW3DFormat(D3DFORMAT d3d_format)
Definition formconv.cpp:150
unsigned Get_Bytes_Per_Pixel(WW3DFormat format)
WW3DFormat
Definition ww3dformat.h:75
@ WW3D_FORMAT_DXT3
Definition ww3dformat.h:98
@ WW3D_FORMAT_DXT2
Definition ww3dformat.h:97
@ WW3D_FORMAT_DXT5
Definition ww3dformat.h:100
@ WW3D_FORMAT_UNKNOWN
Definition ww3dformat.h:76
@ WW3D_FORMAT_DXT4
Definition ww3dformat.h:99
@ WW3D_FORMAT_DXT1
Definition ww3dformat.h:96
#define WWASSERT_PRINT(expr, string)
Definition wwdebug.h:135
#define WWDEBUG_SAY(x)
Definition wwdebug.h:114