Deal with DDS files that specify neither pitch nor linearsize.
authorRyan C. Gordon <icculus@icculus.org>
Tue, 10 May 2011 00:08:55 -0400
changeset 7 341c4de6ffd3
parent 6 b693c592d4ab
child 8 506dbbccee95
Deal with DDS files that specify neither pitch nor linearsize.
mojodds.c
--- a/mojodds.c	Sun May 08 21:34:49 2011 -0400
+++ b/mojodds.c	Tue May 10 00:08:55 2011 -0400
@@ -11,6 +11,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
+#include <assert.h>
 
 #ifdef _MSC_VER
 typedef unsigned __int8 uint8;
@@ -102,6 +103,11 @@
 
 static int parse_dds(MOJODDS_Header *header, const uint8 **ptr, size_t *len)
 {
+    const uint32 pitchAndLinear = (DDSD_PITCH | DDSD_LINEARSIZE);
+    uint32 width = 0;
+    uint32 height = 0;
+    uint32 calcSize = 0;
+    uint32 calcSizeFlag = DDSD_LINEARSIZE;
     int i;
 
     // Files start with magic value...
@@ -135,6 +141,9 @@
     header->dwCaps4 = readui32(ptr, len);
     header->dwReserved2 = readui32(ptr, len);
 
+    width = header->dwWidth;
+    height = header->dwHeight;
+
     if (header->dwSize != DDS_HEADERSIZE)   // header size must be 124.
         return 0;
     else if (header->ddspf.dwSize != DDS_PIXFMTSIZE)   // size must be 32.
@@ -145,29 +154,45 @@
         return 0;
     else if (header->dwCaps2 != 0)  // !!! FIXME (non-zero with other bits in dwCaps set)
         return 0;
+    else if ((header->dwFlags & pitchAndLinear) == pitchAndLinear)
+        return 0;  // can't specify both.
 
     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:
+                calcSize = ((width ? ((width + 3) / 4) : 1) * 8) * height;
+                break;
             case FOURCC_DXT2:
             case FOURCC_DXT3:
             case FOURCC_DXT4:
             case FOURCC_DXT5:
+                calcSize = ((width ? ((width + 3) / 4) : 1) * 16) * height;
+                break;
             // !!! FIXME: DX10 is an extended header, introduced by DirectX 10.
             //case FOURCC_DX10:
-                break;
             default:
                 return 0;  // unsupported data format.
         } // switch
     } // if
 
+    // no pitch or linear size? Calculate it.
+    if ((header->dwFlags & pitchAndLinear) == 0)
+    {
+        if (!calcSizeFlag)
+        {
+            assert(0 && "should have caught this up above");
+            return 0;  // uh oh.
+        } // if
+
+        header->dwPitchOrLinearSize = calcSize;
+        header->dwFlags |= calcSizeFlag;
+    } // if
+
     return 1;
 } // parse_dds
 
@@ -178,7 +203,7 @@
     size_t len = (size_t) _len;
     const uint8 *ptr = (const uint8 *) _ptr;
     return (readui32(&ptr, &len) == DDS_MAGIC);
-}
+} // MOJODDS_isDDS
 
 int MOJODDS_getTexture(const void *_ptr, const unsigned long _len,
                        const void **_tex, unsigned long *_texlen, int *_dxtver,