/** * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Contributors: Amorilia (amorilia@gamebox.net) * * ***** END GPL LICENSE BLOCK ***** */ /* * This file is based on a similar file from the NVIDIA texture tools * (http://nvidia-texture-tools.googlecode.com/) * * Original license from NVIDIA follows. */ // Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. #include #include #include #include // printf #include // sqrt /*** declarations ***/ #if !defined(MAKEFOURCC) # define MAKEFOURCC(ch0, ch1, ch2, ch3) \ ((unsigned int)((unsigned char)(ch0)) | \ ((unsigned int)((unsigned char)(ch1)) << 8) | \ ((unsigned int)((unsigned char)(ch2)) << 16) | \ ((unsigned int)((unsigned char)(ch3)) << 24 )) #endif static const unsigned int FOURCC_DDS = MAKEFOURCC('D', 'D', 'S', ' '); static const unsigned int FOURCC_DXT1 = MAKEFOURCC('D', 'X', 'T', '1'); static const unsigned int FOURCC_DXT2 = MAKEFOURCC('D', 'X', 'T', '2'); static const unsigned int FOURCC_DXT3 = MAKEFOURCC('D', 'X', 'T', '3'); static const unsigned int FOURCC_DXT4 = MAKEFOURCC('D', 'X', 'T', '4'); static const unsigned int FOURCC_DXT5 = MAKEFOURCC('D', 'X', 'T', '5'); static const unsigned int FOURCC_RXGB = MAKEFOURCC('R', 'X', 'G', 'B'); static const unsigned int FOURCC_ATI1 = MAKEFOURCC('A', 'T', 'I', '1'); static const unsigned int FOURCC_ATI2 = MAKEFOURCC('A', 'T', 'I', '2'); // RGB formats. static const unsigned int D3DFMT_R8G8B8 = 20; static const unsigned int D3DFMT_A8R8G8B8 = 21; static const unsigned int D3DFMT_X8R8G8B8 = 22; static const unsigned int D3DFMT_R5G6B5 = 23; static const unsigned int D3DFMT_X1R5G5B5 = 24; static const unsigned int D3DFMT_A1R5G5B5 = 25; static const unsigned int D3DFMT_A4R4G4B4 = 26; static const unsigned int D3DFMT_R3G3B2 = 27; static const unsigned int D3DFMT_A8 = 28; static const unsigned int D3DFMT_A8R3G3B2 = 29; static const unsigned int D3DFMT_X4R4G4B4 = 30; static const unsigned int D3DFMT_A2B10G10R10 = 31; static const unsigned int D3DFMT_A8B8G8R8 = 32; static const unsigned int D3DFMT_X8B8G8R8 = 33; static const unsigned int D3DFMT_G16R16 = 34; static const unsigned int D3DFMT_A2R10G10B10 = 35; static const unsigned int D3DFMT_A16B16G16R16 = 36; // Palette formats. static const unsigned int D3DFMT_A8P8 = 40; static const unsigned int D3DFMT_P8 = 41; // Luminance formats. static const unsigned int D3DFMT_L8 = 50; static const unsigned int D3DFMT_A8L8 = 51; static const unsigned int D3DFMT_A4L4 = 52; // Floating point formats static const unsigned int D3DFMT_R16F = 111; static const unsigned int D3DFMT_G16R16F = 112; static const unsigned int D3DFMT_A16B16G16R16F = 113; static const unsigned int D3DFMT_R32F = 114; static const unsigned int D3DFMT_G32R32F = 115; static const unsigned int D3DFMT_A32B32G32R32F = 116; static const unsigned int DDSD_CAPS = 0x00000001U; static const unsigned int DDSD_PIXELFORMAT = 0x00001000U; static const unsigned int DDSD_WIDTH = 0x00000004U; static const unsigned int DDSD_HEIGHT = 0x00000002U; static const unsigned int DDSD_PITCH = 0x00000008U; static const unsigned int DDSD_MIPMAPCOUNT = 0x00020000U; static const unsigned int DDSD_LINEARSIZE = 0x00080000U; static const unsigned int DDSD_DEPTH = 0x00800000U; static const unsigned int DDSCAPS_COMPLEX = 0x00000008U; static const unsigned int DDSCAPS_TEXTURE = 0x00001000U; static const unsigned int DDSCAPS_MIPMAP = 0x00400000U; static const unsigned int DDSCAPS2_VOLUME = 0x00200000U; static const unsigned int DDSCAPS2_CUBEMAP = 0x00000200U; static const unsigned int DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400U; static const unsigned int DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800U; static const unsigned int DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000U; static const unsigned int DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000U; static const unsigned int DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000U; static const unsigned int DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000U; static const unsigned int DDSCAPS2_CUBEMAP_ALL_FACES = 0x0000FC00U; static const unsigned int DDPF_ALPHAPIXELS = 0x00000001U; static const unsigned int DDPF_ALPHA = 0x00000002U; static const unsigned int DDPF_FOURCC = 0x00000004U; static const unsigned int DDPF_RGB = 0x00000040U; static const unsigned int DDPF_PALETTEINDEXED1 = 0x00000800U; static const unsigned int DDPF_PALETTEINDEXED2 = 0x00001000U; static const unsigned int DDPF_PALETTEINDEXED4 = 0x00000008U; static const unsigned int DDPF_PALETTEINDEXED8 = 0x00000020U; static const unsigned int DDPF_LUMINANCE = 0x00020000U; static const unsigned int DDPF_ALPHAPREMULT = 0x00008000U; static const unsigned int DDPF_NORMAL = 0x80000000U; // @@ Custom nv flag. /*** implementation ***/ void mem_read(Stream & mem, DDSPixelFormat & pf) { mem_read(mem, pf.size); mem_read(mem, pf.flags); mem_read(mem, pf.fourcc); mem_read(mem, pf.bitcount); mem_read(mem, pf.rmask); mem_read(mem, pf.gmask); mem_read(mem, pf.bmask); mem_read(mem, pf.amask); } void mem_read(Stream & mem, DDSCaps & caps) { mem_read(mem, caps.caps1); mem_read(mem, caps.caps2); mem_read(mem, caps.caps3); mem_read(mem, caps.caps4); } void mem_read(Stream & mem, DDSHeader & header) { mem_read(mem, header.fourcc); mem_read(mem, header.size); mem_read(mem, header.flags); mem_read(mem, header.height); mem_read(mem, header.width); mem_read(mem, header.pitch); mem_read(mem, header.depth); mem_read(mem, header.mipmapcount); for (unsigned int i = 0; i < 11; i++) mem_read(mem, header.reserved[i]); mem_read(mem, header.pf); mem_read(mem, header.caps); mem_read(mem, header.notused); } DDSHeader::DDSHeader() { this->fourcc = FOURCC_DDS; this->size = 124; this->flags = (DDSD_CAPS|DDSD_PIXELFORMAT); this->height = 0; this->width = 0; this->pitch = 0; this->depth = 0; this->mipmapcount = 0; for (unsigned int i = 0; i < 11; i++) this->reserved[i] = 0; // Store version information on the reserved header attributes. this->reserved[9] = MAKEFOURCC('N', 'V', 'T', 'T'); this->reserved[10] = (0 << 16) | (9 << 8) | (3); // major.minor.revision this->pf.size = 32; this->pf.flags = 0; this->pf.fourcc = 0; this->pf.bitcount = 0; this->pf.rmask = 0; this->pf.gmask = 0; this->pf.bmask = 0; this->pf.amask = 0; this->caps.caps1 = DDSCAPS_TEXTURE; this->caps.caps2 = 0; this->caps.caps3 = 0; this->caps.caps4 = 0; this->notused = 0; } void DDSHeader::setWidth(unsigned int w) { this->flags |= DDSD_WIDTH; this->width = w; } void DDSHeader::setHeight(unsigned int h) { this->flags |= DDSD_HEIGHT; this->height = h; } void DDSHeader::setDepth(unsigned int d) { this->flags |= DDSD_DEPTH; this->height = d; } void DDSHeader::setMipmapCount(unsigned int count) { if (count == 0) { this->flags &= ~DDSD_MIPMAPCOUNT; this->mipmapcount = 0; if (this->caps.caps2 == 0) { this->caps.caps1 = DDSCAPS_TEXTURE; } else { this->caps.caps1 = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX; } } else { this->flags |= DDSD_MIPMAPCOUNT; this->mipmapcount = count; this->caps.caps1 |= DDSCAPS_COMPLEX | DDSCAPS_MIPMAP; } } void DDSHeader::setTexture2D() { // nothing to do here. } void DDSHeader::setTexture3D() { this->caps.caps2 = DDSCAPS2_VOLUME; } void DDSHeader::setTextureCube() { this->caps.caps1 |= DDSCAPS_COMPLEX; this->caps.caps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALL_FACES; } void DDSHeader::setLinearSize(unsigned int size) { this->flags &= ~DDSD_PITCH; this->flags |= DDSD_LINEARSIZE; this->pitch = size; } void DDSHeader::setPitch(unsigned int pitch) { this->flags &= ~DDSD_LINEARSIZE; this->flags |= DDSD_PITCH; this->pitch = pitch; } void DDSHeader::setFourCC(unsigned char c0, unsigned char c1, unsigned char c2, unsigned char c3) { // set fourcc pixel format. this->pf.flags = DDPF_FOURCC; this->pf.fourcc = MAKEFOURCC(c0, c1, c2, c3); this->pf.bitcount = 0; this->pf.rmask = 0; this->pf.gmask = 0; this->pf.bmask = 0; this->pf.amask = 0; } void DDSHeader::setPixelFormat(unsigned int bitcount, unsigned int rmask, unsigned int gmask, unsigned int bmask, unsigned int amask) { // Make sure the masks are correct. if ((rmask & gmask) || \ (rmask & bmask) || \ (rmask & amask) || \ (gmask & bmask) || \ (gmask & amask) || \ (bmask & amask)) { printf("DDS: bad RGBA masks, pixel format not set\n"); return; } this->pf.flags = DDPF_RGB; if (amask != 0) { this->pf.flags |= DDPF_ALPHAPIXELS; } if (bitcount == 0) { // Compute bit count from the masks. unsigned int total = rmask | gmask | bmask | amask; while(total != 0) { bitcount++; total >>= 1; } // @@ Align to 8? } this->pf.fourcc = 0; this->pf.bitcount = bitcount; this->pf.rmask = rmask; this->pf.gmask = gmask; this->pf.bmask = bmask; this->pf.amask = amask; } void DDSHeader::setNormalFlag(bool b) { if (b) this->pf.flags |= DDPF_NORMAL; else this->pf.flags &= ~DDPF_NORMAL; } /* void DDSHeader::swapBytes() { this->fourcc = POSH_LittleU32(this->fourcc); this->size = POSH_LittleU32(this->size); this->flags = POSH_LittleU32(this->flags); this->height = POSH_LittleU32(this->height); this->width = POSH_LittleU32(this->width); this->pitch = POSH_LittleU32(this->pitch); this->depth = POSH_LittleU32(this->depth); this->mipmapcount = POSH_LittleU32(this->mipmapcount); for(int i = 0; i < 11; i++) { this->reserved[i] = POSH_LittleU32(this->reserved[i]); } this->pf.size = POSH_LittleU32(this->pf.size); this->pf.flags = POSH_LittleU32(this->pf.flags); this->pf.fourcc = POSH_LittleU32(this->pf.fourcc); this->pf.bitcount = POSH_LittleU32(this->pf.bitcount); this->pf.rmask = POSH_LittleU32(this->pf.rmask); this->pf.gmask = POSH_LittleU32(this->pf.gmask); this->pf.bmask = POSH_LittleU32(this->pf.bmask); this->pf.amask = POSH_LittleU32(this->pf.amask); this->caps.caps1 = POSH_LittleU32(this->caps.caps1); this->caps.caps2 = POSH_LittleU32(this->caps.caps2); this->caps.caps3 = POSH_LittleU32(this->caps.caps3); this->caps.caps4 = POSH_LittleU32(this->caps.caps4); this->notused = POSH_LittleU32(this->notused); } */ DirectDrawSurface::DirectDrawSurface(unsigned char *mem, unsigned int size) : stream(mem, size), header() { mem_read(stream, header); } DirectDrawSurface::~DirectDrawSurface() { } bool DirectDrawSurface::isValid() const { if (header.fourcc != FOURCC_DDS || header.size != 124) { return false; } const unsigned int required = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS|DDSD_PIXELFORMAT); if( (header.flags & required) != required ) { return false; } if (header.pf.size != 32) { return false; } /* in some files DDSCAPS_TEXTURE is missing: silently ignore */ /* if( !(header.caps.caps1 & DDSCAPS_TEXTURE) ) { return false; } */ return true; } bool DirectDrawSurface::isSupported() const { if (header.pf.flags & DDPF_FOURCC) { if (header.pf.fourcc != FOURCC_DXT1 && header.pf.fourcc != FOURCC_DXT2 && header.pf.fourcc != FOURCC_DXT3 && header.pf.fourcc != FOURCC_DXT4 && header.pf.fourcc != FOURCC_DXT5 && header.pf.fourcc != FOURCC_RXGB && header.pf.fourcc != FOURCC_ATI1 && header.pf.fourcc != FOURCC_ATI2) { // Unknown fourcc code. return false; } } else if (header.pf.flags & DDPF_RGB) { if (header.pf.bitcount == 24) { return true; } else if (header.pf.bitcount == 32) { return true; } else { // Unsupported pixel format. return false; } } else { return false; } if (isTextureCube() && (header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES) { // Cubemaps must contain all faces. return false; } if (isTexture3D()) { // @@ 3D textures not supported yet. return false; } return true; } unsigned int DirectDrawSurface::mipmapCount() const { if (header.flags & DDSD_MIPMAPCOUNT) return header.mipmapcount; else return 0; } unsigned int DirectDrawSurface::width() const { if (header.flags & DDSD_WIDTH) return header.width; else return 1; } unsigned int DirectDrawSurface::height() const { if (header.flags & DDSD_HEIGHT) return header.height; else return 1; } unsigned int DirectDrawSurface::depth() const { if (header.flags & DDSD_DEPTH) return header.depth; else return 1; } bool DirectDrawSurface::hasAlpha() const { if ((header.pf.flags & DDPF_RGB) && (header.pf.amask == 0)) { return false; } else if (header.pf.fourcc == FOURCC_DXT1) { return false; } else { return true; } } bool DirectDrawSurface::isTexture2D() const { return !isTexture3D() && !isTextureCube(); } bool DirectDrawSurface::isTexture3D() const { return (header.caps.caps2 & DDSCAPS2_VOLUME) != 0; } bool DirectDrawSurface::isTextureCube() const { return (header.caps.caps2 & DDSCAPS2_CUBEMAP) != 0; } void DirectDrawSurface::mipmap(Image * img, unsigned int face, unsigned int mipmap) { stream.seek(offset(face, mipmap)); unsigned int w = width(); unsigned int h = height(); // Compute width and height. for (unsigned int m = 0; m < mipmap; m++) { w = max(w/2, 1U); h = max(h/2, 1U); } img->allocate(w, h); if (header.pf.flags & DDPF_RGB) { readLinearImage(img); } else if (header.pf.flags & DDPF_FOURCC) { readBlockImage(img); } } /* helper function for readLinearImage */ void maskShiftAndSize(unsigned int mask, unsigned int * shift, unsigned int * size) { if (!mask) { *shift = 0; *size = 0; return; } *shift = 0; while((mask & 1) == 0) { ++(*shift); mask >>= 1; } *size = 0; while((mask & 1) == 1) { ++(*size); mask >>= 1; } } /* helper function for readLinearImage */ unsigned int convert(unsigned int c, unsigned int inbits, unsigned int outbits) { if (inbits == 0) { return 0; } else if (inbits == outbits) { return c; } else if (inbits > outbits) { // truncate return c >> (inbits - outbits); } else { // bitexpand return (c << (outbits - inbits)) | convert(c, inbits, outbits - inbits); } } void DirectDrawSurface::readLinearImage(Image * img) { const unsigned int w = img->width(); const unsigned int h = img->height(); unsigned int rshift, rsize; maskShiftAndSize(header.pf.rmask, &rshift, &rsize); unsigned int gshift, gsize; maskShiftAndSize(header.pf.gmask, &gshift, &gsize); unsigned int bshift, bsize; maskShiftAndSize(header.pf.bmask, &bshift, &bsize); unsigned int ashift, asize; maskShiftAndSize(header.pf.amask, &ashift, &asize); unsigned int byteCount = (header.pf.bitcount + 7) / 8; if (byteCount > 4) { /* just in case... we could have segfaults later on if byteCount > 4 */ printf("DDS: bitcount too large (file corrupt?)"); return; } if (header.pf.amask != 0) { img->setFormat(Image::Format_ARGB); } // Read linear RGB images. for (unsigned int y = 0; y < h; y++) { for (unsigned int x = 0; x < w; x++) { unsigned int c = 0; mem_read(stream, (unsigned char *)(&c), byteCount); Color32 pixel(0, 0, 0, 0xFF); pixel.r = convert(c >> rshift, rsize, 8); pixel.g = convert(c >> gshift, gsize, 8); pixel.b = convert(c >> bshift, bsize, 8); pixel.a = convert(c >> ashift, asize, 8); img->pixel(x, y) = pixel; } } } void DirectDrawSurface::readBlockImage(Image * img) { const unsigned int w = img->width(); const unsigned int h = img->height(); const unsigned int bw = (w + 3) / 4; const unsigned int bh = (h + 3) / 4; for (unsigned int by = 0; by < bh; by++) { for (unsigned int bx = 0; bx < bw; bx++) { ColorBlock block; // Read color block. readBlock(&block); // Write color block. for (unsigned int y = 0; y < min(4U, h-4*by); y++) { for (unsigned int x = 0; x < min(4U, w-4*bx); x++) { img->pixel(4*bx+x, 4*by+y) = block.color(x, y); } } } } } static Color32 buildNormal(unsigned char x, unsigned char y) { float nx = 2 * (x / 255) - 1; float ny = 2 * (x / 255) - 1; float nz = sqrt(1 - nx*nx - ny*ny); unsigned char z = clamp(int(255 * (nz + 1) / 2), 0, 255); return Color32(x, y, z); } void DirectDrawSurface::readBlock(ColorBlock * rgba) { if (header.pf.fourcc == FOURCC_DXT1) { BlockDXT1 block; mem_read(stream, block); block.decodeBlock(rgba); } else if (header.pf.fourcc == FOURCC_DXT2 || header.pf.fourcc == FOURCC_DXT3) { BlockDXT3 block; mem_read(stream, block); block.decodeBlock(rgba); } else if (header.pf.fourcc == FOURCC_DXT4 || header.pf.fourcc == FOURCC_DXT5 || header.pf.fourcc == FOURCC_RXGB) { BlockDXT5 block; mem_read(stream, block); block.decodeBlock(rgba); if (header.pf.fourcc == FOURCC_RXGB) { // Swap R & A. for (int i = 0; i < 16; i++) { Color32 & c = rgba->color(i); unsigned int tmp = c.r; c.r = c.a; c.a = tmp; } } } else if (header.pf.fourcc == FOURCC_ATI1) { BlockATI1 block; mem_read(stream, block); block.decodeBlock(rgba); } else if (header.pf.fourcc == FOURCC_ATI2) { BlockATI2 block; mem_read(stream, block); block.decodeBlock(rgba); } // If normal flag set, convert to normal. if (header.pf.flags & DDPF_NORMAL) { if (header.pf.fourcc == FOURCC_ATI2) { for (int i = 0; i < 16; i++) { Color32 & c = rgba->color(i); c = buildNormal(c.r, c.g); } } else if (header.pf.fourcc == FOURCC_DXT5) { for (int i = 0; i < 16; i++) { Color32 & c = rgba->color(i); c = buildNormal(c.g, c.a); } } } } unsigned int DirectDrawSurface::blockSize() const { switch(header.pf.fourcc) { case FOURCC_DXT1: case FOURCC_ATI1: return 8; case FOURCC_DXT2: case FOURCC_DXT3: case FOURCC_DXT4: case FOURCC_DXT5: case FOURCC_RXGB: case FOURCC_ATI2: return 16; }; // Not a block image. return 0; } unsigned int DirectDrawSurface::mipmapSize(unsigned int mipmap) const { unsigned int w = width(); unsigned int h = height(); unsigned int d = depth(); for (unsigned int m = 0; m < mipmap; m++) { w = max(1U, w / 2); h = max(1U, h / 2); d = max(1U, d / 2); } if (header.pf.flags & DDPF_FOURCC) { // @@ How are 3D textures aligned? w = (w + 3) / 4; h = (h + 3) / 4; return blockSize() * w * h; } else if (header.pf.flags & DDPF_RGB) { // Align pixels to bytes. unsigned int byteCount = (header.pf.bitcount + 7) / 8; // Align pitch to 4 bytes. unsigned int pitch = 4 * ((w * byteCount + 3) / 4); return pitch * h * d; } else { printf("DDS: mipmap format not supported\n"); return(0); }; } unsigned int DirectDrawSurface::faceSize() const { const unsigned int count = mipmapCount(); unsigned int size = 0; for (unsigned int m = 0; m < count; m++) { size += mipmapSize(m); } return size; } unsigned int DirectDrawSurface::offset(const unsigned int face, const unsigned int mipmap) { unsigned int size = sizeof(DDSHeader); if (face != 0) { size += face * faceSize(); } for (unsigned int m = 0; m < mipmap; m++) { size += mipmapSize(m); } return size; } void DirectDrawSurface::printInfo() const { /* printf("FOURCC: %c%c%c%c\n", ((unsigned char *)&header.fourcc)[0], ((unsigned char *)&header.fourcc)[1], ((unsigned char *)&header.fourcc)[2], ((unsigned char *)&header.fourcc)[3]); */ printf("Flags: 0x%.8X\n", header.flags); if (header.flags & DDSD_CAPS) printf("\tDDSD_CAPS\n"); if (header.flags & DDSD_PIXELFORMAT) printf("\tDDSD_PIXELFORMAT\n"); if (header.flags & DDSD_WIDTH) printf("\tDDSD_WIDTH\n"); if (header.flags & DDSD_HEIGHT) printf("\tDDSD_HEIGHT\n"); if (header.flags & DDSD_DEPTH) printf("\tDDSD_DEPTH\n"); if (header.flags & DDSD_PITCH) printf("\tDDSD_PITCH\n"); if (header.flags & DDSD_LINEARSIZE) printf("\tDDSD_LINEARSIZE\n"); if (header.flags & DDSD_MIPMAPCOUNT) printf("\tDDSD_MIPMAPCOUNT\n"); printf("Height: %d\n", header.height); printf("Width: %d\n", header.width); printf("Depth: %d\n", header.depth); if (header.flags & DDSD_PITCH) printf("Pitch: %d\n", header.pitch); else if (header.flags & DDSD_LINEARSIZE) printf("Linear size: %d\n", header.pitch); printf("Mipmap count: %d\n", header.mipmapcount); printf("Pixel Format:\n"); /* printf("\tSize: %d\n", header.pf.size); */ printf("\tFlags: 0x%.8X\n", header.pf.flags); if (header.pf.flags & DDPF_RGB) printf("\t\tDDPF_RGB\n"); if (header.pf.flags & DDPF_FOURCC) printf("\t\tDDPF_FOURCC\n"); if (header.pf.flags & DDPF_ALPHAPIXELS) printf("\t\tDDPF_ALPHAPIXELS\n"); if (header.pf.flags & DDPF_ALPHA) printf("\t\tDDPF_ALPHA\n"); if (header.pf.flags & DDPF_PALETTEINDEXED1) printf("\t\tDDPF_PALETTEINDEXED1\n"); if (header.pf.flags & DDPF_PALETTEINDEXED2) printf("\t\tDDPF_PALETTEINDEXED2\n"); if (header.pf.flags & DDPF_PALETTEINDEXED4) printf("\t\tDDPF_PALETTEINDEXED4\n"); if (header.pf.flags & DDPF_PALETTEINDEXED8) printf("\t\tDDPF_PALETTEINDEXED8\n"); if (header.pf.flags & DDPF_ALPHAPREMULT) printf("\t\tDDPF_ALPHAPREMULT\n"); if (header.pf.flags & DDPF_NORMAL) printf("\t\tDDPF_NORMAL\n"); printf("\tFourCC: '%c%c%c%c'\n", ((header.pf.fourcc >> 0) & 0xFF), ((header.pf.fourcc >> 8) & 0xFF), ((header.pf.fourcc >> 16) & 0xFF), ((header.pf.fourcc >> 24) & 0xFF)); printf("\tBit count: %d\n", header.pf.bitcount); printf("\tRed mask: 0x%.8X\n", header.pf.rmask); printf("\tGreen mask: 0x%.8X\n", header.pf.gmask); printf("\tBlue mask: 0x%.8X\n", header.pf.bmask); printf("\tAlpha mask: 0x%.8X\n", header.pf.amask); printf("Caps:\n"); printf("\tCaps 1: 0x%.8X\n", header.caps.caps1); if (header.caps.caps1 & DDSCAPS_COMPLEX) printf("\t\tDDSCAPS_COMPLEX\n"); if (header.caps.caps1 & DDSCAPS_TEXTURE) printf("\t\tDDSCAPS_TEXTURE\n"); if (header.caps.caps1 & DDSCAPS_MIPMAP) printf("\t\tDDSCAPS_MIPMAP\n"); printf("\tCaps 2: 0x%.8X\n", header.caps.caps2); if (header.caps.caps2 & DDSCAPS2_VOLUME) printf("\t\tDDSCAPS2_VOLUME\n"); else if (header.caps.caps2 & DDSCAPS2_CUBEMAP) { printf("\t\tDDSCAPS2_CUBEMAP\n"); if ((header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) == DDSCAPS2_CUBEMAP_ALL_FACES) printf("\t\tDDSCAPS2_CUBEMAP_ALL_FACES\n"); else { if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEX) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEX\n"); if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEX\n"); if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEY) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEY\n"); if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEY\n"); if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEZ\n"); if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEZ\n"); } } printf("\tCaps 3: 0x%.8X\n", header.caps.caps3); printf("\tCaps 4: 0x%.8X\n", header.caps.caps4); if (header.reserved[9] == MAKEFOURCC('N', 'V', 'T', 'T')) { int major = (header.reserved[10] >> 16) & 0xFF; int minor = (header.reserved[10] >> 8) & 0xFF; int revision= header.reserved[10] & 0xFF; printf("Version:\n"); printf("\tNVIDIA Texture Tools %d.%d.%d\n", major, minor, revision); } }