// TexPostCookWii.cpp : Defines the entry point for the console application. // #define _CRT_SECURE_NO_WARNINGS #include "stdafx.h" #include #include #include #include "./Squish/Squish.h" //#include #include using namespace std; const char *strSourceFileName = 0; const char *strDstFileName = 0; bool g_rgbaNoCompressed = false; typedef unsigned char u8; typedef unsigned short u16; typedef unsigned long u32; struct ITF_DDSCAPS2 { DWORD dwCaps; DWORD dwCaps2; DWORD Reserved[2]; }; struct ITF_DDPIXELFORMAT { DWORD dwSize; DWORD dwFlags; DWORD dwFourCC; DWORD dwRGBBitCount; DWORD dwRBitMask; DWORD dwGBitMaskDWORD; DWORD dwBBitMask; DWORD dwRGBAlphaBitMask; }; struct ITF_DDS_USER { DWORD dwLodBias; DWORD dwAlphaBias; DWORD dwbHasOneColor; DWORD dwAnisotropy; DWORD dwIntensityAlpha; DWORD dwReserved[6]; }; struct ITF_DDS_HEADER { DWORD dwMagic; DWORD dwSize; DWORD dwFlags; DWORD dwHeight; DWORD dwWidth; DWORD dwPitchOrLinearSize; DWORD dwDepth; DWORD dwMipMapCount; union { ITF_DDS_USER dwUser; DWORD dwReserved1[11]; }; ITF_DDPIXELFORMAT format; ITF_DDSCAPS2 ddsCaps; DWORD dwReserved2; }; bool gb_Endiannes = false; inline void endianess32(void *dst, const void *src) { unsigned long *q = (unsigned long *)dst; unsigned long i = *(unsigned long *)src; *q = (i>>24) | (i&0x00ff0000)>>8 | (i&0x0000ff00)<<8 | (i&0x000000ff)<<24; } void endianess(void *dst, const void *src, unsigned int size) { char *p = (char*)dst; char *q = (char*)src; for(unsigned int i = 0; i < size; i+=4, p+=4, q+=4) endianess32(p,q); } bool bRGBACheckTransp(const unsigned char *src, unsigned int _w, unsigned int _h) { if(!gb_Endiannes) src+=3; for(unsigned int i = 0; i < _w*_h; i++, src+=4) { if((*src != 0xff) && (*src != 0x0)) return true; } return false; } 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); } extern void GDK_images_TileDXTForWii(void *_pv_DestImg, void *_pv_SrcImg, u32 _u32_Width, u32 _u32_Height); extern void GDK_images_TileRawBufferForWiiI8(void * _pv_DestImg, void * _pv_SrcImg, u32 _u32_Width, u32 _u32_Height); extern void GDK_images_TileRawBufferForWiiI8A8(void * _pv_DestImg, void * _pv_SrcImg, u32 _u32_Width, u32 _u32_Height); extern void GDK_images_TileForWii(void *_pv_DestImg, const void *_pv_SrcImg, u32 _u32_Width, u32 _u32_Height, u32 _u32_BPP); unsigned char *workingBuff1 = 0; unsigned char *workingBuff2 = 0; void copyRGBAfile(const char *Dst, FILE *_pf_SrcFile, ITF_DDS_HEADER *_header, unsigned int flen) { if(!_pf_SrcFile) return; FILE* pdst = fopen(Dst,"wb"); if(!pdst) { fclose(_pf_SrcFile); return; } unsigned int bufsize = flen - sizeof(ITF_DDS_HEADER); void *src_rgba = malloc(bufsize); fread(src_rgba, bufsize, 1, _pf_SrcFile); fclose(_pf_SrcFile); ITF_DDS_HEADER headerfile; endianess(&headerfile, _header, sizeof(ITF_DDS_HEADER)); if(fwrite(&headerfile, sizeof(ITF_DDS_HEADER), 1, pdst) != 1) { cerr << "Can't write output file '" << Dst << "'" << endl; fclose(pdst); return; } endianess(src_rgba, src_rgba, bufsize); fwrite(src_rgba, bufsize, 1, pdst); fclose(pdst); free(src_rgba); } void processRGBAfile(const char *Dst, FILE *_pf_SrcFile, ITF_DDS_HEADER *_header, unsigned int flen) { if(!_pf_SrcFile) return; FILE* pdst = fopen(Dst,"wb"); if(!pdst) { fclose(_pf_SrcFile); return; } unsigned int bufsize = flen - sizeof(ITF_DDS_HEADER); void *src_rgba = malloc(bufsize); fread(src_rgba, bufsize, 1, _pf_SrcFile); fclose(_pf_SrcFile); int mipmapcount = 0; int w = _header->dwWidth; int h = _header->dwHeight; while(1) { if((w<=8) || (h<=8)) // minimum square size break; mipmapcount++; if(mipmapcount==10) // Max LOD on Wii break; w = w>>1; h = h>>1; } if((int)_header->dwMipMapCount > mipmapcount) _header->dwMipMapCount = (DWORD) mipmapcount; ITF_DDS_HEADER headerfile; endianess(&headerfile, _header, sizeof(ITF_DDS_HEADER)); if(fwrite(&headerfile, sizeof(ITF_DDS_HEADER), 1, pdst) != 1) { cerr << "Can't write output file '" << Dst << "'" << endl; fclose(pdst); return; } w = _header->dwWidth; h = _header->dwHeight; mipmapcount = _header->dwMipMapCount; workingBuff1 = (unsigned char *) src_rgba; workingBuff2 = (unsigned char *) malloc(h*w*4); if(gb_Endiannes) endianess(workingBuff1, workingBuff1, bufsize); do { GDK_images_TileForWii(workingBuff2, workingBuff1, w, h, 32); fwrite(workingBuff2, h*w*4, 1, pdst); workingBuff1 += (h*w*4); w >>= 1; h >>= 1; }while(--mipmapcount >= 0); fclose(pdst); workingBuff1 = 0; free(workingBuff2); free(src_rgba); } void copyDXT1file(const char *Dst, FILE *_pf_SrcFile, ITF_DDS_HEADER *_header, unsigned int flen) { if(!_pf_SrcFile) return; FILE* pdst = fopen(Dst,"wb"); if(!pdst) { fclose(_pf_SrcFile); return; } unsigned int bufsize = flen - sizeof(ITF_DDS_HEADER); void *src_dxt1 = malloc(bufsize); fread(src_dxt1, bufsize, 1, _pf_SrcFile); fclose(_pf_SrcFile); int mipmapcount = 0; int w = _header->dwWidth; int h = _header->dwHeight; while(1) { if((w<=8) || (h<=8)) // minimum square size break; mipmapcount++; if(mipmapcount==10) // Max LOD on Wii break; w = w>>1; h = h>>1; } if((int)_header->dwMipMapCount > mipmapcount) _header->dwMipMapCount = (DWORD) mipmapcount; ITF_DDS_HEADER headerfile; endianess(&headerfile, _header, sizeof(ITF_DDS_HEADER)); if(fwrite(&headerfile, sizeof(ITF_DDS_HEADER), 1, pdst) != 1) { cerr << "Can't write output file '" << Dst << "'" << endl; fclose(pdst); return; } w = _header->dwWidth; h = _header->dwHeight; mipmapcount = _header->dwMipMapCount; workingBuff1 = (unsigned char *) src_dxt1; workingBuff2 = (unsigned char *) malloc(h*w/2); if(gb_Endiannes) endianess(workingBuff1, workingBuff1, bufsize); do { GDK_images_TileDXTForWii(workingBuff2, workingBuff1, w, h); fwrite(workingBuff2, h*w/2, 1, pdst); workingBuff1 += (h*w/2); w >>= 1; h >>= 1; }while(--mipmapcount >= 0); fclose(pdst); workingBuff1 = 0; free(workingBuff2); free(src_dxt1); } void ProcessBufferRGB(unsigned char * _rgba, unsigned int _w, unsigned int _h, unsigned char* _aaa, FILE *_pf) { unsigned c; for(unsigned int i = 0; i < _h*_w; ++i) { unsigned char *rgba = _rgba+i*4; if(gb_Endiannes) endianess32(rgba, rgba); c = *rgba; *rgba = rgba[2]; rgba[2] = c; // invert RB if(_aaa) {// fill alpha buffer unsigned char *p = rgba+3; unsigned char *q = _aaa+i*4; q[0] = *p; q[1] = *p; q[2] = *p; q[3] = 0xff; *p = 0xff; } } squish::CompressImage(_rgba, _w, _h, workingBuff1, squish::kDxt1); GDK_images_TileDXTForWii(workingBuff2, workingBuff1, _w, _h); fwrite(workingBuff2, _h*_w/2, 1, _pf); } void ProcessBufferAlpha(unsigned char * _aaa, unsigned int _w, unsigned int _h, FILE *_pf) { squish::CompressImage(_aaa, _w, _h, workingBuff1, squish::kDxt1); GDK_images_TileDXTForWii(workingBuff2, workingBuff1, _w, _h); fwrite(workingBuff2, _h*_w/2, 1, _pf); } void ProcessBufferRGBAForLuminance(unsigned char * _rgba, unsigned int _w, unsigned int _h, FILE *_pf, u32 _ps) { for(unsigned int i = 0; i < _w*_h; ++i) { workingBuff2[i] = _rgba[i*_ps+2]; } GDK_images_TileRawBufferForWiiI8(_rgba, workingBuff2, _w, _h); //endianess(_rgba, _rgba, _h*_w); fwrite(_rgba, _h*_w, 1, _pf); } void ProcessBufferRGBAForLuminanceAlpha(unsigned char * _rgba, unsigned int _w, unsigned int _h, FILE *_pf, u32 _ps) { for(unsigned int i = 0; i < _w*_h; ++i) { workingBuff2[i*2+1] = _rgba[i*_ps+0]; workingBuff2[i*2+0] = _rgba[i*_ps+(_ps-1)]; } GDK_images_TileRawBufferForWiiI8A8(_rgba, workingBuff2, _w, _h); //endianess(_rgba, _rgba, _h*_w*2); fwrite(_rgba, _h*_w*2, 1, _pf); } void copyLuminancefile(const char *Dst, FILE *_pf_SrcFile, ITF_DDS_HEADER *_header, unsigned int flen) { if(!_pf_SrcFile) return; FILE* pdst = fopen(Dst,"wb"); if(!pdst) { fclose(_pf_SrcFile); return; } unsigned int bufsize = flen - sizeof(ITF_DDS_HEADER); void *src_rgba = malloc(bufsize); fread(src_rgba, bufsize, 1, _pf_SrcFile); fclose(_pf_SrcFile); if((_header->format.dwFlags & DDPF_LUMINANCE) != DDPF_LUMINANCE) { cerr << "Invalid input file '" << endl; fclose(pdst); free(src_rgba); return; } int src_ps = _header->format.dwRGBBitCount >> 3; //source pixel size _header->format.dwFourCC = MAKEFOURCC('L', '8', '0', '0'); _header->format.dwFlags = DDPF_LUMINANCE; _header->format.dwRGBBitCount = 8; _header->format.dwRBitMask = 0x00ff; _header->format.dwGBitMaskDWORD = 0x0000; _header->format.dwBBitMask = 0x0000; _header->format.dwRGBAlphaBitMask = 0x0000; ITF_DDS_HEADER headerfile; endianess(&headerfile, _header, sizeof(ITF_DDS_HEADER)); if(fwrite(&headerfile, sizeof(ITF_DDS_HEADER), 1, pdst) != 1) { cerr << "Can't write output file '" << Dst << "'" << endl; fclose(pdst); free(src_rgba); return; } int mipmapcount = 0; int w = _header->dwWidth; int h = _header->dwHeight; while(1) { if((w<=8) || (h<=8)) // minimum square size break; mipmapcount++; if(mipmapcount==10) // Max LOD on Wii break; w = w>>1; h = h>>1; } if((int)_header->dwMipMapCount > mipmapcount) _header->dwMipMapCount = (DWORD) mipmapcount; w = _header->dwWidth; h = _header->dwHeight; mipmapcount = _header->dwMipMapCount; workingBuff1 = (unsigned char *) src_rgba; workingBuff2 = (unsigned char *) malloc(h*w*2); if(gb_Endiannes) endianess(workingBuff1, workingBuff1, bufsize); do { ProcessBufferRGBAForLuminance(workingBuff1, w, h, pdst, src_ps); workingBuff1 += (h*w*src_ps); w >>= 1; h >>= 1; }while(--mipmapcount >= 0); fclose(pdst); free(workingBuff2); workingBuff2 = 0; free(src_rgba); workingBuff1 = 0; } void copyLuminanceAlphafile(const char *Dst, FILE *_pf_SrcFile, ITF_DDS_HEADER *_header, unsigned int flen) { if(!_pf_SrcFile) return; FILE* pdst = fopen(Dst,"wb"); if(!pdst) { fclose(_pf_SrcFile); return; } unsigned int bufsize = flen - sizeof(ITF_DDS_HEADER); void *src_rgba = malloc(bufsize); fread(src_rgba, bufsize, 1, _pf_SrcFile); fclose(_pf_SrcFile); if((_header->format.dwFlags & (DDPF_LUMINANCE | DDPF_ALPHAPIXELS)) != (DDPF_LUMINANCE | DDPF_ALPHAPIXELS)) { cerr << "Invalid input file '" << endl; fclose(pdst); free(src_rgba); return; } int src_ps = _header->format.dwRGBBitCount >> 3; //source pixel size _header->format.dwFourCC = MAKEFOURCC('L', '8', 'A', '8'); _header->format.dwFlags = DDPF_LUMINANCE | DDPF_ALPHAPIXELS; _header->format.dwRGBBitCount = 16; _header->format.dwRBitMask = 0x00ff; _header->format.dwGBitMaskDWORD = 0x0000; _header->format.dwBBitMask = 0x0000; _header->format.dwRGBAlphaBitMask = 0xff00; ITF_DDS_HEADER headerfile; endianess(&headerfile, _header, sizeof(ITF_DDS_HEADER)); if(fwrite(&headerfile, sizeof(ITF_DDS_HEADER), 1, pdst) != 1) { cerr << "Can't write output file '" << Dst << "'" << endl; fclose(pdst); free(src_rgba); return; } int mipmapcount = 0; int w = _header->dwWidth; int h = _header->dwHeight; while(1) { if((w<=8) || (h<=8)) // minimum square size break; mipmapcount++; if(mipmapcount==10) // Max LOD on Wii break; w = w>>1; h = h>>1; } if((int)_header->dwMipMapCount > mipmapcount) _header->dwMipMapCount = (DWORD) mipmapcount; w = _header->dwWidth; h = _header->dwHeight; mipmapcount = _header->dwMipMapCount; workingBuff1 = (unsigned char *) src_rgba; workingBuff2 = (unsigned char *) malloc(h*w*2); if(gb_Endiannes) endianess(workingBuff1, workingBuff1, bufsize); do { ProcessBufferRGBAForLuminanceAlpha(workingBuff1, w, h, pdst, src_ps); workingBuff1 += (h*w*src_ps); w >>= 1; h >>= 1; }while(--mipmapcount >= 0); fclose(pdst); free(workingBuff2); workingBuff2 = 0; free(src_rgba); workingBuff1 = 0; } int ProcessFile() { FILE *pf = fopen(strSourceFileName, "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); ITF_DDS_HEADER header, headerfile; if(fread(&headerfile, sizeof(ITF_DDS_HEADER), 1, pf) != 1) { cerr << " Can't read input file '" << strSourceFileName << "'. " << endl; fclose(pf); return -3; } gb_Endiannes = memcmp(&headerfile, "DDS ", 4) != 0; if(gb_Endiannes) endianess(&header, &headerfile, sizeof(ITF_DDS_HEADER)); else memcpy(&header, &headerfile, sizeof(ITF_DDS_HEADER)); if(memcmp(&header, "DDS ", 4) != 0) { cerr << " Unknown file format. " << endl; fclose(pf); return -4; } if((header.dwHeight < 8) || (header.dwWidth < 8)) // TODO { cerr << " Texture size must scale of 8x8 pixels squares. " << endl; copyRGBAfile(strDstFileName, pf, &header, flen); return 0; } if((header.dwHeight % 8) || (header.dwWidth % 8)) // TODO { cerr << " Texture size must scale of 8x8 pixels squares. " << endl; copyRGBAfile(strDstFileName, pf, &header, flen); return 0; } if((header.dwHeight * header.dwWidth) % 64) // TODO { cerr << " Texture size must fit 32B tiles. " << endl; copyRGBAfile(strDstFileName, pf, &header, flen); return 0; } if(header.dwUser.dwIntensityAlpha == 1) { copyLuminancefile(strDstFileName, pf, &header, flen); return 0; } if(header.dwUser.dwIntensityAlpha == 2) { copyLuminanceAlphafile(strDstFileName, pf, &header, flen); return 0; } if(header.format.dwFourCC == MAKEFOURCC('D','X','T','1')) { copyDXT1file(strDstFileName, pf, &header, flen); return 0; } if(g_rgbaNoCompressed) { processRGBAfile(strDstFileName, pf, &header, flen); return 0; } if(header.format.dwFourCC != 0) //MAKEFOURCC('R','G','B','A')) { char str[5]; memcpy(str, &header.format.dwFourCC, 4); str[sizeof(str)-1] = 0; cerr << " Unknown texture format '" << str << "'." << endl; fclose(pf); return -5; } workingBuff1 = (unsigned char *) malloc(header.dwWidth*header.dwHeight); workingBuff2 = workingBuff1 + header.dwWidth*header.dwHeight/2; unsigned int blen = flen - sizeof(ITF_DDS_HEADER); unsigned char *rgba = (unsigned char *) malloc(blen); unsigned char *aaa = 0; fread(rgba, blen, 1, pf); fclose(pf); bool bUseAlpha = bRGBACheckTransp(rgba, header.dwWidth, header.dwHeight); if(bUseAlpha) { aaa = (unsigned char *) malloc(blen); header.format.dwFourCC = MAKEFOURCC('C','M','P','A'); } else header.format.dwFourCC = MAKEFOURCC('D','X','T','1'); int mipmapcount = 0; int w,h; w = header.dwWidth; h = header.dwHeight; while(1) { if((w<=8) || (h<=8)) // minimum square size break; mipmapcount++; if(mipmapcount==10) // Max LOD on Wii break; w = w>>1; h = h>>1; } if((int)header.dwMipMapCount > mipmapcount) header.dwMipMapCount = (DWORD) mipmapcount; endianess(&headerfile, &header, sizeof(ITF_DDS_HEADER)); pf = fopen(strDstFileName, "wb"); if(!pf) { cerr << "Can't open output file '" << strDstFileName << "'" << endl; return -6; } if(fwrite(&headerfile, sizeof(ITF_DDS_HEADER), 1, pf) != 1) { cerr << "Can't write output file '" << strDstFileName << "'" << endl; fclose(pf); return -7; } unsigned char *pMipmap, *pMipmapA; pMipmap = rgba; pMipmapA = aaa; w = header.dwWidth; h = header.dwHeight; mipmapcount = header.dwMipMapCount; do { ProcessBufferRGB(pMipmap, w, h, pMipmapA, pf); pMipmap += w*h*4; if(pMipmapA) pMipmapA += w*h*4; w = w>>1; h = h>>1; }while(--mipmapcount >= 0); if(bUseAlpha) { pMipmapA = aaa; w = header.dwWidth; h = header.dwHeight; mipmapcount = header.dwMipMapCount; do { ProcessBufferAlpha(pMipmapA, w, h, pf); pMipmapA += w*h*4; w = w>>1; h = h>>1; }while(--mipmapcount >= 0); } fclose(pf); free(workingBuff1); if(aaa) free(aaa); free(rgba); return 0; } void help() { printf("TexPostCookWii 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 \""<