1 /*---------------------------------------------------------------------*
2 Project:  tc library
3 File:     TCScriptFile.cpp
4 
5 Copyright 1998-2001 Nintendo.  All rights reserved.
6 
7 These coded instructions, statements and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law.  They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12 
13 Change History:
14 
15  $Log: TCScriptFile.cpp,v $
16  Revision 1.2  2008/05/23 04:26:10  iwai_yuma
17  Improved for handling of VC2005.
18 
19  Revision 1.1  2006/02/17 09:01:53  mitu
20  1st version
21 
22 
23     6     4/11/01 3:08p John
24     Updated header copyrights and pathname.
25 
26     5     3/09/01 3:21p John
27     Added better error checking for wrapS and wrapT modes.
28 
29     4     3/09/01 2:50p John
30     Modified TCProcessImKey.  Added ability to specify wrapS and wrapT mode
31     using TCS script file.
32 
33     3     8/10/00 6:03p Mikepc
34 
35     2     3/17/00 1:19p Mikepc
36     change tc to use indices numbered from 0.
37 
38     1     12/03/99 3:45p Ryan
39 
40     20    10/13/99 4:19p Mikepc
41 
42     18    10/08/99 2:45p Mikepc
43     update for tplConv portability: altered data structures, replaced
44     references to 'read tga code' with ' *fileFn, removed redundant
45     functions.  Changed some file conversion paths.
46 
47     17    9/17/99 12:57p Mikepc
48     palette entry format defaults to rgb565
49 
50     16    9/17/99 12:21p Mikepc
51     - arbitrary palette size has been removed- changed ReadTplTxtFile() to
52     reject CI4 and CI14_X2 as conversion formats.
53     - palette alpha layer has been removed- changed ProcessPlKey() to
54     default this to 0.
55 
56     15    9/16/99 8:47p Mikepc
57     updated code for auto-palette generation
58 
59     14    9/13/99 5:03p Mikepc
60     changed ProcessPlKey() to look for palette format RGB565 instead of
61     R5G6B5.
62 
63     13    9/09/99 7:02p Mikepc
64     in ProcessImKey, changed 2 conversion format values to match latest
65     gxEnum.h:  R5G6B5 to RGB565, and CMP to CMPR
66 
67     12    9/02/99 11:12a Mikepc
68     some code re-organization between files.
69     added code (verify.cpp) to invoke s3tc.exe from within tc program.
70     changed some routines to accommodate the new texture creation path.
71 
72     11    8/26/99 4:59p Mikepc
73     renamed file extensions from .c to .cpp.
74     .cpp extension allows addition of namespace protection to remove
75     potential name collisions with tool code.  Exceptions are CreateTplFile
76     and QuickConvert.  These are extern "C" linked.
77 
78     10    8/26/99 11:38a Mikepc
79 
80     9     8/26/99 11:03a Mikepc
81     tplCon rewrite for efficient memory usage, batch file processing
82     ability.
83 
84  $NoKeywords: $
85 
86 -----------------------------------------------------------------------*/
87 
88 #include <string.h>
89 #include <stdio.h>
90 #include <stdlib.h>
91 #include <ctype.h>
92 
93 #include <charPipeline/tc/TCCommon.h>
94 
95 #include "TCSrcImageList.h"
96 #include "TCImageList.h"
97 #include "TCPaletteList.h"
98 #include "TCTextureList.h"
99 #include "TCGXDefs.h"
100 
101 #pragma warning(disable : 4996)
102 
103 // path name and ptr for script file keys-
104 // was 'static', made global so it could be cleared
105 // each time for batch processing
106 char  PathName[NAME_SIZE];       // stores current file path name
107 char* PathPtr = NULL;
108 
109 /*>*******************************(*)*******************************<*/
110 static void TCProcessKeyName( char* lineBuff );
111 static void TCProcessSiKey	( u32 index, char* pathName, char* fileName );
112 static void TCProcessImKey	( u32 index, char* attList );
113 static void TCProcessPlKey	( u32 index, char* attList );
114 static void TCProcessTxKey	( u32 index, char* attList );
115 
116 static void TCGetKeyTokens	( char* lineBuff, char* leftSide,
117 							  char* rightSide );
118 
119 static void TCGetKeyNum		( char* srcStr, u32* num );
120 static void TCGetKeyString	( char* srcStr, char* dstStr );
121 static void TCStripBlanks	( char* srcStr, u32 leading, u32 trailing );
122 
123 /*>*******************************(*)*******************************<*/
124 // parse an ini-style text file
125 /*>*******************************(*)*******************************<*/
TCReadTplTxtFile(char * fileName)126 void TCReadTplTxtFile ( char* fileName )
127 {
128 	FILE* fp;
129 	char  lineBuff[NAME_SIZE];
130 	char* buffPtr;
131 
132 
133 	fp = fopen(fileName, "r");
134 	TCAssertMsg( (fp != NULL), "TCReadTplTextFile: couldn't open %s for read\n", fileName );
135 
136 	// read one line at a time until EOF is reached.
137 	// trim leading blanks while reading.
138 	while( (buffPtr = fgets(lineBuff, NAME_SIZE, fp)) != NULL )
139 	{
140 		// ensure that the .txt file line was not greater than (NAME_SIZE-1) characters
141 		// if the string is of size (NAME_SIZE-1), check if EOF or a newline was encountered at position 254
142 		if( (strlen(lineBuff)) == (NAME_SIZE - 1) )
143 		{
144 			if( (feof(fp)) == 0 )            // this is not the end of the file
145 			{
146 				if( lineBuff[ (NAME_SIZE - 2) ] != '\n' )  // fgets should always include a newline at a line's end
147 				                                           // except at the end of the file
148 				{
149 					TCErrorMsg( "TCReadTplTextFile: line exceeded %d characters in '%s'", (NAME_SIZE-1), fileName );
150 				}
151 			}
152 		}
153 
154 		TCStripBlanks( lineBuff, 1, 1 );
155 
156 		// identify the line type by its first character
157 
158 		if( lineBuff[0] == '\0' )                   // '\n' after StripBlanks()
159 		{
160 			continue;
161 		}
162 
163 		else if( lineBuff[0] == ';' )               // start of a comment
164 		{
165 			continue;
166 		}
167 
168 		else                                        // start of a possible key name
169 		{
170 			// take action depending on the type of this key
171 			TCProcessKeyName(lineBuff);
172 		}
173 	}
174 
175 	fclose(fp);
176 }
177 
178 /*>*******************************(*)*******************************<*/
179 // check the first few characters of a non-comment line for one of
180 // 'file', 'image', 'palette', 'texture'
181 // leading blanks will already have been stripped out when fgets was
182 // called for lineBuff so keyPtr should point to lineBuff on success
183 //
184 // note:  if a key can't be identified, the entire line is ignored
185 //
186 /*>*******************************(*)*******************************<*/
TCProcessKeyName(char * lineBuff)187 static void TCProcessKeyName ( char* lineBuff )
188 {
189 	char  leftSide[NAME_SIZE], rightSide[NAME_SIZE];
190 	char* keyPtr;
191 	u32   index;
192 
193 
194 	// split this key into left/right tokens, trim leading/trailing blanks
195 	TCGetKeyTokens( lineBuff, leftSide, rightSide);
196 
197 	// trim blanks and comments from the right side string
198 	TCGetKeyString( rightSide, rightSide );
199 
200     // convert everything to upper case
201     TCStrToUpper( leftSide  );
202     TCStrToUpper( rightSide );
203 
204 	// determine which key this is and get its number if needed
205 
206 	if( (keyPtr = strstr( leftSide, "PATH" )) == leftSide )          // path name key
207 	{
208 
209 		// no number component in path key name
210 
211 		// check for null path name
212 		if( ((strcmp(rightSide, "0")) == 0) || ((strcmp(rightSide, "NULL")) == 0) )
213 		{
214 			PathPtr = NULL;
215 		}
216 		else		// set a new path name
217 		{
218 			PathPtr = PathName;
219 			strcpy( PathPtr, rightSide );
220 		}
221 	}
222     else if( (keyPtr = strstr( leftSide, "FILE" )) == leftSide )      // source image (file name) key
223 	{
224 		TCGetKeyNum( (leftSide + strlen("FILE")), &index );
225 		TCProcessSiKey( index, PathPtr, rightSide );
226 	}
227 
228 	else if( (keyPtr = strstr( leftSide, "IMAGE" )) == leftSide )     // image key
229 	{
230 		TCGetKeyNum( (leftSide + strlen("IMAGE")), &index );
231 		TCProcessImKey(index, rightSide);
232 	}
233 	else if( (keyPtr = strstr( leftSide, "PALETTE" )) == leftSide )   // palette key
234 	{
235 		TCGetKeyNum( (leftSide + strlen("PALETTE")), &index );
236 	    TCProcessPlKey(index, rightSide);
237 	}
238 	else if( (keyPtr = strstr( leftSide, "TEXTURE" )) == leftSide )   // texture key
239 	{
240 		TCGetKeyNum( (leftSide + strlen("TEXTURE")), &index );
241 		TCProcessTxKey(index, rightSide);
242 	}
243 	else
244 	{
245 		;	   // unknown key- treat as a comment and ignore the whole line
246 	}
247 }
248 
249 /*>*******************************(*)*******************************<*/
250 // fetch source image data using this key as file name.
251 // create a new source image, identify layers, create layer names
252 // based on index and file name
253 /*>*******************************(*)*******************************<*/
TCProcessSiKey(u32 index,char * pathName,char * fileName)254 static void TCProcessSiKey ( u32 index, char* pathName, char* fileName )
255 {
256 	char        fullName[NAME_SIZE];
257 	u32         len;
258 	TCSrcImage* newSi;
259 
260 
261     // 'X'ed out index? ignore this key
262     if( index == TC_UNUSED )
263     {
264         return;
265     }
266 
267     TCAssertMsg( (fileName  != NULL), "TCProcessSiKey: NULL fileName for file %d\n", index    );
268     TCAssertMsg( (*fileName != '\0'), "TCProcessSiKey: NULL fileName for file %d\n", index    );
269 
270 
271 	len = 0;
272 	if( pathName != NULL )
273 	{
274 		len = strlen(pathName);
275 	}
276 
277 	len += strlen(fileName);
278     TCAssertMsg( (len <= (NAME_SIZE-1)), "TCProcessSiKey: length of (%s + path) > %d characters\n", (NAME_SIZE-1), fileName );
279 
280 	// build the source image name from the current path and file name
281 	if(pathName)
282 	{
283 		strcpy(fullName, pathName);
284 		strcat(fullName, fileName);
285 	}
286 	else
287 	{
288 		strcpy(fullName, fileName);
289 	}
290 
291 	// create a new source image and set its attributes
292 	newSi = TCNewSrcImage();
293 	TCAssertMsg( (newSi != NULL),"ProcessSiKey: couldn't allocate memory for new source image %d\n", index );
294 
295 	// set source image attributes
296 	// valid source file types depend on user-defined file reading functions
297 	// set by InstallFileReadFn() - invalid types will be caught by ReadFile()
298 	TCSetSrcImageFromFile( newSi, fullName, index );
299 }
300 
301 /*>*******************************(*)*******************************<*/
TCProcessImKey(u32 index,char * attList)302 static void TCProcessImKey( u32 index, char* attList )
303 {
304 	TCImage* newIm;
305 	char*  icPtr       = NULL, *iaPtr      = NULL, *fmtPtr     = NULL;
306     char*  minLODPtr   = NULL, *maxLODPtr  = NULL, *baseLODPtr = NULL;
307     char*  wrapSPtr    = NULL, *wrapTPtr   = NULL;
308 	u32    icNum       = 0, iaNum          = 0,    fmt         = 0;
309 	u32    minLOD      = 0, maxLOD         = 0,    baseLOD     = 0;
310     u32    wrapS       = 0, wrapT          = 0;
311 
312 
313     // 'X'ed out index? ignore this key
314     if( index == TC_UNUSED )
315     {
316         return;
317     }
318 
319     TCAssertMsg( (attList  != NULL), "TCProcessImKey: missing attribute list for image %d in script file\n", index );
320     TCAssertMsg( (*attList != '\0'), "TCProcessImKey: missing attribute list for image %d in script file\n", index );
321 
322 
323 	// split the attList string into tokens using commas as separators.
324 	// remove whitespace from around tokens.
325 	icPtr  = strtok( attList, "," );
326 	TCAssertMsg( (icPtr != NULL), "ProcessImKey: problem reading color index for image %d in script file\n", index );
327 
328 	iaPtr  = strtok( NULL,    "," );
329 	TCAssertMsg( (iaPtr != NULL), "ProcessImKey: problem reading alpha index for image %d in script file\n", index );
330 
331 	fmtPtr = strtok( NULL,    "," );
332 	TCAssertMsg( (fmtPtr != NULL), "ProcessImKey: problem reading output format for image %d in script file\n", index );
333 
334 	// mip map information may is optional
335 	// if present, there must be 3 more comma-separated values
336 	if( (minLODPtr = strtok( NULL,    "," )) != 0 )
337 	{
338     	TCStripBlanks( minLODPtr, 1,1 );
339         if( isdigit( *minLODPtr ) )
340         {
341             // Parse these three arguments as mipmap constants (minLOD, maxLOD, baseLOD)
342 		    maxLODPtr = strtok( NULL, "," );
343 		    TCAssertMsg( (maxLODPtr != NULL), "ProcessImKey: problem reading max LOD for image %d in script file\n", index );
344         	TCStripBlanks( maxLODPtr, 1,1 );
345             TCAssertMsg( (isdigit( *maxLODPtr )), "ProcessImKey: missing max LOD for image %d (should be a number)\n", index );
346 
347 		    baseLODPtr = strtok( NULL, "," );
348 		    TCAssertMsg( (baseLODPtr != NULL), "ProcessImKey: problem reading remap base LOD for image %d in script file\n", index );
349         	TCStripBlanks( baseLODPtr, 1,1 );
350             TCAssertMsg( (isdigit( *baseLODPtr )), "ProcessImKey: missing base LOD for image %d (should be a number)\n", index );
351 
352             // If two more args exist, parse as wrap modes (wrapS, wrapT)
353             if( (wrapSPtr = strtok( NULL, "," )) != 0 )
354             {
355 		        wrapTPtr = strtok( NULL, "" );
356 		        TCAssertMsg( (wrapTPtr != NULL), "ProcessImKey: problem reading wrapT mode for image %d in script file\n", index );
357             }
358         }
359         else
360         {
361             // Parse two arguments as wrap modes (wrapS, wrapT)
362             wrapSPtr = minLODPtr;
363             minLODPtr = NULL;
364 
365 		    wrapTPtr = strtok( NULL, "" );
366 		    TCAssertMsg( (wrapTPtr != NULL), "ProcessImKey: problem reading wrapT mode for image %d in script file\n", index );
367         }
368 	}
369 
370 	// strip whitespace from these tokens
371 	TCStripBlanks( icPtr,  1,1 );
372 	TCStripBlanks( iaPtr,  1,1 );
373 	TCStripBlanks( fmtPtr, 1,1 );
374     TCStripBlanks( wrapSPtr, 1, 1 );
375     TCStripBlanks( wrapTPtr, 1, 1 );
376 
377     // set the color and alpha layer indices:
378 
379     // color layer index is mandatory
380     TCGetKeyNum ( icPtr, &icNum );
381     TCAssertMsg( (icNum != TC_UNUSED), "TCProcessImKey: invalid color index for image %d in script file\n", index );
382 
383     // alpha layer index is optional.
384     // if no alpha layer, iaNum will be set to TC_UNUSED
385     TCGetKeyNum ( iaPtr, &iaNum );
386 
387 
388 	// set the final hw pixel format
389 	if( (strcmp(fmtPtr, "I4")) == 0 )
390 		fmt = TPL_IMAGE_TEXEL_FMT_I4;
391 	else if( (strcmp(fmtPtr, "I8")) == 0 )
392 		fmt = TPL_IMAGE_TEXEL_FMT_I8;
393 	else if( (strcmp(fmtPtr, "IA4")) == 0 )
394 		fmt = TPL_IMAGE_TEXEL_FMT_IA4;
395 	else if( (strcmp(fmtPtr, "IA8")) == 0 )
396 		fmt = TPL_IMAGE_TEXEL_FMT_IA8;
397 
398 	else if( (strcmp(fmtPtr, "RGB565")) == 0 )
399 		fmt = TPL_IMAGE_TEXEL_FMT_R5G6B5;
400 
401 	else if( (strcmp(fmtPtr, "RGB5A3")) == 0 )
402 		fmt = TPL_IMAGE_TEXEL_FMT_RGB5A3;
403 	else if( (strcmp(fmtPtr, "RGBA8")) == 0 )
404 		fmt = TPL_IMAGE_TEXEL_FMT_RGBA8;
405 
406 	else if( (strcmp(fmtPtr, "CI8")) == 0 )
407 		fmt = TPL_IMAGE_TEXEL_FMT_CI8;
408 
409     //=========================================================================================
410 	// note: input palette sizes other than 8-bit/ @256 entry are not supported in this version.
411     //       if output palette is CI4, tc will use the low 4-bits of each index.
412     //       if output palette is CI14_X2, tc will only create up to 256 'real' entries;
413     //       the remaining palette entries will be padded with zeroes.
414 
415 	else if( (strcmp(fmtPtr, "CI4")) == 0 )
416 		fmt = TPL_IMAGE_TEXEL_FMT_CI4;
417 	else if( (strcmp(fmtPtr, "CI14_X2")) == 0 )
418 		fmt = TPL_IMAGE_TEXEL_FMT_CI14_X2;
419 
420     //==========================================================================================
421 
422 	else if( (strcmp(fmtPtr, "CMPR")) == 0 )
423 		fmt = TPL_IMAGE_TEXEL_FMT_CMP;
424 
425 	else
426 		TCErrorMsg( "ProcessImKey: unknown output format '%s' for image %d in script file \n", fmtPtr, index );
427 
428 
429 	// if mipmap numbers are included, get their values
430 	if( minLODPtr )
431 		minLOD   = atoi( minLODPtr );
432 	if( maxLODPtr )
433 		maxLOD   = atoi( maxLODPtr );
434 	if( baseLODPtr )
435 		baseLOD  = atoi( baseLODPtr );
436 
437 	if( wrapSPtr )
438     {
439         if( (strcmp(wrapSPtr, "GX_REPEAT")) == 0 )
440 		    wrapS = TPL_WRAP_MODE_REPEAT;
441 	    else if( (strcmp(wrapSPtr, "GX_CLAMP")) == 0 )
442 		    wrapS = TPL_WRAP_MODE_CLAMP;
443 	    else if( (strcmp(wrapSPtr, "GX_MIRROR")) == 0 )
444 		    wrapS = TPL_WRAP_MODE_MIRROR;
445         else
446             TCErrorMsg( "ProcessImKey: unknown wrapS mode '%s' for image %d in script file \n", wrapSPtr, index );
447     }
448     else
449     {
450         // Wrap mode will be set to defaults in TCWriteTplFile by TCSetFilterModeByDim in TCTPLToolbox.cpp
451         // We have to wait until then since TCSetFilterModeByDim needs information we don't have right now
452         wrapS = TPL_WRAP_MODE_NONE;
453     }
454 
455     if( wrapTPtr )
456     {
457 	    if( (strcmp(wrapTPtr, "GX_REPEAT")) == 0 )
458 		    wrapT = TPL_WRAP_MODE_REPEAT;
459 	    else if( (strcmp(wrapTPtr, "GX_CLAMP")) == 0 )
460 		    wrapT = TPL_WRAP_MODE_CLAMP;
461 	    else if( (strcmp(wrapTPtr, "GX_MIRROR")) == 0 )
462 		    wrapT = TPL_WRAP_MODE_MIRROR;
463         else
464             TCErrorMsg( "ProcessImKey: unknown wrapT mode '%s' for image %d in script file \n", wrapTPtr, index );
465     }
466     else
467     {
468         // Wrap mode will be set to defaults in TCWriteTplFile by TCSetFilterModeByDim in TCTPLToolbox.cpp
469         // We have to wait until then since TCSetFilterModeByDim needs information we don't have right now
470         wrapT = TPL_WRAP_MODE_NONE;
471     }
472 
473 	// create a new Image structure and set its attributes.
474 	// 'index' is also used as the final tpl bank location
475 	newIm = TCNewImage();
476     TCAssertMsg( (newIm != NULL), "ProcessImKey: couldn't allocate new image %d\n", index );
477 
478 	// set new image attributes
479 	TCSetImageIndex(       newIm, index                   );
480 	TCSetImageLayerAtt(    newIm, icNum, iaNum            );
481     TCSetImageTexelFormat( newIm, fmt                     );
482     TCSetImageMipMap(      newIm, minLOD, maxLOD, baseLOD );
483     TCSetImageWrap(        newIm, wrapS, wrapT            );
484 }
485 
486 /*>*******************************(*)*******************************<*/
TCProcessPlKey(u32 index,char * attList)487 static void TCProcessPlKey ( u32 index, char* attList )
488 {
489 	char*      psPtr, *fmtPtr;
490 	u32        psNum,  fmt;
491 	TCPalette* newPl;
492 
493 
494     // 'X'ed out index? ignore this key
495     if( index == TC_UNUSED )
496     {
497         return;
498     }
499 
500     TCAssertMsg( (attList  != NULL), "TCProcessPlKey: missing attribute list for palette %d in script file\n", index );
501     TCAssertMsg( (*attList != '\0'), "TCProcessPlKey: missing attribute list for palette %d in script file\n", index );
502 
503 
504 	// split the attList string into tokens using commas as separators.
505 	// remove whitespace from around tokens.
506 	psPtr  = strtok( attList, "," );
507 	TCAssertMsg( (psPtr != NULL), "ProcessPlKey: problem reading file index for palette %d in script file\n", index );
508 
509 	fmtPtr = strtok( NULL,    ""  );
510 	TCAssertMsg( (fmtPtr != NULL), "ProcessPlKey: problem reading output format for palette %d in script file\n", index );
511 
512 
513 	// strip whitespace from these tokens
514 	TCStripBlanks( psPtr,    1,1 );
515 	TCStripBlanks( fmtPtr,   1,1 );
516 
517 	// set the palette color layer
518     // (color and alpha must come from the same source image)
519     TCGetKeyNum ( psPtr, &psNum );
520     TCAssertMsg( (psNum != TC_UNUSED), "TCProcessPlKey: invalid color index for palette %d in script file\n", index );
521 
522 	// set the palette entry format
523 	// note: IA8 format is not supported yet.
524 	if( (strcmp(fmtPtr, "RGB565")) == 0 )
525 	{
526 		fmt = TPL_PALETTE_ENTRY_FMT_R5G6B5;
527 	}
528 	else if( (strcmp(fmtPtr, "RGB5A3")) == 0 )
529 	{
530 		fmt = TPL_PALETTE_ENTRY_FMT_RGB5A3;
531 	}
532 	else if( (strcmp(fmtPtr, "IA8")) == 0 )
533 	{
534 		TCErrorMsg( "ProcessPlKey: tc does not support output format '%s'. (palette %d in script file)\n", fmtPtr, index );
535 	}
536 	else
537 	{
538 		TCErrorMsg( "ProcessPlKey: unknown output format '%s' for palette %d in script file\n", fmtPtr, index );
539 	}
540 
541 	// create a new Palette structure and set its attributes.
542 	// 'index' is also used as the implied bank location
543 	newPl = TCNewPalette();
544 	TCAssertMsg( (newPl != NULL), "ProcessPlKey: couldn't allocate palette %d\n", index );
545 
546 	// set palette values
547 	TCSetPaletteIndex(       newPl, index );
548     TCSetPaletteSrcImage(    newPl, psNum );
549     TCSetPaletteEntryFormat( newPl, fmt   );
550 }
551 
552 /*>*******************************(*)*******************************<*/
TCProcessTxKey(u32 index,char * attList)553 static void TCProcessTxKey ( u32 index, char* attList )
554 {
555 	char*      imPtr, *plPtr;
556 	u32        imNum,  plNum;
557 	TCTexture* newTx;
558 
559 
560     // 'X'ed out index? ignore this key
561     if( index == TC_UNUSED )
562     {
563         return;
564     }
565 
566     TCAssertMsg( (attList  != NULL), "TCProcessTxKey: missing attribute list for texture %d in script file\n", index );
567     TCAssertMsg( (*attList != '\0'), "TCProcessTxKey: missing attribute list for texture %d in script file\n", index );
568 
569 
570 	// split the attList string into tokens using commas as separators.
571 	// remove whitespace from around tokens.
572 	imPtr  = strtok( attList, "," );
573 	TCAssertMsg( (imPtr != NULL), "ProcessTxKey: problem reading image index for texture %d in script file\n", index );
574 
575 	plPtr  = strtok( NULL,    "," );
576 	TCAssertMsg( (plPtr != NULL), "ProcessTxKey: problem reading palette index for texture %d in script file\n", index );
577 
578 	// strip whitespace from these tokens
579 	TCStripBlanks( imPtr, 1,1 );
580 	TCStripBlanks( plPtr, 1,1 );
581 
582     // image index is mandatory
583     TCGetKeyNum ( imPtr, &imNum );
584     TCAssertMsg( (imNum != TC_UNUSED), "TCProcessTxKey: invalid image index for texture %d in script file\n", index );
585 
586     // palette index is optional.
587     // if no palette, plNum will be set to TC_UNUSED
588     TCGetKeyNum ( plPtr, &plNum );
589 
590 	// create a new Texture structure and set its attributes.
591 	// 'index' is also used as the implied bank location
592 	newTx = TCNewTexture();
593     TCAssertMsg( (newTx != NULL), "ProcessTxKey(): couldn't allocate new Texture %d\n", index );
594 
595     // set texture values
596 	TCSetTextureAttributes( newTx, index, imNum, plNum );
597 }
598 
599 /*>*******************************(*)*******************************<*/
600 // split lineBuff into two tokens separated by an '=' sign,
601 // strip away any leading/trailing whitespace
602 //
603 // note: while there is guaranteed to be at least a one character
604 //		 non-whitespace string for leftSide, rightSide may end up
605 //		 as NULL if no '=' was found.  this could happen if the
606 //		 'key' was actually just a line of text without a ';' comment
607 //		 delineator.  The problem will be caught by TCProcessKeyName().
608 /*>*******************************(*)*******************************<*/
TCGetKeyTokens(char * lineBuff,char * leftSide,char * rightSide)609 static void TCGetKeyTokens ( char* lineBuff, char* leftSide, char* rightSide )
610 {
611 	char* left, *right;
612 
613 
614     // safety check
615 	if( (lineBuff == NULL) || (leftSide == NULL) || (rightSide == NULL) )
616 	{
617 		return;
618 	}
619 
620 	*leftSide  = '\0';
621 	*rightSide = '\0';
622 
623 	if( *lineBuff == '\0')
624 	{
625 		return;
626 	}
627 
628 	// use the '=' sign as leftSide/rightSide separator
629 	if( (left = strtok( lineBuff, "=" )) == 0 )
630 	{
631 		return;
632 	}
633 
634 	strcpy(leftSide, left);
635 	TCStripBlanks( leftSide, 1, 1 );
636 
637 	if( (right = strtok( NULL,     ""  )) == 0 )
638 	{
639 		return;
640 	}
641 
642 	strcpy(rightSide, right);
643 	TCStripBlanks( rightSide, 1, 1 );
644 }
645 
646 /*>*******************************(*)*******************************<*/
647 // get the string equivalent of the key name ( the 'N' portion of 'keyN')
648 // and place it in dstStr.  num will hold the converted result.
649 // note: if *srcStr == TC_BLANK value (TCCommon.h),
650 //       *num will be set to TC_UNUSED
651 /*>*******************************(*)*******************************<*/
TCGetKeyNum(char * srcStr,u32 * num)652 static void TCGetKeyNum ( char* srcStr, u32* num )
653 {
654 	u32   found  = 0;
655 	char  numStr[10];
656     char* numPtr = NULL;
657 	char  subStr[NAME_SIZE];
658     char* subPtr = NULL;
659 
660 
661     // initialize *num
662     *num = TC_UNUSED;
663 
664 	// safety check
665 	if( (srcStr == NULL) || (*srcStr == '\0') )         // no string; return TC_UNUSED
666 	{
667 		return;
668 	}
669 
670 	strcpy(subStr, srcStr);                             // if no string left after 'TCStripBlanks,
671 	TCStripBlanks(subStr, 1, 1);                        // while loop will not execute;
672                                                         // return TC_UNUSED
673 
674 
675 	subPtr = subStr;                                    // collect base-10 digits from
676 	numPtr = numStr;
677     while( *subPtr != '\0' )                            // *subStr to the first non-digit value
678 	{
679         if( (isdigit(*subPtr)) != 0 )
680         {
681             found = 1;
682 		    *numPtr++ = *subPtr++;
683 		    continue;
684         }
685 
686         break;  // reached only if *subStr was not a base-10 digit
687 	}
688 	*numPtr = '\0';
689 
690 
691 	if(found)                                          // number found - convert to int value
692 	{
693 	    *num = (u32)atoi(numStr);
694     }
695 }
696 
697 /*>*******************************(*)*******************************<*/
698 // check the right side string for any ';' delineated comments.
699 // leading/trailing blanks have already been stripped
700 //
701 // note: src and dst may be the same address, so a temporary string is used
702 /*>*******************************(*)*******************************<*/
TCGetKeyString(char * srcStr,char * dstStr)703 static void TCGetKeyString( char* srcStr, char* dstStr )
704 {
705 	char* name;
706 	char  tmp[NAME_SIZE];
707 	u32   count = 0;
708 
709 
710     // safety check
711 	if( (srcStr == NULL) || (dstStr == NULL) )
712 	{
713 		return;
714 	}
715 
716 	// srcStr could be an empty string
717 	if( *srcStr == '\0')
718 	{
719         *dstStr = '\0';
720 		return;
721 	}
722 
723 	// strip away any trailing comment- if the whole string was a comment, return.
724 	if( (name = strtok(srcStr, ";")) == 0 )
725 	{
726 		*dstStr = '\0';
727 		return;
728 	}
729 
730 	// trim any trailing blanks between the name and any removed comment
731 	TCStripBlanks(name, 0, 1 );
732 
733 	// copy out the modified name
734 	count = 0;
735 	while(  (tmp[count] = name[count]) != '\0' )
736 	{
737 		count++;
738 	}
739 	count = 0;
740 	while( (dstStr[count] = tmp[count]) != '\0' )
741 	{
742 		count++;
743 	}
744 }
745 
746 /*>*******************************(*)*******************************<*/
747 // strip leading and trailing blanks from a string.
748 // if leading or trailing == 1, strip blanks from the indicated end
749 // else if leading or trailing == 0, do not strip blanks from the
750 // indicated end
751 /*>*******************************(*)*******************************<*/
TCStripBlanks(char * srcStr,u32 leading,u32 trailing)752 static void TCStripBlanks ( char* srcStr, u32 leading, u32 trailing )
753 {
754 	u32   i,        len;
755 	char* startPtr, *endPtr;
756 	char  tmpStr[NAME_SIZE];
757 
758 
759 	if( srcStr == NULL )
760 	{
761 		return;
762 	}
763 
764 	len = strlen(srcStr);
765 	if( (len == 0) || (len > (NAME_SIZE-1)) )
766 	{
767         TCErrorMsg( "TCStripBlanks: invalid string length %d for string '%s'\n", srcStr );
768 	}
769 
770 
771 	startPtr = srcStr;
772 
773 	// strip leading blanks
774 	if( leading == 1 )
775 	{
776 		while( (*startPtr != '\0') && ( (isspace(*startPtr)) != 0 ) )
777 		{
778 			startPtr++;
779 		}
780 	}
781 
782 	// strip trailing blanks
783 	if( trailing == 1 )
784 	{
785 		if( *startPtr != '\0')
786 		{
787 			endPtr = startPtr + (strlen(startPtr)) - 1;
788 
789 			while( (endPtr >= startPtr) && ((isspace(*endPtr)) != 0) )
790 			{
791 				endPtr--;
792 			}
793 
794 			endPtr++;
795 			*endPtr = '\0';
796 		}
797 	}
798 
799 	// replace the original string with the stripped string
800 	len = strlen(startPtr);
801 	for(i=0; i <= len; i++) // include the '\0'
802 	{
803 		tmpStr[i] = startPtr[i];
804 	}
805 	for(i=0; i <= len; i++)
806 	{
807 		srcStr[i] = tmpStr[i];
808 	}
809 }
810 
811 /*>*******************************(*)*******************************<*/
812