387 lines
8.6 KiB
C++
387 lines
8.6 KiB
C++
// TexPostCook360.cpp : Defines the entry point for the console application.
|
|
//
|
|
|
|
#define _CRT_SECURE_NO_WARNINGS
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <iostream>
|
|
#include <fstream>
|
|
|
|
//#include "d3d9.h"
|
|
#include "d3dx9.h"
|
|
#include "xgraphics.h"
|
|
|
|
using namespace std;
|
|
|
|
//char strSourceFileName[256];
|
|
const char *strSourceFileName = 0;
|
|
const char *strDstFileName = 0;
|
|
|
|
typedef unsigned char u8;
|
|
typedef unsigned short u16;
|
|
typedef unsigned long u32;
|
|
|
|
struct DDSCAPS2
|
|
{
|
|
DWORD dwCaps;
|
|
DWORD dwCaps2;
|
|
DWORD Reserved[2];
|
|
};
|
|
|
|
struct DDPIXELFORMAT
|
|
{
|
|
DWORD dwSize;
|
|
DWORD dwFlags;
|
|
DWORD dwFourCC;
|
|
DWORD dwRGBBitCount;
|
|
DWORD dwRBitMask;
|
|
DWORD dwGBitMaskDWORD;
|
|
DWORD dwBBitMask;
|
|
DWORD dwRGBAlphaBitMask;
|
|
};
|
|
|
|
struct DDS_HEADER
|
|
{
|
|
DWORD dwMagic;
|
|
DWORD dwSize;
|
|
DWORD dwFlags;
|
|
DWORD dwHeight;
|
|
DWORD dwWidth;
|
|
DWORD dwPitchOrLinearSize;
|
|
DWORD dwDepth;
|
|
DWORD dwMipMapCount;
|
|
|
|
DWORD dwReserved1[11];
|
|
|
|
DDPIXELFORMAT format;
|
|
DDSCAPS2 ddsCaps;
|
|
DWORD dwReserved2;
|
|
};
|
|
|
|
/*
|
|
enum PixFormat
|
|
{
|
|
//! Each pixel is 3 bytes. RGB in that order.
|
|
PF_RGB,
|
|
//! Each pixel is 4 bytes. RGBA in that order.
|
|
PF_RGBA,
|
|
|
|
PF_DXT1,
|
|
PF_DXT2,
|
|
PF_DXT3,
|
|
PF_DXT4,
|
|
PF_DXT5,
|
|
|
|
PF_RGB_NATIVE_CTR,
|
|
PF_RGBA_NATIVE_CTR,
|
|
PF_ETC1_CTR,
|
|
PF_ETC1_A4_CTR,
|
|
|
|
PF_CMPA, // WII : DXT1 for RGB + DXT1 for Alpha
|
|
PF_L8,
|
|
PF_LA8,
|
|
PF_A8
|
|
};
|
|
*/
|
|
void copyfile(const char * Dst, const char *Src)
|
|
{
|
|
FILE* psrc = fopen(Src,"rb");
|
|
if(!psrc)
|
|
return;
|
|
fseek(psrc, 0, SEEK_END);
|
|
size_t len = ftell(psrc);
|
|
void *buff = malloc(len);
|
|
fseek(psrc, 0, SEEK_SET);
|
|
fread(buff, len, 1, psrc);
|
|
fclose(psrc);
|
|
|
|
//endianess(buff, buff, len);
|
|
|
|
FILE* pdst = fopen(Dst,"wb");
|
|
if(pdst)
|
|
{
|
|
fwrite(buff, len, 1, pdst);
|
|
fclose(pdst);
|
|
}
|
|
free(buff);
|
|
}
|
|
|
|
int ProcessFile()
|
|
{
|
|
FILE *pf = fopen(strSourceFileName, "rb");
|
|
//FILE *pf = fopen("cooking.dds", "rb");
|
|
if(!pf)
|
|
{
|
|
cerr << "Can't open input file '" << strSourceFileName << "'" << endl;
|
|
return -2;
|
|
}
|
|
|
|
fseek(pf, 0, SEEK_END);
|
|
unsigned int flen = ftell(pf);
|
|
fseek(pf, 0, SEEK_SET);
|
|
|
|
u8* rawBuf = (unsigned char *) malloc(flen);
|
|
|
|
if(fread(rawBuf, flen, 1, pf) != 1)
|
|
{
|
|
cerr << " Can't read input file '" << strSourceFileName << "'. " << endl;
|
|
fclose(pf);
|
|
return -3;
|
|
}
|
|
|
|
fclose(pf);
|
|
|
|
DDS_HEADER header;
|
|
u32 gb_Endiannes = memcmp(&rawBuf, "DDS ", 4) != 0;
|
|
memcpy(&header, rawBuf, sizeof(DDS_HEADER));
|
|
|
|
/*
|
|
//PixFormat pixFormat;
|
|
D3DFORMAT pixFormat;
|
|
|
|
switch (header.format.dwFourCC)
|
|
{
|
|
case MAKEFOURCC('D', 'X', 'T', '1'):
|
|
pixFormat = D3DFMT_DXT1;//PixFormat::PF_DXT1;
|
|
break;
|
|
case MAKEFOURCC('D', 'X', 'T', '2'):
|
|
pixFormat = D3DFMT_DXT2;//PixFormat::PF_DXT2;
|
|
break;
|
|
case MAKEFOURCC('D', 'X', 'T', '3'):
|
|
pixFormat = D3DFMT_DXT3;//PixFormat::PF_DXT3;
|
|
break;
|
|
case MAKEFOURCC('D', 'X', 'T', '4'):
|
|
pixFormat = D3DFMT_DXT4;//PixFormat::PF_DXT4;
|
|
break;
|
|
case MAKEFOURCC('D', 'X', 'T', '5'):
|
|
pixFormat = D3DFMT_DXT5;//PixFormat::PF_DXT5;
|
|
break;
|
|
default:
|
|
pixFormat = D3DFMT_A8B8G8R8;//PixFormat::PF_RGBA;
|
|
break;
|
|
}
|
|
*/
|
|
|
|
u8 *mipData = rawBuf + /*sizeof(u32) +*/ sizeof(DDS_HEADER);
|
|
|
|
D3DXIMAGE_INFO imageInfo;
|
|
D3DXGetImageInfoFromFileInMemory(rawBuf, flen, &imageInfo);
|
|
D3DFORMAT targetFormat = (D3DFORMAT)( imageInfo.Format | D3DFORMAT_TILED_MASK );
|
|
|
|
u32 swapStride = 0;
|
|
XGENDIANTYPE swapType = XGENDIAN_NONE;
|
|
if( imageInfo.Format == D3DFMT_LIN_DXT1 || imageInfo.Format == D3DFMT_LIN_DXT2 || imageInfo.Format == D3DFMT_LIN_DXT3 || imageInfo.Format == D3DFMT_LIN_DXT4 || imageInfo.Format == D3DFMT_LIN_DXT5 )
|
|
{
|
|
swapStride = 2;
|
|
swapType = XGENDIAN_8IN16;
|
|
}
|
|
else if( imageInfo.Format == D3DFMT_LIN_A8R8G8B8 || imageInfo.Format == D3DFMT_LIN_X8R8G8B8 || imageInfo.Format == D3DFMT_LIN_G16R16 )
|
|
{
|
|
swapStride = 4;
|
|
swapType = XGENDIAN_8IN32;
|
|
}
|
|
else
|
|
{
|
|
return -12;
|
|
}
|
|
|
|
// Create texture
|
|
D3DBaseTexture textureHeader;
|
|
u32 baseSize;
|
|
u32 mipSize;
|
|
|
|
XGSetTextureHeaderEx
|
|
(
|
|
imageInfo.Width,
|
|
imageInfo.Height,
|
|
imageInfo.MipLevels,
|
|
0,
|
|
targetFormat,
|
|
0,
|
|
0,
|
|
0,
|
|
XGHEADER_CONTIGUOUS_MIP_OFFSET,
|
|
0,
|
|
( D3DTexture* )&textureHeader,
|
|
(UINT*)&baseSize,
|
|
(UINT*)&mipSize
|
|
);
|
|
|
|
// Create a buffer to hold the texture data.
|
|
u8* buffer = (u8*)malloc( ( baseSize + mipSize) * sizeof(u8) );
|
|
memset(buffer, 0, baseSize + mipSize);
|
|
|
|
XGTEXTURE_DESC baseDesc;
|
|
XGGetTextureDesc( &textureHeader, 0, &baseDesc );
|
|
bool tiled = XGIsTiledFormat( (D3DFORMAT)baseDesc.Format );
|
|
if(!tiled)
|
|
{
|
|
free(buffer);
|
|
return -11;
|
|
}
|
|
|
|
// Convert every mip level
|
|
for( u32 levelIndex = 0; levelIndex < imageInfo.MipLevels; levelIndex++ )
|
|
{
|
|
// Get the description of the current mip level.
|
|
XGTEXTURE_DESC MipDesc;
|
|
XGGetTextureDesc( &textureHeader, levelIndex, &MipDesc );
|
|
|
|
u32 mipMapDataSize = MipDesc.WidthInBlocks * MipDesc.BytesPerBlock * MipDesc.HeightInBlocks;
|
|
u32 rowStride = MipDesc.WidthInBlocks * MipDesc.BytesPerBlock;
|
|
|
|
// Perform the endian-swap in-place on the image data...
|
|
XGEndianSwapMemory
|
|
(
|
|
mipData,
|
|
mipData,
|
|
swapType,
|
|
swapStride,
|
|
mipMapDataSize / swapStride
|
|
);
|
|
|
|
// Get the mip level offset within our buffer.
|
|
DWORD mipLevelOffset = XGGetMipLevelOffset( &textureHeader, 0, levelIndex );
|
|
if( ( levelIndex > 0 ) && ( mipSize > 0 ) )
|
|
{
|
|
mipLevelOffset += baseSize;
|
|
}
|
|
|
|
// Tile.
|
|
XGTileTextureLevel
|
|
(
|
|
baseDesc.Width,
|
|
baseDesc.Height,
|
|
levelIndex,
|
|
XGGetGpuFormat(targetFormat),
|
|
0,
|
|
buffer + mipLevelOffset,
|
|
NULL,
|
|
mipData,
|
|
rowStride,
|
|
NULL
|
|
);
|
|
|
|
// Skip to the next mipmap
|
|
mipData += mipMapDataSize;
|
|
}
|
|
|
|
free(rawBuf);
|
|
|
|
// Endian swap the texture header
|
|
XGEndianSwapMemory
|
|
(
|
|
&textureHeader,
|
|
&textureHeader,
|
|
XGENDIAN_8IN32,
|
|
sizeof(DWORD),
|
|
sizeof(textureHeader) / sizeof(DWORD)
|
|
);
|
|
|
|
pf = fopen(strDstFileName, "wb");
|
|
if(!pf)
|
|
{
|
|
cerr << "Can't open output file '" << strDstFileName << "'" << endl;
|
|
free(buffer);
|
|
return -6;
|
|
}
|
|
|
|
if(fwrite(&textureHeader, sizeof(textureHeader), 1, pf) != 1)
|
|
{
|
|
cerr << "Can't write output file '" << strDstFileName << "'" << endl;
|
|
fclose(pf);
|
|
free(buffer);
|
|
return -7;
|
|
}
|
|
if(fwrite(buffer, baseSize + mipSize, 1, pf) != 1)
|
|
{
|
|
cerr << "Can't write output file '" << strDstFileName << "'" << endl;
|
|
fclose(pf);
|
|
free(buffer);
|
|
return -8;
|
|
}
|
|
|
|
fclose(pf);
|
|
|
|
free(buffer);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void help()
|
|
{
|
|
printf("TexConvertForXbox version 1.0\n");
|
|
printf("Args:\n"
|
|
" -i inputfilename\n"
|
|
" -o outputfilename\n"
|
|
" -h display this help text\n"
|
|
);
|
|
}
|
|
|
|
void ProcessCommandLigne(int argc, char* argv[])
|
|
{
|
|
if(argc < 3)
|
|
{
|
|
help();
|
|
exit(-1);
|
|
}
|
|
|
|
for(int i = 1; i < argc; ++i)
|
|
{
|
|
if( (argv[i][0] != '-') && (argv[i][0] != '/') )
|
|
{
|
|
cerr << "Error on parameter \""<<argv[i]<<"\""<<endl<<endl;
|
|
help();
|
|
exit(-1);
|
|
return;
|
|
}
|
|
|
|
if (_stricmp(&argv[i][1], "i")==0)
|
|
{
|
|
strSourceFileName = argv[++i];
|
|
continue;
|
|
}
|
|
else if(_stricmp(&argv[i][1], "o")==0)
|
|
{
|
|
strDstFileName = argv[++i];
|
|
continue;
|
|
}
|
|
else if(_stricmp(&argv[i][1], "h")==0)
|
|
{
|
|
help();
|
|
exit(0);
|
|
return;
|
|
}
|
|
else if(_stricmp(&argv[i][1], "?")==0)
|
|
{
|
|
help();
|
|
exit(0);
|
|
return;
|
|
}
|
|
else if(_stricmp(&argv[i][1], "?")==0)
|
|
{
|
|
cerr << "Error on parameter \""<<argv[i]<<"\""<<endl<<endl;
|
|
help();
|
|
exit(-1);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
ProcessCommandLigne(argc, argv);
|
|
|
|
int ret = ProcessFile();
|
|
_fcloseall();
|
|
|
|
if(ret < 0)
|
|
copyfile(strDstFileName, strSourceFileName);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|