Initial bit of code I scratched out. Not nearly complete, no real API yet.
authorRyan C. Gordon <icculus@icculus.org>
Sat, 07 May 2011 03:32:54 -0400
changeset 0 8daba3cc1efb
child 1 90603fda7444
Initial bit of code I scratched out. Not nearly complete, no real API yet.
mojodds.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mojodds.c	Sat May 07 03:32:54 2011 -0400
@@ -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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef _MSC_VER
+typedef unsigned __int8 uint8;
+typedef unsigned __int32 uint32;
+#else
+#include <stdint.h>
+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 ...
+