JD2022-TU1/main/extern/TexPostCookWii/TexPostCookWii.cpp

800 lines
18 KiB
C++

// TexPostCookWii.cpp : Defines the entry point for the console application.
//
#define _CRT_SECURE_NO_WARNINGS
#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <fstream>
#include "./Squish/Squish.h"
//#include <Dds.h>
#include <ddraw.h>
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 \""<<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], "n")==0)
{
g_rgbaNoCompressed = true;
continue;
}
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;
}