1 /*---------------------------------------------------------------------------*
2 
3   Copyright (C) 2010-2011 Nintendo.  All rights reserved.
4 
5   These coded instructions, statements, and computer programs contain
6   proprietary information of Nintendo of America Inc. and/or Nintendo
7   Company Ltd., and are protected by Federal copyright law.  They may
8   not be disclosed to third parties or copied or duplicated in any form,
9   in whole or in part, without the prior written consent of Nintendo.
10 
11  *---------------------------------------------------------------------------*/
12 // ------------------------------------------------------------------
13 // TexConvert.cpp
14 // ------------------------------------------------------------------
15 #include <stdio.h>
16 #include <string.h>
17 #include "ddsReader.h"
18 #include "tgaReader.h"
19 #include "TexConvert.h"
20 
PrintSupportedDstFormats(void)21 void PrintSupportedDstFormats(void)
22 {
23     printf("Supported destination converted formats:\n");
24     printf("    GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM\n");
25 	printf("    GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB\n");
26     printf("    GX2_SURFACE_FORMAT_T_BC1_UNORM\n");
27 	printf("    GX2_SURFACE_FORMAT_T_BC1_SRGB\n");
28     printf("    GX2_SURFACE_FORMAT_T_BC2_UNORM\n");
29 	printf("    GX2_SURFACE_FORMAT_T_BC2_SRGB\n");
30     printf("    GX2_SURFACE_FORMAT_T_BC3_UNORM\n");
31 	printf("    GX2_SURFACE_FORMAT_T_BC3_SRGB\n");
32     printf("    GX2_SURFACE_FORMAT_T_BC4_UNORM\n");
33     printf("    GX2_SURFACE_FORMAT_T_BC4_SNORM\n");
34     printf("    GX2_SURFACE_FORMAT_T_BC5_UNORM\n");
35     printf("    GX2_SURFACE_FORMAT_T_BC5_SNORM\n");
36     printf("    GX2_SURFACE_FORMAT_TC_R8_UNORM\n");
37     printf("    GX2_SURFACE_FORMAT_TC_R8_G8_UNORM\n");
38 
39     printf("\n");
40     printf("Supported source DDS formats for conversion:\n");
41     printf("    ARGB 8888\n");
42     printf("    ABGR 8888\n");
43     printf("    ABGR 32Float\n");
44 
45     printf("\n");
46     printf("Supported source DDS formats for passthrough:\n");
47     printf("    ARGB 1555     -> GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM\n");
48     printf("    ABGR 2101010  -> GX2_SURFACE_FORMAT_TCS_R10_G10_B10_A2_UNORM\n");
49     printf("    ARGB 2101010  -> GX2_SURFACE_FORMAT_TCS_R10_G10_B10_A2_UNORM\n");
50     printf("    ARGB 4444     -> GX2_SURFACE_FORMAT_TC_R4_G4_B4_A4_UNORM\n");
51     printf("    ABGR 8888     -> GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM\n");
52     printf("    ARGB 8888     -> GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM\n");
53     printf("    ABGR 16161616 -> GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UNORM\n");
54     printf("    ABGR 16Float  -> GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_FLOAT\n");
55     printf("    ABGR 32Float  -> GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_FLOAT\n");
56     printf("    RGB 565       -> GX2_SURFACE_FORMAT_TCS_R5_G6_B5_UNORM\n");
57     printf("    RGB 888       -> GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM\n");
58     printf("    XRGB 1555     -> GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM\n");
59     printf("    XRGB 4444     -> GX2_SURFACE_FORMAT_TC_R4_G4_B4_A4_UNORM\n");
60     printf("    XBGR 4444     -> GX2_SURFACE_FORMAT_TC_R4_G4_B4_A4_UNORM\n");
61     printf("    XBGR 8888     -> GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM\n");
62     printf("    XRGB 8888     -> GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM\n");
63     printf("    BC1           -> GX2_SURFACE_FORMAT_T_BC1_UNORM\n");
64     printf("    BC2           -> GX2_SURFACE_FORMAT_T_BC2_UNORM\n");
65     printf("    BC3           -> GX2_SURFACE_FORMAT_T_BC3_UNORM\n");
66     printf("    BC4           -> GX2_SURFACE_FORMAT_T_BC4_UNORM\n");
67     printf("    BC5           -> GX2_SURFACE_FORMAT_T_BC5_UNORM\n");
68     printf("\n");
69     printf("(Any necessary component reordering is done during input)\n");
70 
71     printf("\n");
72     printf("Supported source GTX format file inputs for converting to DDS:\n");
73     printf(" GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_FLOAT -> ABGR 32F\n");
74     printf(" GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UNORM -> ABGR 16161616\n");
75     printf(" GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_FLOAT -> ABGR 16F\n");
76     printf(" GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM    -> ABGR 8888\n");
77     printf(" GX2_SURFACE_FORMAT_TCS_R10_G10_B10_A2_UNORM -> ABGR 2101010\n");
78     printf(" GX2_SURFACE_FORMAT_TCS_R5_G6_B5_UNORM       -> RGB 565\n");
79     printf(" GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM     -> XRGB 1555\n");
80     printf(" GX2_SURFACE_FORMAT_TC_R4_G4_B4_A4_UNORM     -> XRGB 4444\n");
81     printf(" GX2_SURFACE_FORMAT_TC_R8_UNORM              -> L8\n");
82     printf(" GX2_SURFACE_FORMAT_T_BC1_UNORM              -> BC1\n");
83     printf(" GX2_SURFACE_FORMAT_T_BC2_UNORM              -> BC2\n");
84     printf(" GX2_SURFACE_FORMAT_T_BC3_UNORM              -> BC3\n");
85     printf(" GX2_SURFACE_FORMAT_T_BC4_UNORM              -> BC4\n");
86     printf(" GX2_SURFACE_FORMAT_T_BC5_UNORM              -> BC5\n");
87     printf("\n");
88     printf("(Any necessary component reordering is done during input.It does not guarantee data consistency between input file and output file.)\n");
89 }
90 
PrintUsageMessage(void)91 void PrintUsageMessage(void)
92 {
93 //       1         2         3         4         5         6         7
94 //345678901234567890123456789012345678901234567890123456789012345678901234567890
95     printf("\
96 Example command line params (to .gtx):\n\
97     -i texture1.dds(.tga) -i texture2.dds(.tga) -o out.gtx -texturearray\n\
98     -mipFilter box -minmip 1 -f GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM\n\
99     -tileMode GX2_TILE_MODE_DEFAULT -swizzle 1\n\
100 \n\
101 Example command line params (to .dds):\n\
102     -i texturebin.gtx -o out.dds -printinfo\n\
103 \n\
104 -i <SrcFile>        : Source image file. This can appear more than once on the\n\
105                       command line for texture arrays or when creating multiple\n\
106                       textures in one gtx file. Maximum source file count is %d.\n\
107                       When source file is gtx file, only the first gtx file is converted to dds.\n\
108 -o <DstFile>        : Destination texture binary file (default: out.gtx)\n\
109 -oa <DstFile>       : Destination existing texture binary file to append textures.\n\
110 -f <DstFmt>         : Destination texture format (default: if not specified,\n\
111                       a destination format is chosen based on the source format)\n\
112 -mipFilter <mode>   : Mip filter for generating mips (only \"box\" supported now)\n\
113 -minmip <N>         : Minimum mipmap size (ie, generate until dimensions <= NxN)\n\
114 -swizzle <N>        : Swizzle value (refer to GX2 Texture documentation)\n\
115 -tileMode <mode>    : Tile mode (default: GX2_TILE_MODE_DEFAULT)\n\
116 -texarray_from_src  : Creates a texture array from the source textures.\n\
117                       Source textures should have the same dimensions.\n\
118 -mips_from_src      : Creates mips from the source textures. The order of the\n\
119                       source textures on the command line should be the desired\n\
120                       order of the mip levels: src_1 = lvl_0, src_2 = lvl_1, etc.\n\
121                       Note: This option cannot be used with texarray_from_src.\n\
122 -align              : Adds alignment padding blocks between the header & image.\n\
123                       The amount of padding depends upon hardware requirements.\n\
124 -weightingRed <N>   : The weighting of the Red or X Channel in BC1/2/3 compression.\n\
125                       The default value is 1.0.\n\
126 -weightingGreen <N> : The weighting of the Green or Y Channel in BC1/2/3 compression.\n\
127                       The default value is 1.0.\n\
128 -weightingBlue <N>  : The weighting of the Blue or Z Channel in BC1/2/3 compression.\n\
129                       The default value is 1.0.\n\
130 -bc1alpha <N>       : Sets alpha threshold to use when converting to BC1 format.\n\
131                       Texels with alpha < N will be considered transparent.\n\
132                       The default value is 127. Use N=0 to disable alpha.\n\
133 -valuetype <type>   : Treats input texture's value as specified type.\n\
134                       (type = unorm or snorm)(default: unorm)\n\
135 -gbtilingconfig <N> : Value to use in tiling config register (HW debugging only)\n\
136 -printinfo          : Print out useful information about the resulting textures.\n\
137 -endianbugfix       : Performs 8-in-32 byte swap on the output texture data.\n\
138                       This is a bug workaround for the prototype hardware.\n\
139                       Also need to set this option to convert from endianbugfixed gtx file to dds.\n\
140 -supported          : List supported output texture formats.\n\
141 -?                  : Show this usage message.\n", MAX_INPUTFILE_COUNT);
142     return;
143 }
144 
PrintCommandLine(s32 argc,char ** argv)145 void PrintCommandLine(s32 argc, char** argv)
146 {
147     for (s32 count = 0; count < argc; count++)
148     {
149         printf("%s ", argv[count]);
150     }
151 }
152 
LoadDLLs(HMODULE * hTexUtilDLL,TC2Func * fpTC2,HMODULE * hGfdDLL,GFDFunc * fpGFD)153 void LoadDLLs(HMODULE *hTexUtilDLL, TC2Func *fpTC2, HMODULE *hGfdDLL, GFDFunc *fpGFD)
154 {
155     // Load DLL
156     *hTexUtilDLL = LoadLibrary(LIB_DLL_TEXUTILS);
157     if ( !*hTexUtilDLL )
158     {
159         printf("Failed to load DLL %ws. Exiting.", LIB_DLL_TEXUTILS);
160         FreeLibrary(*hTexUtilDLL);
161         exit(1);
162     }
163 
164     *hGfdDLL = LoadLibrary(LIB_DLL_GFD);
165     if ( !*hGfdDLL )
166     {
167         printf("Failed to load DLL %ws. Exiting.", LIB_DLL_GFD);
168         FreeLibrary(*hGfdDLL);
169         exit(1);
170     }
171 
172     // Get functions
173     fpTC2->Initialize              = reinterpret_cast<PTC2Initialize>(GetProcAddress(*hTexUtilDLL, "TC2Initialize"));
174     fpTC2->Destroy                 = reinterpret_cast<PTC2Destroy>(GetProcAddress(*hTexUtilDLL, "TC2Destroy"));
175     fpTC2->GX2SurfaceFormatFromStr = reinterpret_cast<PTC2GX2SurfaceFormatFromStr>(GetProcAddress(*hTexUtilDLL, "TC2GX2SurfaceFormatFromStr"));
176     fpTC2->GenerateMipLevels       = reinterpret_cast<PTC2GenerateMipLevels>(GetProcAddress(*hTexUtilDLL, "TC2GenerateMipLevels"));
177     fpTC2->ConvertSurfaceFormat    = reinterpret_cast<PTC2ConvertSurfaceFormat>(GetProcAddress(*hTexUtilDLL, "TC2ConvertSurfaceFormat"));
178     fpTC2->ConvertTiling           = reinterpret_cast<PTC2ConvertTiling>(GetProcAddress(*hTexUtilDLL, "TC2ConvertTiling"));
179     fpTC2->DestroyGX2Surface       = reinterpret_cast<PTC2DestroyGX2Surface>(GetProcAddress(*hTexUtilDLL, "TC2DestroyGX2Surface"));
180     fpTC2->GenerateTexture         = reinterpret_cast<PTC2GenerateTexture>(GetProcAddress(*hTexUtilDLL, "TC2GenerateTexture"));
181     fpTC2->DestroyGX2Texture       = reinterpret_cast<PTC2DestroyGX2Texture>(GetProcAddress(*hTexUtilDLL, "TC2DestroyGX2Texture"));
182     fpTC2->ConvertStringToTileMode = reinterpret_cast<PTC2ConvertStringToTileMode>(GetProcAddress(*hTexUtilDLL, "TC2ConvertStringToTileMode"));
183     fpTC2->GetSourceSurfaceSize    = reinterpret_cast<PTC2GetSourceSurfaceSize>(GetProcAddress(*hTexUtilDLL, "TC2GetSourceSurfaceSize"));
184     fpTC2->CombineAsTextureArray   = reinterpret_cast<PTC2CombineAsTextureArray>(GetProcAddress(*hTexUtilDLL, "TC2CombineAsTextureArray"));
185     fpTC2->CombineAsMips           = reinterpret_cast<PTC2CombineAsMips>(GetProcAddress(*hTexUtilDLL, "TC2CombineAsMips"));
186 
187     fpGFD->WriteFileTexture       = reinterpret_cast<PGFDWriteFileTexture>(GetProcAddress(*hGfdDLL, "GFDWriteFileTexture"));
188     fpGFD->AppendWriteFileTexture = reinterpret_cast<PGFDAppendWriteFileTexture>(GetProcAddress(*hGfdDLL, "GFDAppendWriteFileTexture"));
189     fpGFD->ReadFileTexture        = reinterpret_cast<PGFDReadFileTexture>(GetProcAddress(*hGfdDLL, "GFDReadFileTexture"));
190     fpGFD->FreeFileTexture        = reinterpret_cast<PGFDFreeFileTexture>(GetProcAddress(*hGfdDLL, "GFDFreeFileTexture"));
191 }
192 
FreeDLLs(HMODULE * hTexUtilDLL,HMODULE * hGfdDLL)193 void FreeDLLs(HMODULE *hTexUtilDLL, HMODULE *hGfdDLL)
194 {
195     FreeLibrary(*hTexUtilDLL);
196     FreeLibrary(*hGfdDLL);
197 }
198 
199 // Convert GX2SurfaceFormat strings to text
FormatTypeToString(GX2SurfaceFormat eSurfaceFormat)200 char * FormatTypeToString(GX2SurfaceFormat eSurfaceFormat)
201 {
202     // Magic macro - Creates:  'case x: "x"'
203     #define A(x)  case x: return  #x
204 
205     switch(eSurfaceFormat)
206     {
207     default:
208         A(GX2_SURFACE_FORMAT_INVALID);
209         A(GX2_SURFACE_FORMAT_TC_R8_UNORM);
210         A(GX2_SURFACE_FORMAT_TC_R8_UINT);
211         A(GX2_SURFACE_FORMAT_TC_R8_SNORM);
212         A(GX2_SURFACE_FORMAT_TC_R8_SINT);
213         A(GX2_SURFACE_FORMAT_T_R4_G4_UNORM);
214         A(GX2_SURFACE_FORMAT_TCD_R16_UNORM);
215         A(GX2_SURFACE_FORMAT_TC_R16_UINT );
216         A(GX2_SURFACE_FORMAT_TC_R16_SNORM);
217         A(GX2_SURFACE_FORMAT_TC_R16_SINT);
218         A(GX2_SURFACE_FORMAT_TC_R16_FLOAT);
219         A(GX2_SURFACE_FORMAT_TC_R8_G8_UNORM);
220         A(GX2_SURFACE_FORMAT_TC_R8_G8_UINT);
221         A(GX2_SURFACE_FORMAT_TC_R8_G8_SNORM);
222         A(GX2_SURFACE_FORMAT_TC_R8_G8_SINT );
223         A(GX2_SURFACE_FORMAT_TCS_R5_G6_B5_UNORM );
224         A(GX2_SURFACE_FORMAT_TC_A1_B5_G5_R5_UNORM);
225         A(GX2_SURFACE_FORMAT_TC_R4_G4_B4_A4_UNORM);
226         A(GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM );
227         A(GX2_SURFACE_FORMAT_TC_R32_UINT);
228         A(GX2_SURFACE_FORMAT_TC_R32_SINT);
229         A(GX2_SURFACE_FORMAT_TCD_R32_FLOAT);
230         A(GX2_SURFACE_FORMAT_TC_R16_G16_UNORM);
231         A(GX2_SURFACE_FORMAT_TC_R16_G16_UINT );
232         A(GX2_SURFACE_FORMAT_TC_R16_G16_SNORM);
233         A(GX2_SURFACE_FORMAT_TC_R16_G16_SINT);
234         A(GX2_SURFACE_FORMAT_TC_R16_G16_FLOAT);
235         A(GX2_SURFACE_FORMAT_D_D24_S8_UNORM);
236      // A(GX2_SURFACE_FORMAT_TC_24_8_UNORM); // dup of above
237         A(GX2_SURFACE_FORMAT_TC_R11_G11_B10_FLOAT);
238         A(GX2_SURFACE_FORMAT_TCS_A2_B10_G10_R10_UNORM);
239         A(GX2_SURFACE_FORMAT_TC_A2_B10_G10_R10_UINT);
240         A(GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM);
241         A(GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_UINT);
242         A(GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_SNORM);
243         A(GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_SINT);
244         A(GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB);
245         A(GX2_SURFACE_FORMAT_TCS_R10_G10_B10_A2_UNORM);
246         A(GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_UINT);
247         A(GX2_SURFACE_FORMAT_D_D32_FLOAT_S8_UINT_X24);
248      // A(GX2_SURFACE_FORMAT_T_R32_FLOAT_X8_X24); // dup of above
249         A(GX2_SURFACE_FORMAT_T_X32_G8_UINT_X24);
250         A(GX2_SURFACE_FORMAT_TC_R32_G32_UINT);
251         A(GX2_SURFACE_FORMAT_TC_R32_G32_SINT);
252         A(GX2_SURFACE_FORMAT_TC_R32_G32_FLOAT);
253         A(GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UNORM );
254         A(GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UINT );
255         A(GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_SNORM  );
256         A(GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_SINT );
257         A(GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_FLOAT );
258         A(GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_UINT  );
259         A(GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_SINT );
260         A(GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_FLOAT );
261         A(GX2_SURFACE_FORMAT_T_BC1_UNORM);
262         A(GX2_SURFACE_FORMAT_T_BC1_SRGB);
263         A(GX2_SURFACE_FORMAT_T_BC2_UNORM);
264         A(GX2_SURFACE_FORMAT_T_BC2_SRGB);
265         A(GX2_SURFACE_FORMAT_T_BC3_UNORM);
266         A(GX2_SURFACE_FORMAT_T_BC3_SRGB );
267         A(GX2_SURFACE_FORMAT_T_BC4_UNORM );
268         A(GX2_SURFACE_FORMAT_T_BC4_SNORM );
269         A(GX2_SURFACE_FORMAT_T_BC5_UNORM );
270         A(GX2_SURFACE_FORMAT_T_BC5_SNORM );
271     }
272 }
273 
FormatsMatch(const char * pFormatStr,GX2SurfaceFormat otherFormat)274 bool FormatsMatch(const char* pFormatStr, GX2SurfaceFormat otherFormat )
275 {
276     const char* pOtherStr = FormatTypeToString( otherFormat );
277     if(0 == strcmp(pOtherStr, pFormatStr))
278     {
279         return( true );
280     }
281 
282     // Some formats may be interchangeable
283     for( int i = GX2_SURFACE_FORMAT_FIRST; i <= GX2_SURFACE_FORMAT_LAST; ++i )
284     {
285         if(0 == strcmp(pFormatStr, FormatTypeToString((GX2SurfaceFormat)i)))
286         {
287             switch((GX2SurfaceFormat)i)
288             {
289             case GX2_SURFACE_FORMAT_TC_A1_B5_G5_R5_UNORM: return( otherFormat == GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM );
290             case GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM: return( otherFormat == GX2_SURFACE_FORMAT_TC_A1_B5_G5_R5_UNORM );
291            //  case GX2_SURFACE_FORMAT_TC_R5_G5_B5_UNORM: return( otherFormat == GX2_SURFACE_FORMAT_TC_A1_B5_G5_R5_UNORM );
292             }
293             break;
294         }
295     }
296 
297     return( false );
298 }
299 
300 // Convert path to file
PathToFileName(char * pPath)301 char *PathToFileName(char *pPath)
302 {
303     for(char *p = strchr(pPath, '\0' ); p >= pPath; p--)
304     {
305         if (('\\'==*p) || ('/'==*p))
306             return p + 1;
307     }
308     return (char *)pPath;
309 }
310 
PrintTextureFileInfo(AppConfig * pConfig)311 void PrintTextureFileInfo(AppConfig *pConfig)
312 {
313     // print information
314     if(pConfig->printinfo)
315     {
316         printf("// ----- File Format Info ----- \n");
317         printf("  fileName    = %s\n", PathToFileName(pConfig->outFileName));
318         printf("  indexCount  = %d\n", pConfig->inFileCount);
319         printf("  alignMode   = %d\n", pConfig->alignMode);
320         printf("  endianMode  = %d\n", pConfig->endianbugfix);
321         printf("  BC1Alpha    = %d\n", pConfig->bc1alphathreshold);
322         printf("  GBTilingCfg = 0x%X\n", pConfig->gbtilingconfig);
323     }
324 }
325 
PrintTextureSurfaceInfo(bool printinfo,u32 id,GX2Texture * pGx2Textures)326 void PrintTextureSurfaceInfo(bool printinfo, u32 id, GX2Texture *pGx2Textures)
327 {
328     // print information
329     if(printinfo)
330     {
331         printf("// ----- GX2Surface Info ----- \n");
332         printf("  index     = %d \n", id);
333         printf("  dim       = %d\n", pGx2Textures->surface.dim);
334         printf("  width     = %d\n", pGx2Textures->surface.width);
335         printf("  height    = %d\n", pGx2Textures->surface.height);
336         printf("  depth     = %d\n", pGx2Textures->surface.depth);
337         printf("  numMips   = %d\n", pGx2Textures->surface.numMips);
338         printf("  format    = %s\n", FormatTypeToString(pGx2Textures->surface.format));
339         printf("  aa        = %d\n", pGx2Textures->surface.aa);
340         printf("  use       = %d\n", pGx2Textures->surface.use);
341         printf("  imageSize = %d\n", pGx2Textures->surface.imageSize);
342         printf("  mipSize   = %d\n", pGx2Textures->surface.mipSize);
343         printf("  tileMode  = %d\n", pGx2Textures->surface.tileMode);
344         printf("  swizzle   = %d, 0x%X\n", pGx2Textures->surface.swizzle, pGx2Textures->surface.swizzle);
345         printf("  alignment = %d\n", pGx2Textures->surface.alignment);
346         printf("  pitch     = %d\n", pGx2Textures->surface.pitch);
347         printf("  mipOffset = %d\n", pGx2Textures->surface.mipOffset);
348     }
349 }
350 
InitializeConfig(s32 argc,char ** argv,AppConfig * pConfig)351 bool InitializeConfig(s32 argc, char** argv, AppConfig* pConfig)
352 {
353     s32 count = 0;
354 
355     memset(pConfig, 0, sizeof(*pConfig));
356 
357     //setup default values
358     strcpy_s(pConfig->dstFormat, DSTFORMAT_DEFAULT);
359     strcpy_s(pConfig->tileMode, TILEMODE_DEFAULT);
360 
361     pConfig->gpu                  = GPU_DEFAULT;
362     pConfig->minMipSize           = MINMIPSIZE_DEFAULT;
363     pConfig->mipFilter            = MIPFILTER_DEFAULT;
364     pConfig->outFileName          = NULL;
365     pConfig->inFileCount          = INFILECOUNT_DEFAULT;
366     pConfig->textureArray         = TEXTUREARRAY_DEFAULT;
367     pConfig->mipsFromSrc          = MIPFROMSOURCE_DEFAULT;
368     pConfig->alignMode            = ALIGNMODE_DEFAULT;
369     pConfig->appendMode           = APPENDMODE_DEFAULT;
370     pConfig->endianbugfix         = ENDIANBUGFIX_DEFAULT;
371     pConfig->initialSwizzle       = INITIALSWIZZLE_DEFAULT;
372     pConfig->gbtilingconfig       = GBTILINGCONFIG_DEFAULT;
373     pConfig->valuetype            = VALUETYPE_DEFAULT;
374     pConfig->useWeighting         = USEWEIGHTING_DEFAULT;
375     pConfig->weightingRed         = WEIGHTINGRED_DEFAULT;
376     pConfig->weightingGreen       = WEIGHTINGGREEN_DEFAULT;
377     pConfig->weightingBlue        = WEIGHTINGBLUE_DEFAULT;
378     pConfig->useAdaptiveWeighting = USEADAPTIVEWEIGHTING_DEFAULT;
379 
380     pConfig->bc1usealpha        = BC1USEALPHA_DEFAULT;
381     pConfig->bc1alphathreshold  = BC1ALPHATHRESHOLD_DEFAULT;
382     pConfig->printinfo          = PRINTINFO_DEFAULT;
383 
384     pConfig->fix2197            = false;
385 
386     for (count = 0; count < argc; count++)
387     {
388         if (!strcmp(argv[count], "-tileMode"))
389         {
390             if ((count + 1) < argc)
391             {
392                 strcpy_s(pConfig->tileMode, argv[count + 1]);
393                 count++;
394             }
395         }
396         else if (!strcmp(argv[count], "-gpu"))
397         {
398             if ((count + 1) < argc)
399             {
400                 switch(atoi(argv[count + 1]))
401                 {
402                 case 0:
403                     pConfig->gpu = GPU_V1;
404                     break;
405                 case 1:
406                     pConfig->gpu = GPU_V2;
407                     break;
408                 case 2:
409                     pConfig->gpu = GPU_Cafe;
410                     break;
411                 default:
412                     printf("Error: Unsupported GPU version\n");
413                     exit(1);
414                     break;
415                 }
416                 count++;
417             }
418         }
419         // -i   source filename
420         else if (!strcmp(argv[count], "-i"))
421         {
422             if ((count + 1) < argc)
423             {
424                 pConfig->inFileName[pConfig->inFileCount++] = argv[count + 1];
425 
426                 if (pConfig->inFileCount > MAX_INPUTFILE_COUNT)
427                 {
428                     printf("Exceeded maximum input file count of %d. Exiting.\n", MAX_INPUTFILE_COUNT);
429                     exit(1);
430                 }
431 
432                 count++;
433             }
434         }
435         // -o destination filename
436         else if (!strcmp(argv[count], "-o"))
437         {
438             if ((count + 1) < argc)
439             {
440                 pConfig->outFileName = argv[count + 1];
441                 count++;
442             }
443         }
444         else if (!strcmp(argv[count], "-oa"))
445         {
446             if ((count + 1) < argc)
447             {
448                 pConfig->outFileName = argv[count + 1];
449                 pConfig->appendMode = true;
450                 count++;
451             }
452         }
453         else if (!strcmp(argv[count], "-mipFilter"))
454         {
455             if ((count + 1) < argc)
456             {
457                 if (!strcmp(argv[count + 1], "box"))
458                 {
459                     pConfig->mipFilter = MF_BOX;
460                 }
461                 else
462                 {
463                     printf("Error: Unsupported mip filter mode\n");
464                     exit(1);
465                 }
466                 count++;
467             }
468         }
469         // -minmip  minimum mip size
470         else if (!strcmp(argv[count], "-minmip"))
471         {
472             if ((count + 1) < argc)
473             {
474                 pConfig->minMipSize = atoi(argv[count + 1]);
475                 count++;
476             }
477         }
478         else if (!strcmp(argv[count], "-swizzle"))
479         {
480             if ((count + 1) < argc)
481             {
482                 if((argv[count + 1][0] == '0') &&
483                    (argv[count + 1][1] == 'x'))
484                 {
485                     sscanf_s(argv[count + 1],"0x%X", &pConfig->initialSwizzle);
486                 }
487                 else
488                 {
489                     pConfig->initialSwizzle = atoi(argv[count + 1]);
490                 }
491                 count++;
492             }
493         }
494         // -f   destination format
495         else if (!strcmp(argv[count], "-f"))
496         {
497             if ((count + 1) < argc)
498             {
499                 strcpy_s(pConfig->dstFormat, argv[count + 1]);
500                 count++;
501             }
502         }
503         else if (!strcmp(argv[count], "-gbtilingconfig"))
504         {
505             if ((count + 1) < argc)
506             {
507                 if((argv[count + 1][0] == '0') &&
508                    (argv[count + 1][1] == 'x'))
509                 {
510                     sscanf_s(argv[count + 1],"0x%X", &pConfig->gbtilingconfig);
511                 }
512                 else
513                 {
514                     pConfig->gbtilingconfig = atoi(argv[count + 1]);
515                 }
516                 count++;
517             }
518         }
519         else if (!strcmp(argv[count], "-valuetype"))
520         {
521             if ((count + 1) < argc)
522             {
523                 if (!strcmp(argv[count + 1], "snorm"))
524                 {
525                     pConfig->valuetype = VT_SNORM;
526                 }
527                 else
528                 {
529                     pConfig->valuetype = VT_UNORM;
530                 }
531                 count++;
532             }
533         }
534         else if (!strcmp(argv[count], "-bc1alpha"))
535         {
536             if ((count + 1) < argc)
537             {
538                 pConfig->bc1alphathreshold = atoi(argv[count + 1]);
539                 pConfig->bc1usealpha = (pConfig->bc1alphathreshold > 0);
540                 count++;
541             }
542         }
543         else if (!strcmp(argv[count], "-weightingRed"))
544         {
545             if ((count + 1) < argc)
546             {
547                 pConfig->weightingRed = atof(argv[count + 1]);
548                 pConfig->useWeighting = (pConfig->weightingRed != 1.0);
549                 count++;
550             }
551         }
552         else if (!strcmp(argv[count], "-weightingGreen"))
553         {
554             if ((count + 1) < argc)
555             {
556                 pConfig->weightingGreen = atof(argv[count + 1]);
557                 pConfig->useWeighting = (pConfig->weightingGreen != 1.0);
558                 count++;
559             }
560         }
561         else if (!strcmp(argv[count], "-weightingBlue"))
562         {
563             if ((count + 1) < argc)
564             {
565                 pConfig->weightingBlue = atof(argv[count + 1]);
566                 pConfig->useWeighting = (pConfig->weightingBlue != 1.0);
567                 count++;
568             }
569         }
570         else if (!strcmp(argv[count], "-texarray_from_src"))
571         {
572             if (pConfig->mipsFromSrc)
573             {
574                 printf("Error: Cannot use -texarray_from_src with -mips_from_src.\n");
575                 exit(1);
576             }
577             pConfig->textureArray = true;
578         }
579         else if (!strcmp(argv[count], "-mips_from_src"))
580         {
581             if (pConfig->textureArray)
582             {
583                 printf("Error: Cannot use -mips_from_src with -texarray_from_src.\n");
584                 exit(1);
585             }
586             pConfig->mipsFromSrc = true;
587             pConfig->minMipSize = 0;
588             pConfig->mipFilter = MF_NONE;
589         }
590         else if (!strcmp(argv[count], "-align"))
591         {
592             pConfig->alignMode = true;
593         }
594         else if (!strcmp(argv[count], "-endianbugfix"))
595         {
596             pConfig->endianbugfix = true;
597         }
598         // -? or -help print help
599         else if (!strcmp(argv[count], "-?") || !strcmp(argv[count], "-help"))
600         {
601             PrintUsageMessage();
602             exit(0);
603         }
604         // -supported
605         else if (!strcmp(argv[count], "-supported"))
606         {
607             PrintSupportedDstFormats();
608             exit(0);
609         }
610         else if (!strcmp(argv[count], "-printinfo"))
611         {
612             pConfig->printinfo = true;
613         }
614         // -fix2197
615         else if(!strcmp(argv[count], "-fix2197"))
616         {
617             pConfig->fix2197 = true;
618         }
619         else if (count != 0)
620         {
621             printf("Unrecognized command line parameter \"%s\". Exiting.", argv[count]);
622             exit(1);
623         }
624     }
625     assert(pConfig->minMipSize >= 0);
626 
627     if ((pConfig->minMipSize > 0) && (pConfig->mipFilter == MF_NONE))
628     {   // use the default in the case where user specifies a minMipSize but no filter mode
629         pConfig->mipFilter = MF_BOX;
630     }
631 
632     // default to 1 when no minmip specified
633     if (pConfig->mipFilter != MF_NONE && pConfig->minMipSize < 1)
634     {
635         printf("Minimum mip size of one or more not specified. Setting minimum size to 1.\n");
636         pConfig->minMipSize = 1;
637     }
638 
639     if (!pConfig->inFileCount)
640     {
641         return false;
642     }
643 
644     if (pConfig->mipsFromSrc)
645     {
646         pConfig->minMipSize = 0;
647         pConfig->mipFilter = MF_NONE;
648     }
649 
650     return true;
651 }
652 
StrToLower(char * str)653 char* StrToLower (char *str)
654 {
655     char *p;
656 
657     for (p = str; *p; p++)
658     {
659         *p = tolower(*p);
660     }
661     return (str);
662 }
663 
SNORMToUNORM(GX2Surface * pInSurface)664 bool SNORMToUNORM(GX2Surface *pInSurface)
665 {
666     u32 i;
667     u32 count = 0;
668     u32 value = 0;
669     u32* pSurface = (u32*)pInSurface->imagePtr;
670 
671     if (pInSurface->format == GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM)
672     {
673         // assuming dword aligned size so double check
674         u8* pSurface = (u8*)pInSurface->imagePtr;
675 
676         for (count = 0; count < pInSurface->imageSize; count += 4)
677         {
678             for(i = 0; i < 4; i++)
679             {
680                 s8 sv = (s8)*(pSurface + count + i) ;
681                 u8 uv = (u8)((s32)sv + 128);
682                 *(pSurface + count + i) = uv;
683             }
684         }
685     }
686     else
687     {
688         assert(0);
689         return false;
690     }
691 
692     return true;
693 }
694 
_tmain(s32 argc,char * argv[])695 s32 _tmain(s32 argc, char* argv[])
696 {
697     HMODULE hTexUtilDLL;
698     HMODULE hGfdDLL;
699     TC2Func fpTC2;
700     GFDFunc fpGFD;
701     TC2Config texConfig;
702     GX2TileMode tileMode;
703     AppConfig config;
704     u32 count = 0;
705     ExtensionType extType = ET_DDS;
706     GFDEndianSwapMode swapMode = GFD_ENDIAN_SWAP_MODE_DEFAULT;
707     GFDAlignMode alignMode = GFD_ALIGN_MODE_DISABLE;
708 
709     TC2ConvertOptions convertOptions;
710     GX2Texture         *pGx2Textures        = NULL;
711     GX2Surface         *pSrcTextures        = NULL;
712     GX2Surface         *pTiledTextures      = NULL;
713     GX2Surface         *pMipmapTextures     = NULL;
714     GX2Surface        **ppTexturesToConvert = NULL;
715     GX2Surface         *pConvertedTextures  = NULL;
716 
717     // Loade DLLs
718     LoadDLLs(&hTexUtilDLL, &fpTC2, &hGfdDLL, &fpGFD);
719 
720     if (!InitializeConfig(argc, argv, &config))
721     {
722         PrintUsageMessage();
723         FreeDLLs(&hTexUtilDLL, &hGfdDLL);
724         return 1;
725     }
726 
727     memset(&texConfig, 0, sizeof(texConfig));
728     texConfig.gbTilingConfig = config.gbtilingconfig;
729     texConfig.gpu            = config.gpu;
730     texConfig.bugFix2197     = config.fix2197;
731 
732     memset(&convertOptions, 0, sizeof(convertOptions));
733     convertOptions.useWeighting    = config.useWeighting;
734     convertOptions.weightingRed    = config.weightingRed;
735     convertOptions.weightingGreen  = config.weightingGreen;
736     convertOptions.weightingBlue   = config.weightingBlue;
737     convertOptions.useAdaptiveWeighting = config.useAdaptiveWeighting;
738 
739     convertOptions.bc1usealpha          = config.bc1usealpha;
740     convertOptions.bc1alphathreshold    = config.bc1alphathreshold;
741     convertOptions.bc1alphathreshold    = config.bc1alphathreshold;
742 
743     pSrcTextures = (GX2Surface*)malloc(sizeof(*pSrcTextures) * config.inFileCount);
744     memset(pSrcTextures, 0, sizeof(*pSrcTextures) * config.inFileCount);
745 
746     ppTexturesToConvert = (GX2Surface**)malloc(sizeof(*ppTexturesToConvert) * config.inFileCount);
747     memset(ppTexturesToConvert, 0, (sizeof(ppTexturesToConvert) * config.inFileCount));
748 
749     if (config.mipFilter != MF_NONE && pSrcTextures[0].numMips < 2)
750     {
751         pMipmapTextures = (GX2Surface*)malloc(sizeof(*pMipmapTextures) * config.inFileCount);
752         memset(pMipmapTextures, 0, sizeof(*pMipmapTextures) * config.inFileCount);
753     }
754 
755     pConvertedTextures = (GX2Surface*)malloc(sizeof(*pConvertedTextures) * config.inFileCount);
756     memset(pConvertedTextures, 0, sizeof(*pConvertedTextures) * config.inFileCount);
757 
758     pTiledTextures = (GX2Surface*)malloc(sizeof(*pTiledTextures) * config.inFileCount);
759     memset(pTiledTextures, 0, sizeof(*pTiledTextures) * config.inFileCount);
760 
761     // set align mode
762     if(config.alignMode)
763     {
764         alignMode = GFD_ALIGN_MODE_ENABLE;
765     }
766 
767     // Reset endian swap mode for endian bug fix mode
768     if(config.endianbugfix)
769     {
770         swapMode = GFD_ENDIAN_SWAP_MODE_8_IN_32;
771     }
772 
773     if (!fpTC2.Initialize(&texConfig))
774     {
775         FreeDLLs(&hTexUtilDLL, &hGfdDLL);
776         return 1;
777     }
778 
779     if (!fpTC2.ConvertStringToTileMode(config.tileMode, &tileMode))
780     {
781         printf("Error: Unsupported tileMode.");
782         FreeDLLs(&hTexUtilDLL, &hGfdDLL);
783         return 1;
784     }
785 
786     for (count = 0; count < config.inFileCount; count++)
787     {
788         GX2SurfaceFormat dstFormat;
789 
790         // read in TGA texture
791         if (strstr(StrToLower(config.inFileName[count]), ".tga"))
792         {
793             extType = ET_TGA;
794             if (config.outFileName == NULL)
795             {
796                     config.outFileName = DEFAULT_GTX_FILENAME;
797             }
798             if (!TGAReader::TGALoadFile(config.inFileName[count], &pSrcTextures[count]))
799             {
800                 printf("Error loading TGA file. Exiting.\n");
801                 fpTC2.Destroy();
802                 FreeDLLs(&hTexUtilDLL, &hGfdDLL);
803                 return 2;
804             }
805         }
806         // read in DDS texture
807         else if (strstr(StrToLower(config.inFileName[count]), ".dds"))
808         {
809             extType = ET_DDS;
810             if (config.outFileName == NULL)
811             {
812                     config.outFileName = DEFAULT_GTX_FILENAME;
813             }
814             if (!DDSReader::DDSLoadFile(config.inFileName[count], &pSrcTextures[count]))
815             {
816                 printf("Error loading DDS file. Exiting.\n");
817                 fpTC2.Destroy();
818                 FreeDLLs(&hTexUtilDLL, &hGfdDLL);
819                 return 3;
820             }
821         }
822         // read in GTX texture
823         else if (strstr(StrToLower(config.inFileName[count]), ".gtx"))
824         {
825             FILE* pFile = NULL;
826             GX2Texture gx2Texture;
827             GX2Surface retiledSurface;
828             GFDEndianSwapMode endianSwapMode = GFD_ENDIAN_SWAP_MODE_DEFAULT;
829 
830             int id = 0;
831             extType = ET_GTX;
832 
833             if(config.endianbugfix)
834                 endianSwapMode = GFD_ENDIAN_SWAP_MODE_8_IN_32;
835 
836             if (config.outFileName == NULL)
837             {
838                     config.outFileName = DEFAULT_DDS_FILENAME;
839             }
840 
841             if(!fpGFD.ReadFileTexture(&gx2Texture, (GFDGPUVersion)config.gpu, endianSwapMode, config.inFileName[count]))
842             {
843                 printf("Error loading GTX file. Exiting.\n");
844                 fpTC2.Destroy();
845                 FreeDLLs(&hTexUtilDLL, &hGfdDLL);
846                 return 3;
847             }
848 
849             // Print input config
850             //PrintTextureFileInfo(&config);
851 
852             // Print Information (ID == 0)
853             PrintTextureSurfaceInfo(config.printinfo, 0, &gx2Texture);
854 
855 			// retile and store in texture object
856 			if (!fpTC2.ConvertTiling(&gx2Texture.surface, GX2_TILE_MODE_LINEAR_SPECIAL, 0, &retiledSurface))
857 			{
858 				printf("Error converting tiling. Exiting.\n");
859 				fpGFD.FreeFileTexture(&gx2Texture);
860 				FreeDLLs(&hTexUtilDLL, &hGfdDLL);
861 				return 18;
862 			}
863 
864 			if (strstr(StrToLower(config.outFileName), ".dds"))
865 			{
866 				// Save Texture as DDS file
867 				if (!DDSReader::DDSSaveFile(config.outFileName, &retiledSurface))
868 				{
869 					printf("Error input format %s doesn't supported in DDS file format. Exiting.\n",  FormatTypeToString(retiledSurface.format));
870 					fpGFD.FreeFileTexture(&gx2Texture);
871 					FreeDLLs(&hTexUtilDLL, &hGfdDLL);
872 					return 19;
873 				}
874 
875 				fpGFD.FreeFileTexture(&gx2Texture);
876 				FreeDLLs(&hTexUtilDLL, &hGfdDLL);
877 				return 0;
878 			}
879 			else
880 			{
881 				memcpy(&pSrcTextures[count], &retiledSurface, sizeof(GX2Surface));
882 			}
883         }
884         else
885         {
886             printf("Unrecognized texture file type.\n");
887             fpTC2.Destroy();
888             FreeDLLs(&hTexUtilDLL, &hGfdDLL);
889             return 3;
890         }
891 
892         // convert snorm to unorm
893         if (config.valuetype == VT_SNORM)
894         {
895             if (!SNORMToUNORM(&pSrcTextures[count]))
896             {
897                 printf("Error converting snorm to unorm. Exiting.\n");
898                 fpTC2.Destroy();
899                 FreeDLLs(&hTexUtilDLL, &hGfdDLL);
900                 return 4;
901             }
902         }
903 
904         // generate mipmaps if necessary
905         if (config.mipFilter != MF_NONE && pSrcTextures[count].numMips < 2)
906         {
907             if (!fpTC2.GenerateMipLevels(&pSrcTextures[count], config.minMipSize, MF_BOX, &pMipmapTextures[count]))
908             {
909                 printf("Error generating mips. Exiting.\n");
910                 fpTC2.Destroy();
911                 FreeDLLs(&hTexUtilDLL, &hGfdDLL);
912                 return 4;
913             }
914 
915             ppTexturesToConvert[count] = &pMipmapTextures[count];
916         }
917         else
918         {
919             ppTexturesToConvert[count] = &pSrcTextures[count];
920         }
921 
922         // make the destination format to match the source format if it was not specified on the command line (passthrough mode)
923         // likewise if the format was specified, but matches the texture format, no conversion is necessary
924         if (!strcmp(config.dstFormat, DSTFORMAT_DEFAULT) || FormatsMatch(config.dstFormat, ppTexturesToConvert[count]->format ) )
925         {
926             dstFormat = ppTexturesToConvert[count]->format;
927         }
928         else if (!fpTC2.GX2SurfaceFormatFromStr(config.dstFormat, &dstFormat))
929         {
930             printf("Error: Unsupported destination format. (%s)\n", argv[count + 1]);
931             FreeDLLs(&hTexUtilDLL, &hGfdDLL);
932             return 1;
933         }
934 
935         // convert surface to destination format
936         if (!fpTC2.ConvertSurfaceFormat(ppTexturesToConvert[count], dstFormat, &pConvertedTextures[count], &convertOptions))
937         {
938             printf("Error converting to destination format. Exiting.\n");
939             fpTC2.Destroy();
940             FreeDLLs(&hTexUtilDLL, &hGfdDLL);
941             return 5;
942         }
943     }
944 
945     if (config.textureArray)
946     {
947         GX2Surface          texArray;
948         memset(&texArray, 0, sizeof(texArray));
949 
950         fpTC2.CombineAsTextureArray(pConvertedTextures, config.inFileCount, &texArray);
951 
952         pGx2Textures = (GX2Texture*)malloc(sizeof(*pGx2Textures));
953         memset(pGx2Textures, 0, sizeof(*pGx2Textures));
954 
955         // tile and store in texture object
956         if (!fpTC2.ConvertTiling(&texArray, tileMode, config.initialSwizzle, pTiledTextures))
957         {
958             printf("Error converting tiling. Exiting.\n");
959             fpTC2.Destroy();
960             FreeDLLs(&hTexUtilDLL, &hGfdDLL);
961             return 6;
962         }
963 
964         // generate a texture
965         if (!fpTC2.GenerateTexture(pTiledTextures, pGx2Textures))
966         {
967             printf("Error generating texture. Exiting.\n");
968             fpTC2.Destroy();
969             FreeDLLs(&hTexUtilDLL, &hGfdDLL);
970             return 7;
971         }
972 
973         if(config.appendMode)
974         {
975             // append textures to gtx file
976             if(!fpGFD.AppendWriteFileTexture(config.outFileName, (GFDGPUVersion)config.gpu, swapMode, alignMode, 1, pGx2Textures))
977             {
978                 printf("Error writing texture to file. Exiting.\n");
979                 fpTC2.Destroy();
980                 FreeDLLs(&hTexUtilDLL, &hGfdDLL);
981                 return 8;
982             }
983         }
984         else
985         {
986             // write gtx file
987             if(!fpGFD.WriteFileTexture(config.outFileName, (GFDGPUVersion)config.gpu, swapMode, alignMode, 1, pGx2Textures))
988             {
989                 printf("Error writing texture to file. Exiting.\n");
990                 fpTC2.Destroy();
991                 FreeDLLs(&hTexUtilDLL, &hGfdDLL);
992                 return 8;
993             }
994         }
995 
996         // print information
997         PrintTextureFileInfo(&config);
998         PrintTextureSurfaceInfo(config.printinfo, 0, pGx2Textures);
999 
1000         fpTC2.DestroyGX2Texture(pGx2Textures);
1001         free(pGx2Textures);
1002     }
1003     else if (config.mipsFromSrc)
1004     {
1005         GX2Surface          mipSurface;
1006         memset(&mipSurface, 0, sizeof(mipSurface));
1007 
1008         fpTC2.CombineAsMips(pConvertedTextures, config.inFileCount, &mipSurface);
1009 
1010         pGx2Textures = (GX2Texture*)malloc(sizeof(*pGx2Textures));
1011         memset(pGx2Textures, 0, sizeof(*pGx2Textures));
1012 
1013         // tile and store in texture object
1014         if (!fpTC2.ConvertTiling(&mipSurface, tileMode, config.initialSwizzle, pTiledTextures))
1015         {
1016             printf("Error converting tiling. Exiting.\n");
1017             fpTC2.Destroy();
1018             FreeDLLs(&hTexUtilDLL, &hGfdDLL);
1019             return 6;
1020         }
1021 
1022         // generate a texture
1023         if (!fpTC2.GenerateTexture(pTiledTextures, pGx2Textures))
1024         {
1025             printf("Error generating texture. Exiting.\n");
1026             fpTC2.Destroy();
1027             FreeDLLs(&hTexUtilDLL, &hGfdDLL);
1028             return 7;
1029         }
1030 
1031         if(config.appendMode)
1032         {
1033             // append textures to gtx file
1034             if(!fpGFD.AppendWriteFileTexture(config.outFileName, (GFDGPUVersion)config.gpu, swapMode, alignMode, 1, pGx2Textures))
1035             {
1036                 printf("Error writing texture to file. Exiting.\n");
1037                 fpTC2.Destroy();
1038                 FreeDLLs(&hTexUtilDLL, &hGfdDLL);
1039                 return 8;
1040             }
1041         }
1042         else
1043         {
1044             // write gtx file
1045             if(!fpGFD.WriteFileTexture(config.outFileName, (GFDGPUVersion)config.gpu, swapMode, alignMode, 1, pGx2Textures))
1046             {
1047                 printf("Error writing texture to file. Exiting.\n");
1048                 fpTC2.Destroy();
1049                 FreeDLLs(&hTexUtilDLL, &hGfdDLL);
1050                 return 8;
1051             }
1052         }
1053         // print information
1054         PrintTextureFileInfo(&config);
1055         PrintTextureSurfaceInfo(config.printinfo, 0, pGx2Textures);
1056 
1057         fpTC2.DestroyGX2Texture(pGx2Textures);
1058         free(pGx2Textures);
1059     }
1060     else
1061     {
1062         pGx2Textures = (GX2Texture*)malloc(sizeof(*pGx2Textures) * config.inFileCount);
1063         memset(pGx2Textures, 0, sizeof(*pGx2Textures) * config.inFileCount);
1064 
1065         for (count = 0; count < config.inFileCount; count++)
1066         {
1067             // tile and store in texture object
1068             if (!fpTC2.ConvertTiling(&pConvertedTextures[count], tileMode, config.initialSwizzle, &pTiledTextures[count]))
1069             {
1070                 printf("Error converting tiling. Exiting.\n");
1071                 fpTC2.Destroy();
1072                 FreeDLLs(&hTexUtilDLL, &hGfdDLL);
1073                 return 9;
1074             }
1075 
1076             // generate a texture
1077             if (!fpTC2.GenerateTexture(&pTiledTextures[count], &pGx2Textures[count]))
1078             {
1079                 printf("Error generating texture. Exiting.\n");
1080                 fpTC2.Destroy();
1081                 FreeDLLs(&hTexUtilDLL, &hGfdDLL);
1082                 return 10;
1083             }
1084         }
1085 
1086         if(config.appendMode)
1087         {
1088             // append textures to gtx file
1089             if(!fpGFD.AppendWriteFileTexture(config.outFileName, (GFDGPUVersion)config.gpu, swapMode, alignMode, config.inFileCount, pGx2Textures))
1090             {
1091                 printf("Error writing texture to file. Exiting.\n");
1092                 fpTC2.Destroy();
1093                 FreeDLLs(&hTexUtilDLL, &hGfdDLL);
1094                 return 11;
1095             }
1096         }
1097         else
1098         {
1099             // write gtx file
1100             if(!fpGFD.WriteFileTexture(config.outFileName, (GFDGPUVersion)config.gpu, swapMode, alignMode, config.inFileCount, pGx2Textures))
1101             {
1102                 printf("Error writing texture to file. Exiting.\n");
1103                 fpTC2.Destroy();
1104                 FreeDLLs(&hTexUtilDLL, &hGfdDLL);
1105                 return 11;
1106             }
1107         }
1108 
1109         // print information
1110         PrintTextureFileInfo(&config);
1111 
1112         for (count = 0; count < config.inFileCount; count++)
1113         {
1114             // print information
1115             PrintTextureSurfaceInfo(config.printinfo, count, pGx2Textures);
1116             fpTC2.DestroyGX2Texture(&pGx2Textures[count]);
1117         }
1118         free(pGx2Textures);
1119     }
1120 
1121     for (count = 0; count < config.inFileCount; count++)
1122     {
1123         if (config.mipFilter != MF_NONE && pSrcTextures[count].numMips < 2)
1124         {
1125             fpTC2.DestroyGX2Surface(&pMipmapTextures[count]);
1126         }
1127         if(extType == ET_DDS)
1128         {
1129             DDSReader::DDSFree(&pSrcTextures[count]);
1130             fpTC2.DestroyGX2Surface(&pSrcTextures[count]);
1131             fpTC2.DestroyGX2Surface(&pConvertedTextures[count]);
1132 		}
1133         else if(extType == ET_TGA)
1134         {
1135             TGAReader::TGAFree(&pSrcTextures[count]);
1136             fpTC2.DestroyGX2Surface(&pSrcTextures[count]);
1137             fpTC2.DestroyGX2Surface(&pConvertedTextures[count]);
1138 		}
1139 
1140         if ((count == 0) || (!config.textureArray && !config.mipsFromSrc))
1141         {
1142             fpTC2.DestroyGX2Surface(&pTiledTextures[count]);
1143         }
1144     }
1145 
1146     free(pSrcTextures);
1147     free(pConvertedTextures);
1148     free(pTiledTextures);
1149 
1150     fpTC2.Destroy();
1151 
1152     FreeDLLs(&hTexUtilDLL, &hGfdDLL);
1153 
1154     return 0;
1155 }
1156