From 5f561a6157ce9b0fbece103e1a8d6123a23f3253 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 7 May 2011 03:32:54 -0400 Subject: [PATCH] Initial bit of code I scratched out. Not nearly complete, no real API yet. --- mojodds.c | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 mojodds.c diff --git a/mojodds.c b/mojodds.c new file mode 100644 index 0000000..4740029 --- /dev/null +++ b/mojodds.c @@ -0,0 +1,202 @@ +/** + * MojoDDS; tools for dealing with DDS files. + * + * Please see the file LICENSE.txt in the source's root directory. + * + * This file written by Ryan C. Gordon. + */ + +// Specs on DDS format: http://msdn.microsoft.com/en-us/library/bb943991.aspx/ + +#include +#include +#include + +#ifdef _MSC_VER +typedef unsigned __int8 uint8; +typedef unsigned __int32 uint32; +#else +#include +typedef uint8_t uint8; +typedef uint32_t uint32; +#endif + +#define STATICARRAYLEN(x) ( (sizeof ((x))) / (sizeof ((x)[0])) ) + + +#define DDS_MAGIC 0x20534444 // 'DDS ' in littleendian. +#define DDS_HEADERSIZE 124 +#define DDS_PIXFMTSIZE 32 +#define DDSD_CAPS 0x1 +#define DDSD_HEIGHT 0x2 +#define DDSD_WIDTH 0x4 +#define DDSD_PITCH 0x8 +#define DDSD_FMT 0x1000 +#define DDSD_MIPMAPCOUNT 0x20000 +#define DDSD_LINEARSIZE 0x80000 +#define DDSD_DEPTH 0x800000 +#define DDSD_REQ (DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_FMT) +#define DDSCAPS_COMPLEX 0x8 +#define DDSCAPS_MIPMAP 0x400000 +#define DDSCAPS_TEXTURE 0x1000 +#define DDPF_ALPHAPIXELS 0x1 +#define DDPF_ALPHA 0x2 +#define DDPF_FOURCC 0x4 +#define DDPF_RGB 0x40 +#define DDPF_YUV 0x200 +#define DDPF_LUMINANCE 0x20000 + +#define FOURCC_DXT1 0x31545844 +#define FOURCC_DXT2 0x32545844 +#define FOURCC_DXT3 0x33545844 +#define FOURCC_DXT4 0x34545844 +#define FOURCC_DXT5 0x35545844 +#define FOURCC_DX10 0x30315844 + +typedef struct +{ + uint32 dwSize; + uint32 dwFlags; + uint32 dwFourCC; + uint32 dwRGBBitCount; + uint32 dwRBitMask; + uint32 dwGBitMask; + uint32 dwBBitMask; + uint32 dwABitMask; +} MOJODDS_PixelFormat; + +typedef struct +{ + uint32 dwSize; + uint32 dwFlags; + uint32 dwHeight; + uint32 dwWidth; + uint32 dwPitchOrLinearSize; + uint32 dwDepth; + uint32 dwMipMapCount; + uint32 dwReserved1[11]; + MOJODDS_PixelFormat ddspf; + uint32 dwCaps; + uint32 dwCaps2; + uint32 dwCaps3; + uint32 dwCaps4; + uint32 dwReserved2; +} MOJODDS_Header; + + +static uint32 readui32(const uint8 **_ptr, size_t *_len) +{ + uint32 retval = 0; + if (*_len < sizeof (retval)) + *_len = 0; + else + { + const uint8 *ptr = *_ptr; + retval = (((uint32) ptr[0]) << 0) | (((uint32) ptr[1]) << 8) | + (((uint32) ptr[2]) << 16) | (((uint32) ptr[3]) << 24) ; + *_ptr += sizeof (retval); + *_len -= sizeof (retval); + } // else + return retval; +} // readui32 + +static int parse_dds(MOJODDS_Header *header, const uint8 **ptr, size_t *len) +{ + int i; + + // Files start with magic value... + if (readui32(ptr, len) != DDS_MAGIC) + return 0; // not a DDS file. + + // Then comes the DDS header... + if (*len < DDS_HEADERSIZE) + return 0; + + header->dwSize = readui32(ptr, len); + header->dwFlags = readui32(ptr, len); + header->dwHeight = readui32(ptr, len); + header->dwWidth = readui32(ptr, len); + header->dwPitchOrLinearSize = readui32(ptr, len); + header->dwDepth = readui32(ptr, len); + header->dwMipMapCount = readui32(ptr, len); + for (i = 0; i < STATICARRAYLEN(header->dwReserved1); i++) + header->dwReserved1[i] = readui32(ptr, len); + header->ddspf.dwSize = readui32(ptr, len); + header->ddspf.dwFlags = readui32(ptr, len); + header->ddspf.dwFourCC = readui32(ptr, len); + header->ddspf.dwRGBBitCount = readui32(ptr, len); + header->ddspf.dwRBitMask = readui32(ptr, len); + header->ddspf.dwGBitMask = readui32(ptr, len); + header->ddspf.dwBBitMask = readui32(ptr, len); + header->ddspf.dwABitMask = readui32(ptr, len); + header->dwCaps = readui32(ptr, len); + header->dwCaps2 = readui32(ptr, len); + header->dwCaps3 = readui32(ptr, len); + header->dwCaps4 = readui32(ptr, len); + header->dwReserved2 = readui32(ptr, len); + + if (header->dwSize != DDS_HEADERSIZE) // header size must be 124. + return 0; + else if (header->ddspf.dwSize != DDS_PIXFMTSIZE) // size must be 32. + return 0; + else if ((header->dwFlags & DDSD_REQ) != DDSD_REQ) // must have these bits. + return 0; + else if (header->dwCaps != DDSCAPS_TEXTURE) // !!! FIXME + return 0; + else if (header->dwCaps2 != 0) // !!! FIXME (non-zero with other bits in dwCaps set) + return 0; + + if ((header->ddspf.dwFlags & DDPF_FOURCC) == 0) // !!! FIXME + return 0; + if ((header->dwFlags & DDSD_LINEARSIZE) == 0) // !!! FIXME + return 0; + + if (header->ddspf.dwFlags & DDPF_FOURCC) + { + switch (header->ddspf.dwFourCC) + { + case FOURCC_DXT1: + case FOURCC_DXT2: + case FOURCC_DXT3: + case FOURCC_DXT4: + case FOURCC_DXT5: + // !!! FIXME: DX10 is an extended header, introduced by DirectX 10. + //case FOURCC_DX10: + break; + default: + return 0; // unsupported data format. + } // switch + } // if + + return 1; +} // parse_dds + + +// !!! FIXME: improve the crap out of this API later. +int MOJODDS_getTexture(const void *_ptr, const long _len, + const void **_tex, long *_texlen, int *_dxtver) +{ + size_t len = (size_t) _len; + const uint8 *ptr = (const uint8 *) _ptr; + MOJODDS_Header header; + if (!parse_dds(&header, &ptr, &len)) + return 0; + + *_tex = (const void *) ptr; + *_texlen = (long) header.dwPitchOrLinearSize; + + switch (header.ddspf.dwFourCC) + { + case FOURCC_DXT1: *_dxtver = 1; break; + case FOURCC_DXT2: *_dxtver = 2; break; + case FOURCC_DXT3: *_dxtver = 3; break; + case FOURCC_DXT4: *_dxtver = 4; break; + case FOURCC_DXT5: *_dxtver = 5; break; + default: *_dxtver = 0; return 0; + } // switch + + return 1; +} // MOJODDS_getTexture + +// end of mojodds.c ... +