~ubuntu-branches/ubuntu/hardy/devil/hardy-updates

« back to all changes in this revision

Viewing changes to src-IL/src/il_dds.c

  • Committer: Bazaar Package Importer
  • Author(s): Marcelo E. Magallon
  • Date: 2005-01-03 19:57:42 UTC
  • Revision ID: james.westby@ubuntu.com-20050103195742-4ipkplcwygu3irv0
Tags: upstream-1.6.7
ImportĀ upstreamĀ versionĀ 1.6.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//-----------------------------------------------------------------------------
 
2
//
 
3
// ImageLib Sources
 
4
// Copyright (C) 2000-2002 by Denton Woods
 
5
// Last modified: 02/21/2002 <--Y2K Compliant! =]
 
6
//
 
7
// Filename: src-IL/src/il_dds.c
 
8
//
 
9
// Description: Reads from a DirectDraw Surface (.dds) file.
 
10
//
 
11
//-----------------------------------------------------------------------------
 
12
 
 
13
 
 
14
//
 
15
//
 
16
// Note:  Almost all this code is from nVidia's DDS-loading example at
 
17
//      http://www.nvidia.com/view.asp?IO=dxtc_decompression_code
 
18
//      and from the specs at
 
19
//      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dx8_c/hh/dx8_c/graphics_using_0j03.asp
 
20
//      and
 
21
//      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dx8_c/directx_cpp/Graphics/ProgrammersGuide/Appendix/DDSFileFormat/ovwDDSFileFormat.asp
 
22
//      However, some not really valid .dds files are also read, for example
 
23
//      Volume Textures without the COMPLEX bit set, so the specs aren't taken
 
24
//      too strictly while reading.
 
25
 
 
26
 
 
27
#include "il_internal.h"
 
28
#ifndef IL_NO_DDS
 
29
#include "il_dds.h"
 
30
 
 
31
 
 
32
// Global variables
 
33
DDSHEAD Head;                   // Image header
 
34
ILubyte *CompData;              // Compressed data
 
35
ILuint  CompSize;               // Compressed size
 
36
ILuint  CompLineSize;           // Compressed line size
 
37
ILuint  CompFormat;             // Compressed format
 
38
ILimage *Image;
 
39
ILint   Width, Height, Depth;
 
40
ILuint  BlockSize;
 
41
 
 
42
ILuint CubemapDirections[CUBEMAP_SIDES] = {
 
43
        DDS_CUBEMAP_POSITIVEX,
 
44
        DDS_CUBEMAP_NEGATIVEX,
 
45
        DDS_CUBEMAP_POSITIVEY,
 
46
        DDS_CUBEMAP_NEGATIVEY,
 
47
        DDS_CUBEMAP_POSITIVEZ,
 
48
        DDS_CUBEMAP_NEGATIVEZ
 
49
};
 
50
 
 
51
 
 
52
//! Checks if the file specified in FileName is a valid .dds file.
 
53
ILboolean ilIsValidDds(const ILstring FileName)
 
54
{
 
55
        ILHANDLE        DdsFile;
 
56
        ILboolean       bDds = IL_FALSE;
 
57
 
 
58
        if (!iCheckExtension(FileName, IL_TEXT("dds"))) {
 
59
                ilSetError(IL_INVALID_EXTENSION);
 
60
                return bDds;
 
61
        }
 
62
 
 
63
        DdsFile = iopenr(FileName);
 
64
        if (DdsFile == NULL) {
 
65
                ilSetError(IL_COULD_NOT_OPEN_FILE);
 
66
                return bDds;
 
67
        }
 
68
 
 
69
        bDds = ilIsValidDdsF(DdsFile);
 
70
        icloser(DdsFile);
 
71
 
 
72
        return bDds;
 
73
}
 
74
 
 
75
 
 
76
//! Checks if the ILHANDLE contains a valid .dds file at the current position.
 
77
ILboolean ilIsValidDdsF(ILHANDLE File)
 
78
{
 
79
        ILuint          FirstPos;
 
80
        ILboolean       bRet;
 
81
 
 
82
        iSetInputFile(File);
 
83
        FirstPos = itell();
 
84
        bRet = iIsValidDds();
 
85
        iseek(FirstPos, IL_SEEK_SET);
 
86
 
 
87
        return bRet;
 
88
}
 
89
 
 
90
 
 
91
//! Checks if Lump is a valid .dds lump.
 
92
ILboolean ilIsValidDdsL(ILvoid *Lump, ILuint Size)
 
93
{
 
94
        iSetInputLump(Lump, Size);
 
95
        return iIsValidDds();
 
96
}
 
97
 
 
98
 
 
99
// Internal function used to get the .dds header from the current file.
 
100
ILboolean iGetDdsHead(DDSHEAD *Header)
 
101
{
 
102
        if (iread(Header, sizeof(DDSHEAD), 1) != 1)
 
103
                return IL_FALSE;
 
104
 
 
105
        Int(&Header->Size1);
 
106
        Int(&Header->Flags1);
 
107
        Int(&Header->Height);
 
108
        Int(&Header->Width);
 
109
        Int(&Header->LinearSize);
 
110
        Int(&Header->Depth);
 
111
        Int(&Header->MipMapCount);
 
112
        Int(&Header->AlphaBitDepth);
 
113
        Int(&Header->Size2);
 
114
        Int(&Header->Flags2);
 
115
        Int(&Header->FourCC);
 
116
        Int(&Header->RGBBitCount);
 
117
        Int(&Header->RBitMask);
 
118
        Int(&Header->GBitMask);
 
119
        Int(&Header->BBitMask);
 
120
        Int(&Header->RGBAlphaBitMask);
 
121
        Int(&Header->ddsCaps1);
 
122
        Int(&Header->ddsCaps2);
 
123
        Int(&Header->ddsCaps3);
 
124
        Int(&Header->ddsCaps4);
 
125
        Int(&Header->TextureStage);
 
126
 
 
127
        if (Head.Depth == 0)
 
128
                Head.Depth = 1;
 
129
 
 
130
        return IL_TRUE;
 
131
}
 
132
 
 
133
 
 
134
// Internal function to get the header and check it.
 
135
ILboolean iIsValidDds()
 
136
{
 
137
        ILboolean       IsValid;
 
138
        DDSHEAD         Head;
 
139
 
 
140
        iGetDdsHead(&Head);
 
141
        iseek(-(ILint)sizeof(DDSHEAD), IL_SEEK_CUR);  // Go ahead and restore to previous state
 
142
 
 
143
        IsValid = iCheckDds(&Head);
 
144
 
 
145
        return IsValid;
 
146
}
 
147
 
 
148
 
 
149
// Internal function used to check if the HEADER is a valid .dds header.
 
150
ILboolean iCheckDds(DDSHEAD *Head)
 
151
{
 
152
        if (strnicmp(Head->Signature, "DDS ", 4))
 
153
                return IL_FALSE;
 
154
        if (Head->Size1 != 124)
 
155
                return IL_FALSE;
 
156
        if (Head->Size2 != 32)
 
157
                return IL_FALSE;
 
158
        if (Head->Width == 0 || Head->Height == 0)
 
159
                return IL_FALSE;
 
160
        return IL_TRUE;
 
161
}
 
162
 
 
163
 
 
164
//! Reads a .dds file
 
165
ILboolean ilLoadDds(const ILstring FileName)
 
166
{
 
167
        ILHANDLE        DdsFile;
 
168
        ILboolean       bDds = IL_FALSE;
 
169
 
 
170
        DdsFile = iopenr(FileName);
 
171
        if (DdsFile == NULL) {
 
172
                ilSetError(IL_COULD_NOT_OPEN_FILE);
 
173
                return bDds;
 
174
        }
 
175
 
 
176
        bDds = ilLoadDdsF(DdsFile);
 
177
        icloser(DdsFile);
 
178
 
 
179
        return bDds;
 
180
}
 
181
 
 
182
 
 
183
//! Reads an already-opened .dds file
 
184
ILboolean ilLoadDdsF(ILHANDLE File)
 
185
{
 
186
        ILuint          FirstPos;
 
187
        ILboolean       bRet;
 
188
 
 
189
        iSetInputFile(File);
 
190
        FirstPos = itell();
 
191
        bRet = iLoadDdsInternal();
 
192
        iseek(FirstPos, IL_SEEK_SET);
 
193
 
 
194
        return bRet;
 
195
}
 
196
 
 
197
 
 
198
//! Reads from a memory "lump" that contains a .dds
 
199
ILboolean ilLoadDdsL(ILvoid *Lump, ILuint Size)
 
200
{
 
201
        iSetInputLump(Lump, Size);
 
202
        return iLoadDdsInternal();
 
203
}
 
204
 
 
205
 
 
206
ILboolean iLoadDdsCubemapInternal()
 
207
{
 
208
        ILuint  i;
 
209
        ILubyte Bpp;
 
210
        ILimage *startImage;
 
211
 
 
212
        CompData = NULL;
 
213
 
 
214
        if (CompFormat == PF_RGB || CompFormat == PF_3DC)
 
215
                Bpp = 3;
 
216
        else
 
217
                Bpp = 4;
 
218
 
 
219
        startImage = Image;
 
220
        // run through cube map possibilities
 
221
        for (i = 0; i < CUBEMAP_SIDES; i++) {
 
222
                // reset each time
 
223
                Width = Head.Width;
 
224
                Height = Head.Height;
 
225
                Depth = Head.Depth;
 
226
                if (Head.ddsCaps2 & CubemapDirections[i]) {
 
227
                        if (i != 0) {
 
228
                                Image->Next = ilNewImage(Width, Height, Depth, Bpp, 1);
 
229
                                if (Image->Next == NULL)
 
230
                                        return IL_FALSE;
 
231
 
 
232
                                Image = Image->Next;
 
233
                                startImage->NumNext++;
 
234
                                ilBindImage(ilGetCurName());  // Set to parent image first.
 
235
                                ilActiveImage(i);
 
236
                        }
 
237
 
 
238
                        Image->CubeFlags = CubemapDirections[i];
 
239
 
 
240
                        if (!ReadData())
 
241
                                return IL_FALSE;
 
242
 
 
243
                        if (!AllocImage()) {
 
244
                                if (CompData)
 
245
                                        ifree(CompData);
 
246
                                return IL_FALSE;
 
247
                        }
 
248
 
 
249
                        if (!Decompress()) {
 
250
                                if (CompData)
 
251
                                        ifree(CompData);
 
252
                                return IL_FALSE;
 
253
                        }
 
254
 
 
255
                        if (!ReadMipmaps()) {
 
256
                                if (CompData)
 
257
                                        ifree(CompData);
 
258
                                return IL_FALSE;
 
259
                        }
 
260
                }
 
261
        }
 
262
 
 
263
        if (CompData) {
 
264
                ifree(CompData);
 
265
                CompData = NULL;
 
266
        }
 
267
 
 
268
        ilBindImage(ilGetCurName());  // Set to parent image first.
 
269
        return ilFixImage();
 
270
}
 
271
 
 
272
 
 
273
ILboolean iLoadDdsInternal()
 
274
{
 
275
        CompData = NULL;
 
276
 
 
277
        if (iCurImage == NULL) {
 
278
                ilSetError(IL_ILLEGAL_OPERATION);
 
279
                return IL_FALSE;
 
280
        }
 
281
 
 
282
        if (!iGetDdsHead(&Head)) {
 
283
                ilSetError(IL_INVALID_FILE_HEADER);
 
284
                return IL_FALSE;
 
285
        }
 
286
        if(!iCheckDds(&Head)) {
 
287
                ilSetError(IL_INVALID_FILE_HEADER);
 
288
                return IL_FALSE;
 
289
        }
 
290
 
 
291
        DecodePixelFormat();
 
292
        if (CompFormat == PF_UNKNOWN) {
 
293
                ilSetError(IL_INVALID_FILE_HEADER);
 
294
                return IL_FALSE;
 
295
        }
 
296
        /*else if (CompFormat == PF_3DC) {
 
297
                ilSetError(IL_FORMAT_NOT_SUPPORTED);
 
298
                return IL_FALSE;
 
299
        }*/
 
300
        // Microsoft bug, they're not following their own documentation.
 
301
        if (!(Head.Flags1 & (DDS_LINEARSIZE | DDS_PITCH))) {
 
302
                Head.Flags1 |= DDS_LINEARSIZE;
 
303
                Head.LinearSize = BlockSize;
 
304
        }
 
305
 
 
306
        Image = iCurImage;
 
307
        if (Head.ddsCaps1 & DDS_COMPLEX) {
 
308
                if (Head.ddsCaps2 & DDS_CUBEMAP) {
 
309
                        if (!iLoadDdsCubemapInternal())
 
310
                                return IL_FALSE;
 
311
                        return IL_TRUE;
 
312
                }
 
313
        }
 
314
        Width = Head.Width;
 
315
        Height = Head.Height;
 
316
        Depth = Head.Depth;
 
317
 
 
318
        AdjustVolumeTexture(&Head);
 
319
 
 
320
        if (!ReadData())
 
321
                return IL_FALSE;
 
322
        if (!AllocImage()) {
 
323
                if (CompData)
 
324
                        ifree(CompData);
 
325
                return IL_FALSE;
 
326
        }
 
327
        if (!Decompress()) {
 
328
                if (CompData)
 
329
                        ifree(CompData);
 
330
                return IL_FALSE;
 
331
        }
 
332
 
 
333
        if (!ReadMipmaps()) {
 
334
                if (CompData)
 
335
                        ifree(CompData);
 
336
                return IL_FALSE;
 
337
        }
 
338
 
 
339
        if (CompData)
 
340
                ifree(CompData);
 
341
 
 
342
        ilBindImage(ilGetCurName());  // Set to parent image first.
 
343
        return ilFixImage();
 
344
}
 
345
 
 
346
 
 
347
ILvoid DecodePixelFormat()
 
348
{
 
349
        if (Head.Flags2 & DDS_FOURCC) {
 
350
                BlockSize = ((Head.Width + 3)/4) * ((Head.Height + 3)/4) * ((Head.Depth + 3)/4);
 
351
                switch (Head.FourCC)
 
352
                {
 
353
                        case IL_MAKEFOURCC('D','X','T','1'):
 
354
                                CompFormat = PF_DXT1;
 
355
                                BlockSize *= 8;
 
356
                                break;
 
357
 
 
358
                        case IL_MAKEFOURCC('D','X','T','2'):
 
359
                                CompFormat = PF_DXT2;
 
360
                                BlockSize *= 16;
 
361
                                break;
 
362
 
 
363
                        case IL_MAKEFOURCC('D','X','T','3'):
 
364
                                CompFormat = PF_DXT3;
 
365
                                BlockSize *= 16;
 
366
                                break;
 
367
 
 
368
                        case IL_MAKEFOURCC('D','X','T','4'):
 
369
                                CompFormat = PF_DXT4;
 
370
                                BlockSize *= 16;
 
371
                                break;
 
372
 
 
373
                        case IL_MAKEFOURCC('D','X','T','5'):
 
374
                                CompFormat = PF_DXT5;
 
375
                                BlockSize *= 16;
 
376
                                break;
 
377
 
 
378
                        case IL_MAKEFOURCC('A', 'T', 'I', '2'):
 
379
                                CompFormat = PF_3DC;
 
380
                                BlockSize *= 16;
 
381
                                break;
 
382
 
 
383
                        default:
 
384
                                CompFormat = PF_UNKNOWN;
 
385
                                BlockSize *= 16;
 
386
                                break;
 
387
                }
 
388
        } else {
 
389
        // This dds texture isn't compressed so write out ARGB format
 
390
                if (Head.Flags2 & DDS_ALPHAPIXELS) {
 
391
                        CompFormat = PF_ARGB;
 
392
                } else {
 
393
                        CompFormat = PF_RGB;
 
394
                }
 
395
                BlockSize = (Head.Width * Head.Height * Head.Depth * (Head.RGBBitCount >> 3));
 
396
        }
 
397
        return;
 
398
}
 
399
 
 
400
 
 
401
// The few volume textures that I have don't have consistent LinearSize
 
402
//      entries, even thouh the DDS_LINEARSIZE flag is set.
 
403
ILvoid AdjustVolumeTexture(DDSHEAD *Head)
 
404
{
 
405
        if (Head->Depth <= 1)
 
406
                return;
 
407
 
 
408
        // All volume textures I've seem so far didn't have the DDS_COMPLEX flag set,
 
409
        // even though this is normally required. But because noone does set it,
 
410
        // also read images without it (TODO: check file size for 3d texture?)
 
411
        if (/*!(Head->ddsCaps1 & DDS_COMPLEX) ||*/ !(Head->ddsCaps2 & DDS_VOLUME)) {
 
412
                Head->Depth = 1;
 
413
                Depth = 1;
 
414
        }
 
415
 
 
416
        switch (CompFormat)
 
417
        {
 
418
                case PF_ARGB:
 
419
                case PF_RGB:
 
420
                        Head->LinearSize = IL_MAX(1,Head->Width) * IL_MAX(1,Head->Height) *
 
421
                                (Head->RGBBitCount / 8);
 
422
                        break;
 
423
        
 
424
                case PF_DXT1:
 
425
                        Head->LinearSize = IL_MAX(1,Head->Width/4) * IL_MAX(1,Head->Height/4) * 8;
 
426
                        break;
 
427
 
 
428
                case PF_DXT2:
 
429
                case PF_DXT3:
 
430
                case PF_DXT4:
 
431
                case PF_DXT5:
 
432
                case PF_3DC:
 
433
                        Head->LinearSize = IL_MAX(1,Head->Width/4) * IL_MAX(1,Head->Height/4) * 16;
 
434
                        break;
 
435
        }
 
436
 
 
437
        Head->Flags1 |= DDS_LINEARSIZE;
 
438
        Head->LinearSize *= Head->Depth;
 
439
 
 
440
        return;
 
441
}
 
442
 
 
443
 
 
444
// Reads the compressed data
 
445
ILboolean ReadData()
 
446
{
 
447
        ILuint  Bps;
 
448
        ILint   y, z;
 
449
        ILubyte *Temp;
 
450
        ILuint  Bpp;
 
451
 
 
452
        if (CompFormat == PF_RGB || CompFormat == PF_3DC)
 
453
                Bpp = 3;
 
454
        else
 
455
                Bpp = 4;
 
456
 
 
457
        if (CompData) {
 
458
                ifree(CompData);
 
459
                CompData = NULL;
 
460
        }
 
461
 
 
462
        if (Head.Flags1 & DDS_LINEARSIZE) {
 
463
                //Head.LinearSize = Head.LinearSize * Depth;
 
464
 
 
465
                CompData = (ILubyte*)ialloc(Head.LinearSize);
 
466
                if (CompData == NULL) {
 
467
                        return IL_FALSE;
 
468
                }
 
469
 
 
470
                if (iread(CompData, 1, Head.LinearSize) != (ILuint)Head.LinearSize) {
 
471
                        ifree(CompData);
 
472
                        return IL_FALSE;
 
473
                }
 
474
        }
 
475
        else {
 
476
                Bps = Width * Head.RGBBitCount / 8;
 
477
                CompSize = Bps * Height * Depth;
 
478
                CompLineSize = Bps;
 
479
 
 
480
                CompData = (ILubyte*)ialloc(CompSize);
 
481
                if (CompData == NULL) {
 
482
                        return IL_FALSE;
 
483
                }
 
484
 
 
485
                Temp = CompData;
 
486
                for (z = 0; z < Depth; z++) {
 
487
                        for (y = 0; y < Height; y++) {
 
488
                                if (iread(Temp, 1, Bps) != Bps) {
 
489
                                        ifree(CompData);
 
490
                                        return IL_FALSE;
 
491
                                }
 
492
                                Temp += Bps;
 
493
                        }
 
494
                }
 
495
        }
 
496
 
 
497
        return IL_TRUE;
 
498
}
 
499
 
 
500
 
 
501
ILboolean AllocImage()
 
502
{
 
503
        switch (CompFormat)
 
504
        {
 
505
                case PF_RGB:
 
506
                        if (!ilTexImage(Width, Height, Depth, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL))
 
507
                                return IL_FALSE;
 
508
                        break;
 
509
                case PF_ARGB:
 
510
                        if (!ilTexImage(Width, Height, Depth, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL))
 
511
                                return IL_FALSE;
 
512
                        break;
 
513
                case PF_3DC:
 
514
                        //right now there's no OpenGL api to use the compressed 3dc data, so
 
515
                        //throw it away (I don't know how DirectX works, though)?
 
516
                        if (!ilTexImage(Width, Height, Depth, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL))
 
517
                                return IL_FALSE;
 
518
                        break;
 
519
                default:
 
520
                        if (!ilTexImage(Width, Height, Depth, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL))
 
521
                                return IL_FALSE;
 
522
                        if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) {
 
523
                                iCurImage->DxtcData = (ILubyte*)ialloc(Head.LinearSize);
 
524
                                if (iCurImage->DxtcData == NULL)
 
525
                                        return IL_FALSE;
 
526
                                iCurImage->DxtcFormat = CompFormat - PF_DXT1 + IL_DXT1;
 
527
                                iCurImage->DxtcSize = Head.LinearSize;
 
528
                                memcpy(iCurImage->DxtcData, CompData, iCurImage->DxtcSize);
 
529
                        }
 
530
                        break;
 
531
        }
 
532
 
 
533
        Image->Origin = IL_ORIGIN_UPPER_LEFT;
 
534
        
 
535
        return IL_TRUE;
 
536
}
 
537
 
 
538
 
 
539
ILboolean Decompress()
 
540
{
 
541
        switch (CompFormat)
 
542
        {
 
543
                case PF_ARGB:
 
544
                case PF_RGB:
 
545
                        return DecompressARGB();
 
546
 
 
547
                case PF_DXT1:
 
548
                        return DecompressDXT1();
 
549
 
 
550
                case PF_DXT2:
 
551
                        return DecompressDXT2();
 
552
 
 
553
                case PF_DXT3:
 
554
                        return DecompressDXT3();
 
555
 
 
556
                case PF_DXT4:
 
557
                        return DecompressDXT4();
 
558
 
 
559
                case PF_DXT5:
 
560
                        return DecompressDXT5();
 
561
 
 
562
                case PF_3DC:
 
563
                        return Decompress3Dc();
 
564
 
 
565
                case PF_UNKNOWN:
 
566
                        return IL_FALSE;
 
567
        }
 
568
 
 
569
        return IL_FALSE;
 
570
}
 
571
 
 
572
 
 
573
ILboolean ReadMipmaps()
 
574
{
 
575
        ILuint  i, CompFactor=0;
 
576
        ILubyte Bpp;
 
577
        ILimage *StartImage, *TempImage;
 
578
        ILuint  LastLinear;
 
579
        ILuint  minW, minH;
 
580
 
 
581
        if (CompFormat == PF_RGB || CompFormat == PF_3DC)
 
582
                Bpp = 3;
 
583
        else
 
584
                Bpp = 4;
 
585
 
 
586
        if (Head.Flags1 & DDS_LINEARSIZE) {
 
587
                CompFactor = (Width * Height * Depth * Bpp) / Head.LinearSize;
 
588
        }
 
589
 
 
590
        StartImage = Image;
 
591
 
 
592
        if (!(Head.Flags1 & DDS_MIPMAPCOUNT) || Head.MipMapCount == 0) {
 
593
                //some .dds-files have their mipmap flag set,
 
594
                //but a mipmapcount of 0. Because mipMapCount is an uint, 0 - 1 gives
 
595
                //overflow - don't let this happen:
 
596
                Head.MipMapCount = 1;
 
597
        }
 
598
 
 
599
        LastLinear = Head.LinearSize;
 
600
        for (i = 0; i < Head.MipMapCount - 1; i++) {
 
601
                Depth = Depth / 2;
 
602
                Width = Width / 2;
 
603
                Height = Height / 2;
 
604
 
 
605
                if (Depth == 0) 
 
606
                        Depth = 1;
 
607
                if (Width == 0) 
 
608
                        Width = 1;
 
609
                if (Height == 0) 
 
610
                        Height = 1;
 
611
 
 
612
                //TODO: mipmaps don't keep DXT data???
 
613
                Image->Next = ilNewImage(Width, Height, Depth, Bpp, 1);
 
614
                if (Image->Next == NULL)
 
615
                        goto mip_fail;
 
616
                Image = Image->Next;
 
617
                Image->Origin = IL_ORIGIN_UPPER_LEFT;
 
618
 
 
619
                if (Head.Flags1 & DDS_LINEARSIZE) {
 
620
                        minW = Width;
 
621
                        minH = Height;
 
622
                        if ((CompFormat != PF_RGB) && (CompFormat != PF_ARGB)) {
 
623
                                minW = IL_MAX(4, Width);
 
624
                                minH = IL_MAX(4, Height);
 
625
                                Head.LinearSize = (minW * minH * Depth * Bpp) / CompFactor;
 
626
                        }
 
627
                        else {
 
628
                                Head.LinearSize = Width * Height * Depth * (Head.RGBBitCount >> 3);
 
629
                        }
 
630
                }
 
631
                else {
 
632
                        Head.LinearSize >>= 1;
 
633
                }
 
634
 
 
635
                if (!ReadData())
 
636
                        goto mip_fail;
 
637
                if (!Decompress())
 
638
                        goto mip_fail;
 
639
        }
 
640
 
 
641
        Head.LinearSize = LastLinear;
 
642
        StartImage->Mipmaps = StartImage->Next;
 
643
        StartImage->Next = NULL;
 
644
        StartImage->NumMips = Head.MipMapCount - 1;
 
645
        Image = StartImage;
 
646
 
 
647
        return IL_TRUE;
 
648
 
 
649
mip_fail:
 
650
        Image = StartImage;
 
651
        StartImage = StartImage->Next;
 
652
        while (StartImage) {
 
653
                TempImage = StartImage;
 
654
                StartImage = StartImage->Next;
 
655
                ifree(TempImage);
 
656
        }
 
657
        return IL_FALSE;
 
658
}
 
659
 
 
660
 
 
661
ILboolean DecompressDXT1()
 
662
{
 
663
        int                     x, y, z, i, j, k, Select;
 
664
        ILubyte         *Temp;
 
665
        Color565        *color_0, *color_1;
 
666
        Color8888       colours[4], *col;
 
667
        ILuint          bitmask, Offset;
 
668
 
 
669
 
 
670
        Temp = CompData;
 
671
        for (z = 0; z < Depth; z++) {
 
672
                for (y = 0; y < Height; y += 4) {
 
673
                        for (x = 0; x < Width; x += 4) {
 
674
 
 
675
                                color_0 = ((Color565*)Temp);
 
676
                                color_1 = ((Color565*)(Temp+2));
 
677
                                bitmask = ((ILuint*)Temp)[1];
 
678
                                Temp += 8;
 
679
 
 
680
                                colours[0].r = color_0->nRed << 3;
 
681
                                colours[0].g = color_0->nGreen << 2;
 
682
                                colours[0].b = color_0->nBlue << 3;
 
683
                                colours[0].a = 0xFF;
 
684
 
 
685
                                colours[1].r = color_1->nRed << 3;
 
686
                                colours[1].g = color_1->nGreen << 2;
 
687
                                colours[1].b = color_1->nBlue << 3;
 
688
                                colours[1].a = 0xFF;
 
689
 
 
690
 
 
691
                                if (*((ILushort*)color_0) > *((ILushort*)color_1)) {
 
692
                                        // Four-color block: derive the other two colors.
 
693
                                        // 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3
 
694
                                        // These 2-bit codes correspond to the 2-bit fields 
 
695
                                        // stored in the 64-bit block.
 
696
                                        colours[2].b = (2 * colours[0].b + colours[1].b + 1) / 3;
 
697
                                        colours[2].g = (2 * colours[0].g + colours[1].g + 1) / 3;
 
698
                                        colours[2].r = (2 * colours[0].r + colours[1].r + 1) / 3;
 
699
                                        colours[2].a = 0xFF;
 
700
 
 
701
                                        colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3;
 
702
                                        colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3;
 
703
                                        colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3;
 
704
                                        colours[3].a = 0xFF;
 
705
                                }
 
706
                                else { 
 
707
                                        // Three-color block: derive the other color.
 
708
                                        // 00 = color_0,  01 = color_1,  10 = color_2,
 
709
                                        // 11 = transparent.
 
710
                                        // These 2-bit codes correspond to the 2-bit fields 
 
711
                                        // stored in the 64-bit block. 
 
712
                                        colours[2].b = (colours[0].b + colours[1].b) / 2;
 
713
                                        colours[2].g = (colours[0].g + colours[1].g) / 2;
 
714
                                        colours[2].r = (colours[0].r + colours[1].r) / 2;
 
715
                                        colours[2].a = 0xFF;
 
716
 
 
717
                                        colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3;
 
718
                                        colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3;
 
719
                                        colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3;
 
720
                                        colours[3].a = 0x00;
 
721
                                }
 
722
 
 
723
                                for (j = 0, k = 0; j < 4; j++) {
 
724
                                        for (i = 0; i < 4; i++, k++) {
 
725
 
 
726
                                                Select = (bitmask & (0x03 << k*2)) >> k*2;
 
727
                                                col = &colours[Select];
 
728
 
 
729
                                                if (((x + i) < Width) && ((y + j) < Height)) {
 
730
                                                        Offset = z * Image->SizeOfPlane + (y + j) * Image->Bps + (x + i) * Image->Bpp;
 
731
                                                        Image->Data[Offset + 0] = col->r;
 
732
                                                        Image->Data[Offset + 1] = col->g;
 
733
                                                        Image->Data[Offset + 2] = col->b;
 
734
                                                        Image->Data[Offset + 3] = col->a;
 
735
                                                }
 
736
                                        }
 
737
                                }
 
738
                        }
 
739
                }
 
740
        }
 
741
 
 
742
        return IL_TRUE;
 
743
}
 
744
 
 
745
 
 
746
ILboolean DecompressDXT2()
 
747
{
 
748
        // Can do color & alpha same as dxt3, but color is pre-multiplied 
 
749
        //   so the result will be wrong unless corrected. 
 
750
        if (!DecompressDXT3())
 
751
                return IL_FALSE;
 
752
        CorrectPreMult();
 
753
 
 
754
        return IL_TRUE;
 
755
}
 
756
 
 
757
 
 
758
ILboolean DecompressDXT3()
 
759
{
 
760
        int                     x, y, z, i, j, k, Select;
 
761
        ILubyte         *Temp;
 
762
        Color565        *color_0, *color_1;
 
763
        Color8888       colours[4], *col;
 
764
        ILuint          bitmask, Offset;
 
765
        ILushort        word;
 
766
        DXTAlphaBlockExplicit *alpha;
 
767
 
 
768
 
 
769
        Temp = CompData;
 
770
        for (z = 0; z < Depth; z++) {
 
771
                for (y = 0; y < Height; y += 4) {
 
772
                        for (x = 0; x < Width; x += 4) {
 
773
                                alpha = (DXTAlphaBlockExplicit*)Temp;
 
774
                                Temp += 8;
 
775
                                color_0 = ((Color565*)Temp);
 
776
                                color_1 = ((Color565*)(Temp+2));
 
777
                                bitmask = ((ILuint*)Temp)[1];
 
778
                                Temp += 8;
 
779
 
 
780
                                colours[0].r = color_0->nRed << 3;
 
781
                                colours[0].g = color_0->nGreen << 2;
 
782
                                colours[0].b = color_0->nBlue << 3;
 
783
                                colours[0].a = 0xFF;
 
784
 
 
785
                                colours[1].r = color_1->nRed << 3;
 
786
                                colours[1].g = color_1->nGreen << 2;
 
787
                                colours[1].b = color_1->nBlue << 3;
 
788
                                colours[1].a = 0xFF;
 
789
 
 
790
                                // Four-color block: derive the other two colors.    
 
791
                                // 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3
 
792
                                // These 2-bit codes correspond to the 2-bit fields 
 
793
                                // stored in the 64-bit block.
 
794
                                colours[2].b = (2 * colours[0].b + colours[1].b + 1) / 3;
 
795
                                colours[2].g = (2 * colours[0].g + colours[1].g + 1) / 3;
 
796
                                colours[2].r = (2 * colours[0].r + colours[1].r + 1) / 3;
 
797
                                colours[2].a = 0xFF;
 
798
 
 
799
                                colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3;
 
800
                                colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3;
 
801
                                colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3;
 
802
                                colours[3].a = 0xFF;
 
803
 
 
804
                                k = 0;
 
805
                                for (j = 0; j < 4; j++) {
 
806
                                        for (i = 0; i < 4; i++, k++) {
 
807
 
 
808
                                                Select = (bitmask & (0x03 << k*2)) >> k*2;
 
809
                                                col = &colours[Select];
 
810
 
 
811
                                                if (((x + i) < Width) && ((y + j) < Height)) {
 
812
                                                        Offset = z * Image->SizeOfPlane + (y + j) * Image->Bps + (x + i) * Image->Bpp;
 
813
                                                        Image->Data[Offset + 0] = col->r;
 
814
                                                        Image->Data[Offset + 1] = col->g;
 
815
                                                        Image->Data[Offset + 2] = col->b;
 
816
                                                }
 
817
                                        }
 
818
                                }
 
819
 
 
820
                                for (j = 0; j < 4; j++) {
 
821
                                        word = alpha->row[j];
 
822
                                        for (i = 0; i < 4; i++) {
 
823
                                                if (((x + i) < Width) && ((y + j) < Height)) {
 
824
                                                        Offset = z * Image->SizeOfPlane + (y + j) * Image->Bps + (x + i) * Image->Bpp + 3;
 
825
                                                        Image->Data[Offset] = word & 0x0F;
 
826
                                                        Image->Data[Offset] = Image->Data[Offset] | (Image->Data[Offset] << 4);
 
827
                                                }
 
828
                                                word >>= 4;
 
829
                                        }
 
830
                                }
 
831
 
 
832
                        }
 
833
                }
 
834
        }
 
835
 
 
836
        return IL_TRUE;
 
837
}
 
838
 
 
839
 
 
840
ILboolean DecompressDXT4()
 
841
{
 
842
        // Can do color & alpha same as dxt5, but color is pre-multiplied 
 
843
        //   so the result will be wrong unless corrected. 
 
844
        if (!DecompressDXT5())
 
845
                return IL_FALSE;
 
846
        CorrectPreMult();
 
847
 
 
848
        return IL_FALSE;
 
849
}
 
850
 
 
851
 
 
852
ILboolean DecompressDXT5()
 
853
{
 
854
        int                     x, y, z, i, j, k, Select;
 
855
        ILubyte         *Temp;
 
856
        Color565        *color_0, *color_1;
 
857
        Color8888       colours[4], *col;
 
858
        ILuint          bitmask, Offset;
 
859
        ILubyte         alphas[8], *alphamask;
 
860
        ILuint          bits;
 
861
 
 
862
        Temp = CompData;
 
863
        for (z = 0; z < Depth; z++) {
 
864
                for (y = 0; y < Height; y += 4) {
 
865
                        for (x = 0; x < Width; x += 4) {
 
866
                                if (y >= Height || x >= Width)
 
867
                                        break;
 
868
                                alphas[0] = Temp[0];
 
869
                                alphas[1] = Temp[1];
 
870
                                alphamask = Temp + 2;
 
871
                                Temp += 8;
 
872
                                color_0 = ((Color565*)Temp);
 
873
                                color_1 = ((Color565*)(Temp+2));
 
874
                                bitmask = ((ILuint*)Temp)[1];
 
875
                                Temp += 8;
 
876
 
 
877
                                colours[0].r = color_0->nRed << 3;
 
878
                                colours[0].g = color_0->nGreen << 2;
 
879
                                colours[0].b = color_0->nBlue << 3;
 
880
                                colours[0].a = 0xFF;
 
881
 
 
882
                                colours[1].r = color_1->nRed << 3;
 
883
                                colours[1].g = color_1->nGreen << 2;
 
884
                                colours[1].b = color_1->nBlue << 3;
 
885
                                colours[1].a = 0xFF;
 
886
 
 
887
                                // Four-color block: derive the other two colors.    
 
888
                                // 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3
 
889
                                // These 2-bit codes correspond to the 2-bit fields 
 
890
                                // stored in the 64-bit block.
 
891
                                colours[2].b = (2 * colours[0].b + colours[1].b + 1) / 3;
 
892
                                colours[2].g = (2 * colours[0].g + colours[1].g + 1) / 3;
 
893
                                colours[2].r = (2 * colours[0].r + colours[1].r + 1) / 3;
 
894
                                colours[2].a = 0xFF;
 
895
 
 
896
                                colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3;
 
897
                                colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3;
 
898
                                colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3;
 
899
                                colours[3].a = 0xFF;
 
900
 
 
901
                                k = 0;
 
902
                                for (j = 0; j < 4; j++) {
 
903
                                        for (i = 0; i < 4; i++, k++) {
 
904
 
 
905
                                                Select = (bitmask & (0x03 << k*2)) >> k*2;
 
906
                                                col = &colours[Select];
 
907
 
 
908
                                                // only put pixels out < width or height
 
909
                                                if (((x + i) < Width) && ((y + j) < Height)) {
 
910
                                                        Offset = z * Image->SizeOfPlane + (y + j) * Image->Bps + (x + i) * Image->Bpp;
 
911
                                                        Image->Data[Offset + 0] = col->r;
 
912
                                                        Image->Data[Offset + 1] = col->g;
 
913
                                                        Image->Data[Offset + 2] = col->b;
 
914
                                                }
 
915
                                        }
 
916
                                }
 
917
 
 
918
                                // 8-alpha or 6-alpha block?    
 
919
                                if (alphas[0] > alphas[1]) {    
 
920
                                        // 8-alpha block:  derive the other six alphas.    
 
921
                                        // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
 
922
                                        alphas[2] = (6 * alphas[0] + 1 * alphas[1] + 3) / 7;    // bit code 010
 
923
                                        alphas[3] = (5 * alphas[0] + 2 * alphas[1] + 3) / 7;    // bit code 011
 
924
                                        alphas[4] = (4 * alphas[0] + 3 * alphas[1] + 3) / 7;    // bit code 100
 
925
                                        alphas[5] = (3 * alphas[0] + 4 * alphas[1] + 3) / 7;    // bit code 101
 
926
                                        alphas[6] = (2 * alphas[0] + 5 * alphas[1] + 3) / 7;    // bit code 110
 
927
                                        alphas[7] = (1 * alphas[0] + 6 * alphas[1] + 3) / 7;    // bit code 111
 
928
                                }
 
929
                                else {
 
930
                                        // 6-alpha block.
 
931
                                        // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
 
932
                                        alphas[2] = (4 * alphas[0] + 1 * alphas[1] + 2) / 5;    // Bit code 010
 
933
                                        alphas[3] = (3 * alphas[0] + 2 * alphas[1] + 2) / 5;    // Bit code 011
 
934
                                        alphas[4] = (2 * alphas[0] + 3 * alphas[1] + 2) / 5;    // Bit code 100
 
935
                                        alphas[5] = (1 * alphas[0] + 4 * alphas[1] + 2) / 5;    // Bit code 101
 
936
                                        alphas[6] = 0x00;                                                                               // Bit code 110
 
937
                                        alphas[7] = 0xFF;                                                                               // Bit code 111
 
938
                                }
 
939
 
 
940
                                // Note: Have to separate the next two loops,
 
941
                                //      it operates on a 6-byte system.
 
942
 
 
943
                                // First three bytes
 
944
                                bits = *((ILint*)alphamask);
 
945
                                for (j = 0; j < 2; j++) {
 
946
                                        for (i = 0; i < 4; i++) {
 
947
                                                // only put pixels out < width or height
 
948
                                                if (((x + i) < Width) && ((y + j) < Height)) {
 
949
                                                        Offset = z * Image->SizeOfPlane + (y + j) * Image->Bps + (x + i) * Image->Bpp + 3;
 
950
                                                        Image->Data[Offset] = alphas[bits & 0x07];
 
951
                                                }
 
952
                                                bits >>= 3;
 
953
                                        }
 
954
                                }
 
955
 
 
956
                                // Last three bytes
 
957
                                bits = *((ILint*)&alphamask[3]);
 
958
                                for (j = 2; j < 4; j++) {
 
959
                                        for (i = 0; i < 4; i++) {
 
960
                                                // only put pixels out < width or height
 
961
                                                if (((x + i) < Width) && ((y + j) < Height)) {
 
962
                                                        Offset = z * Image->SizeOfPlane + (y + j) * Image->Bps + (x + i) * Image->Bpp + 3;
 
963
                                                        Image->Data[Offset] = alphas[bits & 0x07];
 
964
                                                }
 
965
                                                bits >>= 3;
 
966
                                        }
 
967
                                }
 
968
                        }
 
969
                }
 
970
        }
 
971
 
 
972
        return IL_TRUE;
 
973
}
 
974
 
 
975
ILboolean       Decompress3Dc()
 
976
{
 
977
        int                     x, y, z, i, j, k, t1, t2;
 
978
        ILubyte         *Temp, *Temp2;
 
979
        ILubyte         XColours[8], YColours[8];
 
980
        ILuint          bitmask, bitmask2, Offset, CurrOffset;
 
981
 
 
982
 
 
983
        Temp = CompData;
 
984
        Offset = 0;
 
985
        for (z = 0; z < Depth; z++) {
 
986
                for (y = 0; y < Height; y += 4) {
 
987
                        for (x = 0; x < Width; x += 4) {
 
988
                                Temp2 = Temp + 8;
 
989
 
 
990
                                //Read Y palette
 
991
                                t1 = YColours[0] = Temp[0];
 
992
                                t2 = YColours[1] = Temp[1];
 
993
                                Temp += 2;
 
994
                                if (t1 > t2)
 
995
                                        for (i = 2; i < 8; ++i)
 
996
                                                YColours[i] = t1 + ((t2 - t1)*(i - 1))/7;
 
997
                                else {
 
998
                                        for (i = 2; i < 6; ++i)
 
999
                                                YColours[i] = t1 + ((t2 - t1)*(i - 1))/5;
 
1000
                                        YColours[6] = 0;
 
1001
                                        YColours[7] = 255;
 
1002
                                }
 
1003
 
 
1004
                                // Read X palette
 
1005
                                t1 = XColours[0] = Temp2[0];
 
1006
                                t2 = XColours[1] = Temp2[1];
 
1007
                                Temp2 += 2;
 
1008
                                if (t1 > t2)
 
1009
                                        for (i = 2; i < 8; ++i)
 
1010
                                                XColours[i] = t1 + ((t2 - t1)*(i - 1))/7;
 
1011
                                else {
 
1012
                                        for (i = 2; i < 6; ++i)
 
1013
                                                XColours[i] = t1 + ((t2 - t1)*(i - 1))/5;
 
1014
                                        XColours[6] = 0;
 
1015
                                        XColours[7] = 255;
 
1016
                                }
 
1017
 
 
1018
                                //decompress pixel data
 
1019
                                CurrOffset = Offset;
 
1020
                                for (k = 0; k < 4; k += 2) {
 
1021
                                        // First three bytes
 
1022
                                        bitmask = ((ILuint)(Temp[0]) << 0) | ((ILuint)(Temp[1]) << 8) | ((ILuint)(Temp[2]) << 16);
 
1023
                                        bitmask2 = ((ILuint)(Temp2[0]) << 0) | ((ILuint)(Temp2[1]) << 8) | ((ILuint)(Temp2[2]) << 16);
 
1024
                                        for (j = 0; j < 2; j++) {
 
1025
                                                // only put pixels out < height
 
1026
                                                if ((y + k + j) < Height) {
 
1027
                                                        for (i = 0; i < 4; i++) {
 
1028
                                                                // only put pixels out < width
 
1029
                                                                if (((x + i) < Width)) {
 
1030
                                                                        ILint t, tx, ty;
 
1031
 
 
1032
                                                                        t1 = CurrOffset + (x + i)*3;
 
1033
                                                                        Image->Data[t1 + 1] = ty = YColours[bitmask & 0x07];
 
1034
                                                                        Image->Data[t1 + 0] = tx = XColours[bitmask2 & 0x07];
 
1035
 
 
1036
                                                                        //calculate b (z) component ((r/255)^2 + (g/255)^2 + (b/255)^2 = 1
 
1037
                                                                        t = 127*128 - (tx - 127)*(tx - 128) - (ty - 127)*(ty - 128);
 
1038
                                                                        if (t > 0)
 
1039
                                                                                Image->Data[t1 + 2] = (ILubyte)(iSqrt(t) + 128);
 
1040
                                                                        else
 
1041
                                                                                Image->Data[t1 + 2] = 0x7F;
 
1042
                                                                }
 
1043
                                                                bitmask >>= 3;
 
1044
                                                                bitmask2 >>= 3;
 
1045
                                                        }
 
1046
                                                        CurrOffset += Image->Bps;
 
1047
                                                }
 
1048
                                        }
 
1049
                                        Temp += 3;
 
1050
                                        Temp2 += 3;
 
1051
                                }
 
1052
 
 
1053
                                //skip bytes that were read via Temp2
 
1054
                                Temp += 8;
 
1055
                        }
 
1056
                        Offset += Image->Bps*4;
 
1057
                }
 
1058
        }
 
1059
 
 
1060
        return IL_TRUE;
 
1061
}
 
1062
 
 
1063
ILvoid CorrectPreMult()
 
1064
{
 
1065
        ILuint i;
 
1066
 
 
1067
        for (i = 0; i < Image->SizeOfData; i += 4) {
 
1068
                if (Image->Data[i+3] != 0) {  // Cannot divide by 0.
 
1069
                        Image->Data[i]   = (ILubyte)(((ILuint)Image->Data[i]   << 8) / Image->Data[i+3]);
 
1070
                        Image->Data[i+1] = (ILubyte)(((ILuint)Image->Data[i+1] << 8) / Image->Data[i+3]);
 
1071
                        Image->Data[i+2] = (ILubyte)(((ILuint)Image->Data[i+2] << 8) / Image->Data[i+3]);
 
1072
                }
 
1073
        }
 
1074
 
 
1075
        return;
 
1076
}
 
1077
 
 
1078
 
 
1079
ILboolean DecompressARGB()
 
1080
{
 
1081
        ILuint  i, ReadI, RedL, RedR, GreenL, GreenR, BlueL, BlueR, AlphaL, AlphaR;
 
1082
        ILubyte *Temp;
 
1083
 
 
1084
        GetBitsFromMask(Head.RBitMask, &RedL, &RedR);
 
1085
        GetBitsFromMask(Head.GBitMask, &GreenL, &GreenR);
 
1086
        GetBitsFromMask(Head.BBitMask, &BlueL, &BlueR);
 
1087
        GetBitsFromMask(Head.RGBAlphaBitMask, &AlphaL, &AlphaR);
 
1088
        Temp = CompData;
 
1089
 
 
1090
        for (i = 0; i < Image->SizeOfData; i += Image->Bpp) {
 
1091
                ReadI = *((ILuint*)Temp);
 
1092
                Temp += (Head.RGBBitCount / 8);
 
1093
 
 
1094
                Image->Data[i]   = ((ReadI & Head.RBitMask) >> RedR) << RedL;
 
1095
                Image->Data[i+1] = ((ReadI & Head.GBitMask) >> GreenR) << GreenL;
 
1096
                Image->Data[i+2] = ((ReadI & Head.BBitMask) >> BlueR) << BlueL;
 
1097
 
 
1098
                if (Image->Bpp == 4) {
 
1099
                        Image->Data[i+3] = ((ReadI & Head.RGBAlphaBitMask) >> AlphaR) << AlphaL;
 
1100
                        if (AlphaL >= 7) {
 
1101
                                Image->Data[i+3] = Image->Data[i+3] ? 0xFF : 0x00;
 
1102
                        }
 
1103
                        else if (AlphaL >= 4) {
 
1104
                                Image->Data[i+3] = Image->Data[i+3] | (Image->Data[i+3] >> 4);
 
1105
                        }
 
1106
                }
 
1107
        }
 
1108
 
 
1109
        return IL_TRUE;
 
1110
}
 
1111
 
 
1112
 
 
1113
// @TODO:  Look at using the BSF/BSR operands for inline ASM here.
 
1114
ILvoid GetBitsFromMask(ILuint Mask, ILuint *ShiftLeft, ILuint *ShiftRight)
 
1115
{
 
1116
        ILuint Temp, i;
 
1117
 
 
1118
        if (Mask == 0) {
 
1119
                *ShiftLeft = *ShiftRight = 0;
 
1120
                return;
 
1121
        }
 
1122
 
 
1123
        Temp = Mask;
 
1124
        for (i = 0; i < 32; i++, Temp >>= 1) {
 
1125
                if (Temp & 1)
 
1126
                        break;
 
1127
        }
 
1128
        *ShiftRight = i;
 
1129
 
 
1130
        // Temp is preserved, so use it again:
 
1131
        for (i = 0; i < 8; i++, Temp >>= 1) {
 
1132
                if (!(Temp & 1))
 
1133
                        break;
 
1134
        }
 
1135
        *ShiftLeft = 8 - i;
 
1136
 
 
1137
        return;
 
1138
}
 
1139
 
 
1140
 
 
1141
#endif//IL_NO_DDS