mojodds.c
changeset 7 341c4de6ffd3
parent 5 ab7382a45d11
child 8 506dbbccee95
equal deleted inserted replaced
6:b693c592d4ab 7:341c4de6ffd3
     9 // Specs on DDS format: http://msdn.microsoft.com/en-us/library/bb943991.aspx/
     9 // Specs on DDS format: http://msdn.microsoft.com/en-us/library/bb943991.aspx/
    10 
    10 
    11 #include <stdio.h>
    11 #include <stdio.h>
    12 #include <string.h>
    12 #include <string.h>
    13 #include <stdlib.h>
    13 #include <stdlib.h>
       
    14 #include <assert.h>
    14 
    15 
    15 #ifdef _MSC_VER
    16 #ifdef _MSC_VER
    16 typedef unsigned __int8 uint8;
    17 typedef unsigned __int8 uint8;
    17 typedef unsigned __int32 uint32;
    18 typedef unsigned __int32 uint32;
    18 #else
    19 #else
   100     return retval;
   101     return retval;
   101 } // readui32
   102 } // readui32
   102 
   103 
   103 static int parse_dds(MOJODDS_Header *header, const uint8 **ptr, size_t *len)
   104 static int parse_dds(MOJODDS_Header *header, const uint8 **ptr, size_t *len)
   104 {
   105 {
       
   106     const uint32 pitchAndLinear = (DDSD_PITCH | DDSD_LINEARSIZE);
       
   107     uint32 width = 0;
       
   108     uint32 height = 0;
       
   109     uint32 calcSize = 0;
       
   110     uint32 calcSizeFlag = DDSD_LINEARSIZE;
   105     int i;
   111     int i;
   106 
   112 
   107     // Files start with magic value...
   113     // Files start with magic value...
   108     if (readui32(ptr, len) != DDS_MAGIC)
   114     if (readui32(ptr, len) != DDS_MAGIC)
   109         return 0;  // not a DDS file.
   115         return 0;  // not a DDS file.
   133     header->dwCaps2 = readui32(ptr, len);
   139     header->dwCaps2 = readui32(ptr, len);
   134     header->dwCaps3 = readui32(ptr, len);
   140     header->dwCaps3 = readui32(ptr, len);
   135     header->dwCaps4 = readui32(ptr, len);
   141     header->dwCaps4 = readui32(ptr, len);
   136     header->dwReserved2 = readui32(ptr, len);
   142     header->dwReserved2 = readui32(ptr, len);
   137 
   143 
       
   144     width = header->dwWidth;
       
   145     height = header->dwHeight;
       
   146 
   138     if (header->dwSize != DDS_HEADERSIZE)   // header size must be 124.
   147     if (header->dwSize != DDS_HEADERSIZE)   // header size must be 124.
   139         return 0;
   148         return 0;
   140     else if (header->ddspf.dwSize != DDS_PIXFMTSIZE)   // size must be 32.
   149     else if (header->ddspf.dwSize != DDS_PIXFMTSIZE)   // size must be 32.
   141         return 0;
   150         return 0;
   142     else if ((header->dwFlags & DDSD_REQ) != DDSD_REQ)  // must have these bits.
   151     else if ((header->dwFlags & DDSD_REQ) != DDSD_REQ)  // must have these bits.
   143         return 0;
   152         return 0;
   144     else if (header->dwCaps != DDSCAPS_TEXTURE)  // !!! FIXME
   153     else if (header->dwCaps != DDSCAPS_TEXTURE)  // !!! FIXME
   145         return 0;
   154         return 0;
   146     else if (header->dwCaps2 != 0)  // !!! FIXME (non-zero with other bits in dwCaps set)
   155     else if (header->dwCaps2 != 0)  // !!! FIXME (non-zero with other bits in dwCaps set)
   147         return 0;
   156         return 0;
       
   157     else if ((header->dwFlags & pitchAndLinear) == pitchAndLinear)
       
   158         return 0;  // can't specify both.
   148 
   159 
   149     if ((header->ddspf.dwFlags & DDPF_FOURCC) == 0)  // !!! FIXME
   160     if ((header->ddspf.dwFlags & DDPF_FOURCC) == 0)  // !!! FIXME
   150         return 0;
       
   151     if ((header->dwFlags & DDSD_LINEARSIZE) == 0)  // !!! FIXME
       
   152         return 0;
   161         return 0;
   153 
   162 
   154     if (header->ddspf.dwFlags & DDPF_FOURCC)
   163     if (header->ddspf.dwFlags & DDPF_FOURCC)
   155     {
   164     {
   156         switch (header->ddspf.dwFourCC)
   165         switch (header->ddspf.dwFourCC)
   157         {
   166         {
   158             case FOURCC_DXT1:
   167             case FOURCC_DXT1:
       
   168                 calcSize = ((width ? ((width + 3) / 4) : 1) * 8) * height;
       
   169                 break;
   159             case FOURCC_DXT2:
   170             case FOURCC_DXT2:
   160             case FOURCC_DXT3:
   171             case FOURCC_DXT3:
   161             case FOURCC_DXT4:
   172             case FOURCC_DXT4:
   162             case FOURCC_DXT5:
   173             case FOURCC_DXT5:
       
   174                 calcSize = ((width ? ((width + 3) / 4) : 1) * 16) * height;
       
   175                 break;
   163             // !!! FIXME: DX10 is an extended header, introduced by DirectX 10.
   176             // !!! FIXME: DX10 is an extended header, introduced by DirectX 10.
   164             //case FOURCC_DX10:
   177             //case FOURCC_DX10:
   165                 break;
       
   166             default:
   178             default:
   167                 return 0;  // unsupported data format.
   179                 return 0;  // unsupported data format.
   168         } // switch
   180         } // switch
   169     } // if
   181     } // if
   170 
   182 
       
   183     // no pitch or linear size? Calculate it.
       
   184     if ((header->dwFlags & pitchAndLinear) == 0)
       
   185     {
       
   186         if (!calcSizeFlag)
       
   187         {
       
   188             assert(0 && "should have caught this up above");
       
   189             return 0;  // uh oh.
       
   190         } // if
       
   191 
       
   192         header->dwPitchOrLinearSize = calcSize;
       
   193         header->dwFlags |= calcSizeFlag;
       
   194     } // if
       
   195 
   171     return 1;
   196     return 1;
   172 } // parse_dds
   197 } // parse_dds
   173 
   198 
   174 
   199 
   175 // !!! FIXME: improve the crap out of this API later.
   200 // !!! FIXME: improve the crap out of this API later.
   176 int MOJODDS_isDDS(const void *_ptr, const unsigned long _len)
   201 int MOJODDS_isDDS(const void *_ptr, const unsigned long _len)
   177 {
   202 {
   178     size_t len = (size_t) _len;
   203     size_t len = (size_t) _len;
   179     const uint8 *ptr = (const uint8 *) _ptr;
   204     const uint8 *ptr = (const uint8 *) _ptr;
   180     return (readui32(&ptr, &len) == DDS_MAGIC);
   205     return (readui32(&ptr, &len) == DDS_MAGIC);
   181 }
   206 } // MOJODDS_isDDS
   182 
   207 
   183 int MOJODDS_getTexture(const void *_ptr, const unsigned long _len,
   208 int MOJODDS_getTexture(const void *_ptr, const unsigned long _len,
   184                        const void **_tex, unsigned long *_texlen, int *_dxtver,
   209                        const void **_tex, unsigned long *_texlen, int *_dxtver,
   185                        unsigned int *_w, unsigned int *_h)
   210                        unsigned int *_w, unsigned int *_h)
   186 {
   211 {