Advertisement
Guest User

Untitled

a guest
May 15th, 2012
545
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 15.09 KB | None | 0 0
  1. /*
  2.     Author: Necrolis (www.d2mods.com)
  3.     Credits: plash - for pointing out various things here and there (mainly the incorrect atlas names).
  4.              Fiel & npd2006 - for giving me much needed testing feedback :)
  5. */
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <assert.h>
  11. #include <stdint.h>
  12. #include <stddef.h>
  13. #include "DDSMake.h"
  14.  
  15. /*
  16.     Current Limitations:
  17.         - No cubemaps, but it seems D3 doesn't use Tex files for cubemaps
  18.         - Only DXTn Has been tested, no 2 phase files found yet!
  19.         - Some decodes may come out weird due to my cheap stride/decode method stuff, need a test file for these too :)
  20.         - Two Phase decoding is not done, this is the first thing on my list to add
  21. */
  22.  
  23. enum eD3SNOTypes
  24. {
  25.     SNO_MAGIC           = 0xDEADBEEF,
  26.     SNO_TEXTURE         = 0x2D, // was 0x2C
  27.     SNO_SURFACE         = 0x2B,
  28. };
  29.  
  30. struct SNOHeader            //sizeof 0x10
  31. {
  32.     uint32_t dwMagic;       //+00 - 0xDEADBEEF
  33.     uint32_t dwSNOType;     //+04 - see 0x8148F0, 0x2B(Surface), 0x2C(Texture)
  34.     uint32_t dwUnknown[2];  //+08 - probably prev/next links for runtime
  35. };
  36.  
  37. struct TexMipLevel          //sizeof 0x8
  38. {
  39.     uint32_t dwDataStart;   //+00
  40.     uint32_t dwDataSize;    //+04
  41. };
  42.  
  43. struct TexHeader                //sizeof 0x378
  44. {
  45.     uint32_t dwUnk[3];          //+00 - NOT the SNO header!!!
  46.     uint32_t fFlags;            //+0C
  47.     uint32_t dwPixelFormat;     //+10 - Format of the Pixel Data ([9..12] do extra decoding, bound between 0 and 40)
  48.     uint32_t nWidth;            //+14
  49.     uint32_t nHeight;           //+18
  50.     uint32_t nMipLevels;        //+1C - this includes 0 sized mips too :O
  51.     uint32_t nUnk6[2];          //+20
  52.     TexMipLevel pMipLevels[31]; //+28
  53.     uint32_t dwLoadType;        //+124 - determines frame header size 0x10(1) or 0x14(0)
  54.     uint32_t dwUnk2;            //+128
  55.     uint32_t dwPixelDataStart;  //+12C - runtime only
  56.     uint32_t dwUnk3[55];        //+130
  57.     uint32_t dwAtlasEntries;    //+208
  58.     uint32_t dwAtlasOffset;     //+20C
  59.     uint32_t dwUnk7[13];        //+210
  60.     void* pTexture;             //+244 - runtime store of the texture pointer
  61.     uint32_t nPool;             //+248
  62.     uint32_t dwUnk4;            //+24C
  63.     char szIFLName[256];        //+250
  64.     uint32_t dwUnk5[10];        //+350
  65.     //tex entries follow directly
  66. };
  67.  
  68. struct TexEntry                 //sizeof 0x204
  69. {
  70.     char szInternalName[256];   //+000
  71.     char szFileName[256];       //+100
  72.     uint32_t nEntryNumber;      //+200
  73. };
  74.  
  75. struct TexAtlasEntry        //sizeof 0x50
  76. {
  77.     char szName[64];        //+00
  78.     float fXpos;            //+40
  79.     float fYpos;            //+44
  80.     float fXposEnd;         //+48
  81.     float fYposEnd;         //+4C
  82. };
  83.  
  84.  
  85. int GetD3DTextureFormat(int nFormat)
  86. {
  87.     if(nFormat > 40)
  88.     {
  89.         puts("Invalid Texture Format!\n");
  90.         assert(false);
  91.     }
  92.  
  93.     switch(nFormat)
  94.     {
  95.         case 0: return 21;  //D3DFMT_A8R8G8B8
  96.         case 1: return 0;
  97.         case 2: return 22;  //D3DFMT_X8R8G8B8
  98.         case 3: return 26;  //D3DFMT_A4R4G4B4
  99.         case 4: return 25;  //D3DFMT_A1R5G5B5
  100.         case 5: return 24;  //D3DFMT_X1R5G5B5
  101.         case 6: return 23;  //D3DFMT_R5G6B5
  102.         case 7: return 50;  //D3DFMT_L8
  103.         case 8: return 0;
  104.         case 9: return 0x31545844; //DXT1
  105.         case 10: return 0x31545844; //DXT1
  106.         case 11: return 0x33545844; //DXT3
  107.         case 12: return 0x35545844; //DXT5
  108.         case 13: return 0;
  109.         case 14: return 0;
  110.         case 15: return 0;
  111.         case 16: return 0;
  112.         case 17: return 0;
  113.         case 18: return 0;
  114.         case 19: return 0;
  115.         case 20: return 0;
  116.         case 21: return 32; //D3DFMT_A8B8G8R8
  117.         case 22: return 0;
  118.         case 23: return 28; //D3DFMT_A8
  119.         case 24: return 114;   //D3DFMT_R32F
  120.         case 25: return 113;   //D3DFMT_A16B16G16R16F
  121.         case 26: return 116;   //D3DFMT_A32B32G32R32F
  122.         case 27: return 0;
  123.         case 28: return 0;
  124.         case 29: return 0;
  125.         case 30: return 77; //D3DFMT_D24X8
  126.         case 31: return 80; //D3DFMT_D16
  127.         case 32: return 0x34324644; //DF24
  128.         case 33: return 0x36314644; //DF26
  129.         case 34: return 71; //D3DFMT_D32
  130.         case 35: return 0x5A574152; //RAWZ
  131.         case 36: return 0x5A544E49; //INTZ
  132.         case 37: return 77; //D3DFMT_D24X8
  133.         case 38: return 110;   //D3DFMT_R16F
  134.         case 39: return 115;   //D3DFMT_G32R32F
  135.         case 40: return 112;   //D3DFMT_G16R16F
  136.     }
  137.  
  138.     puts("Invalid Texture Format!\n");
  139.     assert(false);
  140.     return 0;
  141. }
  142.  
  143. #define D3DVal(x,y) case y: return #x;
  144.  
  145.  
  146. const char* GetD3DFormatName(int nD3DFormat)
  147. {
  148.     switch(nD3DFormat)
  149.     {
  150.         D3DVal(D3DFMT_UNKNOWN,0)
  151.  
  152.         D3DVal(D3DFMT_R8G8B8,20)
  153.         D3DVal(D3DFMT_A8R8G8B8,21)
  154.         D3DVal(D3DFMT_X8R8G8B8,22)
  155.         D3DVal(D3DFMT_R5G6B5,23)
  156.         D3DVal(D3DFMT_X1R5G5B5,24)
  157.         D3DVal(D3DFMT_A1R5G5B5,25)
  158.         D3DVal(D3DFMT_A4R4G4B4,26)
  159.         D3DVal(D3DFMT_R3G3B2,27)
  160.         D3DVal(D3DFMT_A8,28)
  161.         D3DVal(D3DFMT_A8R3G3B2,29)
  162.         D3DVal(D3DFMT_X4R4G4B4,30)
  163.         D3DVal(D3DFMT_A2B10G10R10,31)
  164.         D3DVal(D3DFMT_A8B8G8R8,32)
  165.         D3DVal(D3DFMT_X8B8G8R8,33)
  166.         D3DVal(D3DFMT_G16R16,34)
  167.         D3DVal(D3DFMT_A2R10G10B10,35)
  168.         D3DVal(D3DFMT_A16B16G16R16,36)
  169.  
  170.         D3DVal(D3DFMT_A8P8,40)
  171.         D3DVal(D3DFMT_P8,41)
  172.  
  173.         D3DVal(D3DFMT_L8,50)
  174.         D3DVal(D3DFMT_A8L8,51)
  175.         D3DVal(D3DFMT_A4L4,52)
  176.  
  177.         D3DVal(D3DFMT_V8U8,60)
  178.         D3DVal(D3DFMT_L6V5U5,61)
  179.         D3DVal(D3DFMT_X8L8V8U8,62)
  180.         D3DVal(D3DFMT_Q8W8V8U8,63)
  181.         D3DVal(D3DFMT_V16U16,64)
  182.         D3DVal(D3DFMT_A2W10V10U10,67)
  183.  
  184.         D3DVal(D3DFMT_UYVY,MAKEFOURCC('U', 'Y', 'V', 'Y'))
  185.         D3DVal(D3DFMT_R8G8_B8G8,MAKEFOURCC('R', 'G', 'B', 'G'))
  186.         D3DVal(D3DFMT_YUY2,MAKEFOURCC('Y', 'U', 'Y', '2'))
  187.         D3DVal(D3DFMT_G8R8_G8B8,MAKEFOURCC('G', 'R', 'G', 'B'))
  188.         D3DVal(D3DFMT_DXT1,MAKEFOURCC('D', 'X', 'T', '1'))
  189.         D3DVal(D3DFMT_DXT2,MAKEFOURCC('D', 'X', 'T', '2'))
  190.         D3DVal(D3DFMT_DXT3,MAKEFOURCC('D', 'X', 'T', '3'))
  191.         D3DVal(D3DFMT_DXT4,MAKEFOURCC('D', 'X', 'T', '4'))
  192.         D3DVal(D3DFMT_DXT5,MAKEFOURCC('D', 'X', 'T', '5'))
  193.  
  194.         D3DVal(D3DFMT_D16_LOCKABLE,70)
  195.         D3DVal(D3DFMT_D32,71)
  196.         D3DVal(D3DFMT_D15S1,73)
  197.         D3DVal(D3DFMT_D24S8,75)
  198.         D3DVal(D3DFMT_D24X8,77)
  199.         D3DVal(D3DFMT_D24X4S4,79)
  200.         D3DVal(D3DFMT_D16,80)
  201.  
  202.         D3DVal(D3DFMT_D32F_LOCKABLE,82)
  203.         D3DVal(D3DFMT_D24FS8,83)
  204.  
  205.         D3DVal(D3DFMT_L16,81)
  206.  
  207.         D3DVal(D3DFMT_VERTEXDATA,100)
  208.         D3DVal(D3DFMT_INDEX16,101)
  209.         D3DVal(D3DFMT_INDEX32,102)
  210.  
  211.         D3DVal(D3DFMT_Q16W16V16U16,110)
  212.  
  213.         D3DVal(D3DFMT_MULTI2_ARGB8,MAKEFOURCC('M','E','T','1'))
  214.  
  215.         D3DVal(D3DFMT_R16F,111)
  216.         D3DVal(D3DFMT_G16R16F,112)
  217.         D3DVal(D3DFMT_A16B16G16R16F,113)
  218.  
  219.         D3DVal(D3DFMT_R32F,114)
  220.         D3DVal(D3DFMT_G32R32F,115)
  221.         D3DVal(D3DFMT_A32B32G32R32F,116)
  222.  
  223.         D3DVal(D3DFMT_CxV8U8,117)
  224.     }
  225.  
  226.     puts("Invalid D3D9 Format!\n");
  227.     assert(false);
  228.     return "El3phant G0at";
  229. }
  230.  
  231. //NOTE: no 20!
  232. int GetDecodeSize(int nDecodeMethod)
  233. {
  234.     static int nPixelSizes[41] = {4,4,4,2,2,2,2,1,1,8,8,16,16,4,4,4,2,2,2,2,-1,4,3,1,4,8,16,2,6,8,4,2,4,2,4,4,4,4,2,8,4};
  235.     return nPixelSizes[nDecodeMethod];
  236. }
  237.  
  238. int DecodeTexPixelData(int nDecodeMethod, int nDecodeMethodEx, uint8_t* pDst, uint8_t* pSrc, size_t nDstSize, size_t nWidth, size_t nHeight, size_t nMipLevel, size_t nCalcPitch, size_t nTexPitch)
  239. {
  240.     //First Pass Decode
  241.     uint8_t* pBuffer = NULL;
  242.     if(nDecodeMethod <= 12 && nDecodeMethod >= 9)
  243.     {
  244.         size_t nPixels = ((nWidth >> nMipLevel) * (nHeight >> nMipLevel)) / 16;
  245.         int nPixelSize = GetDecodeSize(nDecodeMethod);
  246.         if(nPixelSize == -1)
  247.             return 0;
  248.  
  249.         size_t nSize = nPixels * nPixelSize;
  250.         pBuffer = (uint8_t*)malloc(nSize);
  251.         if(nPixelSize == 8)
  252.         {
  253.             uint32_t* pDest = (uint32_t*)pBuffer;
  254.             uint32_t* r = (uint32_t*)pSrc;
  255.             uint32_t* g = (uint32_t*)(pSrc + (nPixels * 4));
  256.             for(size_t i = nPixels; i != 0; i--)
  257.             {
  258.                 pDest[0] = *r++;
  259.                 pDest[1] = *g++;
  260.                 pDest += 2;
  261.             }
  262.         }
  263.         else
  264.         {
  265.             if(nDecodeMethod == 11)
  266.             {
  267.                 uint32_t* pDest = (uint32_t*)pBuffer;
  268.                 uint32_t* r = (uint32_t*)(pSrc + (nSize / 2));
  269.                 uint32_t* g = (uint32_t*)pSrc;
  270.                 uint32_t* b = (uint32_t*)(pSrc + ((nSize * 12) / 16));
  271.                 for(size_t i = nPixels; i != 0; i--)
  272.                 {
  273.                     pDest[0] = *g++;
  274.                     pDest[1] = *g++;
  275.                     pDest[2] = *r++;
  276.                     pDest[3] = *b++;
  277.                     pDest += 4;
  278.                 }
  279.             }
  280.             else
  281.             {
  282.                 uint16_t* pDest = (uint16_t*)pBuffer;
  283.                 uint16_t* r = (uint16_t*)(pSrc + (nSize / 8));
  284.                 uint32_t* g = (uint32_t*)(pSrc + (nSize / 2));
  285.                 uint32_t* b = (uint32_t*)(pSrc + ((nSize * 12) / 16));
  286.                 uint16_t* a = (uint16_t*)pSrc;
  287.                 for(size_t i = nPixels; i != 0; i--)
  288.                 {
  289.                     pDest[0] = *a++;
  290.                     pDest[1] = *r++;
  291.                     pDest[2] = *r++;
  292.                     pDest[3] = *r++;
  293.                     *(uint32_t*)(&pDest[4]) = *g++;
  294.                     *(uint32_t*)(&pDest[6]) = *b++;
  295.                     pDest += 8;
  296.                 }
  297.             }
  298.         }
  299.     }
  300.     else
  301.     {
  302.         pBuffer = (uint8_t*)malloc(nDstSize);
  303.         memcpy(pBuffer,pSrc,nDstSize);
  304.     }
  305.  
  306.     //Second Pass Decode
  307.     if(nDecodeMethod == nDecodeMethodEx)
  308.     {
  309.         if(nCalcPitch != nTexPitch)
  310.         {
  311.             size_t nPitch = nHeight >> nMipLevel;
  312.             if(nDecodeMethod > 12 && nDecodeMethod > 9)
  313.                 nPitch /= 4;
  314.  
  315.             uint8_t* pSource = pBuffer;
  316.             for(size_t i = nPitch; i != 0 ; i--)
  317.             {
  318.                 memcpy(pDst,pSource,nCalcPitch);
  319.                 pDst += nCalcPitch;
  320.                 pSource += nCalcPitch;
  321.             }
  322.         }
  323.         else
  324.         {
  325.             memcpy(pDst,pBuffer,nDstSize);
  326.             free(pBuffer);
  327.         }
  328.  
  329.         return 1;
  330.     }
  331.  
  332.     assert(false);
  333.     //alt second phase  not in yet
  334.  
  335.     return 1;
  336. }
  337.  
  338. int DecodeAtlasData(TexHeader* pFile, const char* szOutName)
  339. {
  340.     size_t nAtlas = pFile->dwAtlasEntries;
  341.     if(nAtlas < 1)
  342.     {
  343.         puts("file contains no atlas data!\n");
  344.         return 0;
  345.     }
  346.     else
  347.         printf("Dumping Atlas Data: %d Entries\n",nAtlas);
  348.  
  349.     char szName[512];
  350.     sprintf(szName,"%s_atlas.txt",szOutName);
  351.     FILE* pOut = fopen(szName,"w+");
  352.     fputs("Name\tXpos(f)\tYpos(f)\tXposEnd(f)\tYposEnd(t)\tXpos(i)\tYpos(i)\tXposEnd(i)\tYposEnd(i)\n",pOut);
  353.     float fWidth = (float)pFile->nWidth;
  354.     float fHeight = (float)pFile->nHeight;
  355.     TexAtlasEntry* pStart = (TexAtlasEntry*)((uint8_t*)pFile + pFile->dwAtlasOffset);
  356.     TexAtlasEntry* pEnd = pStart + nAtlas;
  357.     while(pStart < pEnd)
  358.     {
  359.         fprintf(pOut,"%s\t%f\t%f\t%f\t%f\t%u\t%u\t%u\t%u\n",pStart->szName,pStart->fXpos,pStart->fYpos,pStart->fXposEnd,pStart->fYposEnd,(int)(pStart->fXpos * fWidth),(int)(pStart->fYpos * fHeight),(int)(pStart->fXposEnd * fWidth),(int)(pStart->fYposEnd * fHeight));
  360.         pStart++;
  361.     }
  362.  
  363.     fclose(pOut);
  364.     return 1;
  365. }
  366.  
  367. int DecodeTexture(TexHeader* pFile, const char* szOutName)
  368. {
  369.     size_t nWidth = pFile->nWidth;
  370.     size_t nHeight = pFile->nHeight;
  371.     //there is a proper header decoder, I'm too lazy to implement atm...
  372.     size_t nPitch = nWidth * 4; //lame for now
  373.     size_t nFormat = pFile->dwPixelFormat;
  374.     size_t nMipLevels = pFile->nMipLevels;
  375.     int nD3DFormat = GetD3DTextureFormat(nFormat);
  376.     printf("Format: %s (0x%x) Width: %u Height: %u Mip Levels: %u\n",GetD3DFormatName(nD3DFormat),nD3DFormat,nWidth,nHeight,nMipLevels);
  377.     //system("pause");
  378.     if(nMipLevels > 1)
  379.     {
  380.         size_t nMipSize = 0;
  381.         for(size_t i = 0; i < nMipLevels; i++)
  382.         {
  383.             TexMipLevel* pMipLevel = &pFile->pMipLevels[i];
  384.             nMipSize += pMipLevel->dwDataSize;
  385.         }
  386.  
  387.         uint8_t* pPixelBuffer = (uint8_t*)malloc(nMipSize);
  388.         size_t nPosition = 0;
  389.         size_t nAddedMips = 0;
  390.         for(size_t i = 0; i < nMipLevels; i++)
  391.         {
  392.  
  393.             TexMipLevel* pMipLevel = &pFile->pMipLevels[i];
  394.             size_t nSize = pMipLevel->dwDataSize;
  395.             if(nSize > 0)
  396.             {
  397.                 uint8_t* pStart = (uint8_t*)pFile + pMipLevel->dwDataStart;
  398.                 uint8_t* pBuffer = (uint8_t*)malloc(nSize);
  399.                 DecodeTexPixelData(nFormat,nFormat,pBuffer,pStart,nSize,nWidth,nHeight,i,nPitch,nPitch);
  400.                 memcpy(&pPixelBuffer[nPosition],pBuffer,nSize);
  401.                 nPosition += nSize;
  402.                 free(pBuffer);
  403.                 nAddedMips++;
  404.             }
  405.         }
  406.  
  407.         if(!DDS_CreateFile(szOutName,pPixelBuffer,nMipSize,nWidth,nHeight,nD3DFormat,nAddedMips,nPitch))
  408.             printf("Failed to Save: %s Format: %s (0x%X)\n",szOutName,GetD3DFormatName(nD3DFormat),nD3DFormat);
  409.  
  410.         free(pPixelBuffer);
  411.     }
  412.     else
  413.     {
  414.         TexMipLevel* pMipLevel = &pFile->pMipLevels[0];
  415.         size_t nSize = pMipLevel->dwDataSize;
  416.         uint8_t* pStart = (uint8_t*)pFile + pMipLevel->dwDataStart;
  417.         uint8_t* pBuffer = (uint8_t*)malloc(nSize);
  418.         DecodeTexPixelData(nFormat,nFormat,pBuffer,pStart,nSize,nWidth,nHeight,0,nPitch,nPitch);
  419.         if(!DDS_CreateFile(szOutName,pBuffer,nSize,nWidth,nHeight,nD3DFormat,nMipLevels,nPitch))
  420.             printf("Failed to Save: %s Format: %s (0x%X)\n",szOutName,GetD3DFormatName(nD3DFormat),nD3DFormat);
  421.  
  422.         free(pBuffer);
  423.     }
  424.  
  425.     DecodeAtlasData(pFile,szOutName);
  426.     return 1;
  427. }
  428.  
  429. int DecodeCubeMap()
  430. {
  431.     return 0;
  432. }
  433.  
  434. void GetFileName(char* szOut, const char* szFile)
  435. {
  436.     const char* szDot = strrchr(szFile,'.');
  437.     const char* szSlash = strrchr(szFile,'/');
  438.     if(szSlash == NULL)
  439.         szSlash = strrchr(szFile,'\\');
  440.  
  441.     if(szSlash == NULL)
  442.     {
  443.         memcpy(szOut,szFile,szDot - szFile);
  444.         szOut[szDot - szFile] = '\0';
  445.     }
  446.     else
  447.     {
  448.         szSlash++;
  449.         memcpy(szOut,szSlash,szDot - szSlash);
  450.         szOut[szDot - szSlash] = '\0';
  451.     }
  452. }
  453.  
  454. int main(int argc, char* argv[])
  455. {
  456.     puts("D3TexConv v 0.9 (c) Necrolis 2011\n");
  457.     //needs a check to see if files exist
  458.     if(argc > 1)
  459.     {
  460.         printf("Processing %d Files...\n",argc - 1);
  461.         for(int i = 1; i < argc; i++)
  462.         {
  463.             char szOutName[512];
  464.             const char* szFile = argv[i];
  465.             if(szFile == NULL || *szFile == '\0')
  466.             {
  467.                 puts("Invalid File\n");
  468.                 continue;
  469.             }
  470.  
  471.             GetFileName(szOutName,szFile);
  472.             FILE* pFile = fopen(szFile,"rb+");
  473.             if(pFile == NULL)
  474.             {
  475.                 printf("Invalid File: %s\n",szFile);
  476.                 continue;
  477.             }
  478.  
  479.             printf("Opened File: %s\n",szFile);
  480.             fseek(pFile,0,SEEK_END);
  481.             size_t nSize = ftell(pFile);
  482.             rewind(pFile);
  483.             char* pBuffer = (char*)malloc(nSize);
  484.             fread(pBuffer,sizeof(char),nSize,pFile);
  485.             fclose(pFile);
  486.             printf("Processing File: %s Size: %u bytes\n",szOutName,nSize);
  487.             SNOHeader* pHeader = (SNOHeader*)pBuffer;
  488.             if(pHeader->dwMagic == SNO_MAGIC && (pHeader->dwSNOType == SNO_SURFACE || pHeader->dwSNOType == SNO_TEXTURE))
  489.                 DecodeTexture((TexHeader*)(pBuffer + sizeof(SNOHeader)),szOutName);
  490.             else
  491.                 puts("Invalid Texture or Surface (SNO Header Mismatch)\n");
  492.  
  493.             delete(pBuffer);
  494.         }
  495.     }
  496.     else
  497.         printf("We need a File(s) to work with!\n");
  498.  
  499.     system("pause");
  500.     return 0;
  501. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement