Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Author: Necrolis (www.d2mods.com)
- Credits: plash - for pointing out various things here and there (mainly the incorrect atlas names).
- Fiel & npd2006 - for giving me much needed testing feedback :)
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <assert.h>
- #include <stdint.h>
- #include <stddef.h>
- #include "DDSMake.h"
- /*
- Current Limitations:
- - No cubemaps, but it seems D3 doesn't use Tex files for cubemaps
- - Only DXTn Has been tested, no 2 phase files found yet!
- - Some decodes may come out weird due to my cheap stride/decode method stuff, need a test file for these too :)
- - Two Phase decoding is not done, this is the first thing on my list to add
- */
- enum eD3SNOTypes
- {
- SNO_MAGIC = 0xDEADBEEF,
- SNO_TEXTURE = 0x2D, // was 0x2C
- SNO_SURFACE = 0x2B,
- };
- struct SNOHeader //sizeof 0x10
- {
- uint32_t dwMagic; //+00 - 0xDEADBEEF
- uint32_t dwSNOType; //+04 - see 0x8148F0, 0x2B(Surface), 0x2C(Texture)
- uint32_t dwUnknown[2]; //+08 - probably prev/next links for runtime
- };
- struct TexMipLevel //sizeof 0x8
- {
- uint32_t dwDataStart; //+00
- uint32_t dwDataSize; //+04
- };
- struct TexHeader //sizeof 0x378
- {
- uint32_t dwUnk[3]; //+00 - NOT the SNO header!!!
- uint32_t fFlags; //+0C
- uint32_t dwPixelFormat; //+10 - Format of the Pixel Data ([9..12] do extra decoding, bound between 0 and 40)
- uint32_t nWidth; //+14
- uint32_t nHeight; //+18
- uint32_t nMipLevels; //+1C - this includes 0 sized mips too :O
- uint32_t nUnk6[2]; //+20
- TexMipLevel pMipLevels[31]; //+28
- uint32_t dwLoadType; //+124 - determines frame header size 0x10(1) or 0x14(0)
- uint32_t dwUnk2; //+128
- uint32_t dwPixelDataStart; //+12C - runtime only
- uint32_t dwUnk3[55]; //+130
- uint32_t dwAtlasEntries; //+208
- uint32_t dwAtlasOffset; //+20C
- uint32_t dwUnk7[13]; //+210
- void* pTexture; //+244 - runtime store of the texture pointer
- uint32_t nPool; //+248
- uint32_t dwUnk4; //+24C
- char szIFLName[256]; //+250
- uint32_t dwUnk5[10]; //+350
- //tex entries follow directly
- };
- struct TexEntry //sizeof 0x204
- {
- char szInternalName[256]; //+000
- char szFileName[256]; //+100
- uint32_t nEntryNumber; //+200
- };
- struct TexAtlasEntry //sizeof 0x50
- {
- char szName[64]; //+00
- float fXpos; //+40
- float fYpos; //+44
- float fXposEnd; //+48
- float fYposEnd; //+4C
- };
- int GetD3DTextureFormat(int nFormat)
- {
- if(nFormat > 40)
- {
- puts("Invalid Texture Format!\n");
- assert(false);
- }
- switch(nFormat)
- {
- case 0: return 21; //D3DFMT_A8R8G8B8
- case 1: return 0;
- case 2: return 22; //D3DFMT_X8R8G8B8
- case 3: return 26; //D3DFMT_A4R4G4B4
- case 4: return 25; //D3DFMT_A1R5G5B5
- case 5: return 24; //D3DFMT_X1R5G5B5
- case 6: return 23; //D3DFMT_R5G6B5
- case 7: return 50; //D3DFMT_L8
- case 8: return 0;
- case 9: return 0x31545844; //DXT1
- case 10: return 0x31545844; //DXT1
- case 11: return 0x33545844; //DXT3
- case 12: return 0x35545844; //DXT5
- case 13: return 0;
- case 14: return 0;
- case 15: return 0;
- case 16: return 0;
- case 17: return 0;
- case 18: return 0;
- case 19: return 0;
- case 20: return 0;
- case 21: return 32; //D3DFMT_A8B8G8R8
- case 22: return 0;
- case 23: return 28; //D3DFMT_A8
- case 24: return 114; //D3DFMT_R32F
- case 25: return 113; //D3DFMT_A16B16G16R16F
- case 26: return 116; //D3DFMT_A32B32G32R32F
- case 27: return 0;
- case 28: return 0;
- case 29: return 0;
- case 30: return 77; //D3DFMT_D24X8
- case 31: return 80; //D3DFMT_D16
- case 32: return 0x34324644; //DF24
- case 33: return 0x36314644; //DF26
- case 34: return 71; //D3DFMT_D32
- case 35: return 0x5A574152; //RAWZ
- case 36: return 0x5A544E49; //INTZ
- case 37: return 77; //D3DFMT_D24X8
- case 38: return 110; //D3DFMT_R16F
- case 39: return 115; //D3DFMT_G32R32F
- case 40: return 112; //D3DFMT_G16R16F
- }
- puts("Invalid Texture Format!\n");
- assert(false);
- return 0;
- }
- #define D3DVal(x,y) case y: return #x;
- const char* GetD3DFormatName(int nD3DFormat)
- {
- switch(nD3DFormat)
- {
- D3DVal(D3DFMT_UNKNOWN,0)
- D3DVal(D3DFMT_R8G8B8,20)
- D3DVal(D3DFMT_A8R8G8B8,21)
- D3DVal(D3DFMT_X8R8G8B8,22)
- D3DVal(D3DFMT_R5G6B5,23)
- D3DVal(D3DFMT_X1R5G5B5,24)
- D3DVal(D3DFMT_A1R5G5B5,25)
- D3DVal(D3DFMT_A4R4G4B4,26)
- D3DVal(D3DFMT_R3G3B2,27)
- D3DVal(D3DFMT_A8,28)
- D3DVal(D3DFMT_A8R3G3B2,29)
- D3DVal(D3DFMT_X4R4G4B4,30)
- D3DVal(D3DFMT_A2B10G10R10,31)
- D3DVal(D3DFMT_A8B8G8R8,32)
- D3DVal(D3DFMT_X8B8G8R8,33)
- D3DVal(D3DFMT_G16R16,34)
- D3DVal(D3DFMT_A2R10G10B10,35)
- D3DVal(D3DFMT_A16B16G16R16,36)
- D3DVal(D3DFMT_A8P8,40)
- D3DVal(D3DFMT_P8,41)
- D3DVal(D3DFMT_L8,50)
- D3DVal(D3DFMT_A8L8,51)
- D3DVal(D3DFMT_A4L4,52)
- D3DVal(D3DFMT_V8U8,60)
- D3DVal(D3DFMT_L6V5U5,61)
- D3DVal(D3DFMT_X8L8V8U8,62)
- D3DVal(D3DFMT_Q8W8V8U8,63)
- D3DVal(D3DFMT_V16U16,64)
- D3DVal(D3DFMT_A2W10V10U10,67)
- D3DVal(D3DFMT_UYVY,MAKEFOURCC('U', 'Y', 'V', 'Y'))
- D3DVal(D3DFMT_R8G8_B8G8,MAKEFOURCC('R', 'G', 'B', 'G'))
- D3DVal(D3DFMT_YUY2,MAKEFOURCC('Y', 'U', 'Y', '2'))
- D3DVal(D3DFMT_G8R8_G8B8,MAKEFOURCC('G', 'R', 'G', 'B'))
- D3DVal(D3DFMT_DXT1,MAKEFOURCC('D', 'X', 'T', '1'))
- D3DVal(D3DFMT_DXT2,MAKEFOURCC('D', 'X', 'T', '2'))
- D3DVal(D3DFMT_DXT3,MAKEFOURCC('D', 'X', 'T', '3'))
- D3DVal(D3DFMT_DXT4,MAKEFOURCC('D', 'X', 'T', '4'))
- D3DVal(D3DFMT_DXT5,MAKEFOURCC('D', 'X', 'T', '5'))
- D3DVal(D3DFMT_D16_LOCKABLE,70)
- D3DVal(D3DFMT_D32,71)
- D3DVal(D3DFMT_D15S1,73)
- D3DVal(D3DFMT_D24S8,75)
- D3DVal(D3DFMT_D24X8,77)
- D3DVal(D3DFMT_D24X4S4,79)
- D3DVal(D3DFMT_D16,80)
- D3DVal(D3DFMT_D32F_LOCKABLE,82)
- D3DVal(D3DFMT_D24FS8,83)
- D3DVal(D3DFMT_L16,81)
- D3DVal(D3DFMT_VERTEXDATA,100)
- D3DVal(D3DFMT_INDEX16,101)
- D3DVal(D3DFMT_INDEX32,102)
- D3DVal(D3DFMT_Q16W16V16U16,110)
- D3DVal(D3DFMT_MULTI2_ARGB8,MAKEFOURCC('M','E','T','1'))
- D3DVal(D3DFMT_R16F,111)
- D3DVal(D3DFMT_G16R16F,112)
- D3DVal(D3DFMT_A16B16G16R16F,113)
- D3DVal(D3DFMT_R32F,114)
- D3DVal(D3DFMT_G32R32F,115)
- D3DVal(D3DFMT_A32B32G32R32F,116)
- D3DVal(D3DFMT_CxV8U8,117)
- }
- puts("Invalid D3D9 Format!\n");
- assert(false);
- return "El3phant G0at";
- }
- //NOTE: no 20!
- int GetDecodeSize(int nDecodeMethod)
- {
- 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};
- return nPixelSizes[nDecodeMethod];
- }
- 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)
- {
- //First Pass Decode
- uint8_t* pBuffer = NULL;
- if(nDecodeMethod <= 12 && nDecodeMethod >= 9)
- {
- size_t nPixels = ((nWidth >> nMipLevel) * (nHeight >> nMipLevel)) / 16;
- int nPixelSize = GetDecodeSize(nDecodeMethod);
- if(nPixelSize == -1)
- return 0;
- size_t nSize = nPixels * nPixelSize;
- pBuffer = (uint8_t*)malloc(nSize);
- if(nPixelSize == 8)
- {
- uint32_t* pDest = (uint32_t*)pBuffer;
- uint32_t* r = (uint32_t*)pSrc;
- uint32_t* g = (uint32_t*)(pSrc + (nPixels * 4));
- for(size_t i = nPixels; i != 0; i--)
- {
- pDest[0] = *r++;
- pDest[1] = *g++;
- pDest += 2;
- }
- }
- else
- {
- if(nDecodeMethod == 11)
- {
- uint32_t* pDest = (uint32_t*)pBuffer;
- uint32_t* r = (uint32_t*)(pSrc + (nSize / 2));
- uint32_t* g = (uint32_t*)pSrc;
- uint32_t* b = (uint32_t*)(pSrc + ((nSize * 12) / 16));
- for(size_t i = nPixels; i != 0; i--)
- {
- pDest[0] = *g++;
- pDest[1] = *g++;
- pDest[2] = *r++;
- pDest[3] = *b++;
- pDest += 4;
- }
- }
- else
- {
- uint16_t* pDest = (uint16_t*)pBuffer;
- uint16_t* r = (uint16_t*)(pSrc + (nSize / 8));
- uint32_t* g = (uint32_t*)(pSrc + (nSize / 2));
- uint32_t* b = (uint32_t*)(pSrc + ((nSize * 12) / 16));
- uint16_t* a = (uint16_t*)pSrc;
- for(size_t i = nPixels; i != 0; i--)
- {
- pDest[0] = *a++;
- pDest[1] = *r++;
- pDest[2] = *r++;
- pDest[3] = *r++;
- *(uint32_t*)(&pDest[4]) = *g++;
- *(uint32_t*)(&pDest[6]) = *b++;
- pDest += 8;
- }
- }
- }
- }
- else
- {
- pBuffer = (uint8_t*)malloc(nDstSize);
- memcpy(pBuffer,pSrc,nDstSize);
- }
- //Second Pass Decode
- if(nDecodeMethod == nDecodeMethodEx)
- {
- if(nCalcPitch != nTexPitch)
- {
- size_t nPitch = nHeight >> nMipLevel;
- if(nDecodeMethod > 12 && nDecodeMethod > 9)
- nPitch /= 4;
- uint8_t* pSource = pBuffer;
- for(size_t i = nPitch; i != 0 ; i--)
- {
- memcpy(pDst,pSource,nCalcPitch);
- pDst += nCalcPitch;
- pSource += nCalcPitch;
- }
- }
- else
- {
- memcpy(pDst,pBuffer,nDstSize);
- free(pBuffer);
- }
- return 1;
- }
- assert(false);
- //alt second phase not in yet
- return 1;
- }
- int DecodeAtlasData(TexHeader* pFile, const char* szOutName)
- {
- size_t nAtlas = pFile->dwAtlasEntries;
- if(nAtlas < 1)
- {
- puts("file contains no atlas data!\n");
- return 0;
- }
- else
- printf("Dumping Atlas Data: %d Entries\n",nAtlas);
- char szName[512];
- sprintf(szName,"%s_atlas.txt",szOutName);
- FILE* pOut = fopen(szName,"w+");
- fputs("Name\tXpos(f)\tYpos(f)\tXposEnd(f)\tYposEnd(t)\tXpos(i)\tYpos(i)\tXposEnd(i)\tYposEnd(i)\n",pOut);
- float fWidth = (float)pFile->nWidth;
- float fHeight = (float)pFile->nHeight;
- TexAtlasEntry* pStart = (TexAtlasEntry*)((uint8_t*)pFile + pFile->dwAtlasOffset);
- TexAtlasEntry* pEnd = pStart + nAtlas;
- while(pStart < pEnd)
- {
- 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));
- pStart++;
- }
- fclose(pOut);
- return 1;
- }
- int DecodeTexture(TexHeader* pFile, const char* szOutName)
- {
- size_t nWidth = pFile->nWidth;
- size_t nHeight = pFile->nHeight;
- //there is a proper header decoder, I'm too lazy to implement atm...
- size_t nPitch = nWidth * 4; //lame for now
- size_t nFormat = pFile->dwPixelFormat;
- size_t nMipLevels = pFile->nMipLevels;
- int nD3DFormat = GetD3DTextureFormat(nFormat);
- printf("Format: %s (0x%x) Width: %u Height: %u Mip Levels: %u\n",GetD3DFormatName(nD3DFormat),nD3DFormat,nWidth,nHeight,nMipLevels);
- //system("pause");
- if(nMipLevels > 1)
- {
- size_t nMipSize = 0;
- for(size_t i = 0; i < nMipLevels; i++)
- {
- TexMipLevel* pMipLevel = &pFile->pMipLevels[i];
- nMipSize += pMipLevel->dwDataSize;
- }
- uint8_t* pPixelBuffer = (uint8_t*)malloc(nMipSize);
- size_t nPosition = 0;
- size_t nAddedMips = 0;
- for(size_t i = 0; i < nMipLevels; i++)
- {
- TexMipLevel* pMipLevel = &pFile->pMipLevels[i];
- size_t nSize = pMipLevel->dwDataSize;
- if(nSize > 0)
- {
- uint8_t* pStart = (uint8_t*)pFile + pMipLevel->dwDataStart;
- uint8_t* pBuffer = (uint8_t*)malloc(nSize);
- DecodeTexPixelData(nFormat,nFormat,pBuffer,pStart,nSize,nWidth,nHeight,i,nPitch,nPitch);
- memcpy(&pPixelBuffer[nPosition],pBuffer,nSize);
- nPosition += nSize;
- free(pBuffer);
- nAddedMips++;
- }
- }
- if(!DDS_CreateFile(szOutName,pPixelBuffer,nMipSize,nWidth,nHeight,nD3DFormat,nAddedMips,nPitch))
- printf("Failed to Save: %s Format: %s (0x%X)\n",szOutName,GetD3DFormatName(nD3DFormat),nD3DFormat);
- free(pPixelBuffer);
- }
- else
- {
- TexMipLevel* pMipLevel = &pFile->pMipLevels[0];
- size_t nSize = pMipLevel->dwDataSize;
- uint8_t* pStart = (uint8_t*)pFile + pMipLevel->dwDataStart;
- uint8_t* pBuffer = (uint8_t*)malloc(nSize);
- DecodeTexPixelData(nFormat,nFormat,pBuffer,pStart,nSize,nWidth,nHeight,0,nPitch,nPitch);
- if(!DDS_CreateFile(szOutName,pBuffer,nSize,nWidth,nHeight,nD3DFormat,nMipLevels,nPitch))
- printf("Failed to Save: %s Format: %s (0x%X)\n",szOutName,GetD3DFormatName(nD3DFormat),nD3DFormat);
- free(pBuffer);
- }
- DecodeAtlasData(pFile,szOutName);
- return 1;
- }
- int DecodeCubeMap()
- {
- return 0;
- }
- void GetFileName(char* szOut, const char* szFile)
- {
- const char* szDot = strrchr(szFile,'.');
- const char* szSlash = strrchr(szFile,'/');
- if(szSlash == NULL)
- szSlash = strrchr(szFile,'\\');
- if(szSlash == NULL)
- {
- memcpy(szOut,szFile,szDot - szFile);
- szOut[szDot - szFile] = '\0';
- }
- else
- {
- szSlash++;
- memcpy(szOut,szSlash,szDot - szSlash);
- szOut[szDot - szSlash] = '\0';
- }
- }
- int main(int argc, char* argv[])
- {
- puts("D3TexConv v 0.9 (c) Necrolis 2011\n");
- //needs a check to see if files exist
- if(argc > 1)
- {
- printf("Processing %d Files...\n",argc - 1);
- for(int i = 1; i < argc; i++)
- {
- char szOutName[512];
- const char* szFile = argv[i];
- if(szFile == NULL || *szFile == '\0')
- {
- puts("Invalid File\n");
- continue;
- }
- GetFileName(szOutName,szFile);
- FILE* pFile = fopen(szFile,"rb+");
- if(pFile == NULL)
- {
- printf("Invalid File: %s\n",szFile);
- continue;
- }
- printf("Opened File: %s\n",szFile);
- fseek(pFile,0,SEEK_END);
- size_t nSize = ftell(pFile);
- rewind(pFile);
- char* pBuffer = (char*)malloc(nSize);
- fread(pBuffer,sizeof(char),nSize,pFile);
- fclose(pFile);
- printf("Processing File: %s Size: %u bytes\n",szOutName,nSize);
- SNOHeader* pHeader = (SNOHeader*)pBuffer;
- if(pHeader->dwMagic == SNO_MAGIC && (pHeader->dwSNOType == SNO_SURFACE || pHeader->dwSNOType == SNO_TEXTURE))
- DecodeTexture((TexHeader*)(pBuffer + sizeof(SNOHeader)),szOutName);
- else
- puts("Invalid Texture or Surface (SNO Header Mismatch)\n");
- delete(pBuffer);
- }
- }
- else
- printf("We need a File(s) to work with!\n");
- system("pause");
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement