1 /*---------------------------------------------------------------------*
2 Project:  tc library
3 File:     TCFile.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: TCFile.cpp,v $
16  Revision 1.1  2006/02/17 09:01:53  mitu
17  1st version
18 
19 
20     4    4/11/01 3:08p John
21     Updated header copyrights and pathname.
22 
23     3     8/10/00 6:02p Mikepc
24     removed redundant #include<assert.h>,
25     changed any remaining asserts to TCAssertMsg
26 
27     2     3/17/00 1:19p Mikepc
28     change tc to use indices numbered from 0.
29 
30     1     12/03/99 3:45p Ryan
31 
32     7     10/08/99 2:45p Mikepc
33     update for tplConv portability: altered data structures, replaced
34     references to 'read tga code' with ' *fileFn, removed redundant
35     functions.  Changed some file conversion paths.
36 
37     6     10/01/99 12:20p Mikepc
38     Integrated s3.lib code to generate s3 textures 'on the fly' as direct
39     draw surfaces.  Removed .dds file reading code.  Changed CMP texture
40     generation 'order of operations' to- rgb layer->s3->CMPR format per
41     mipmap LOD.
42 
43     5     9/02/99 11:12a Mikepc
44     some code re-organization between files.
45     added code (verify.cpp) to invoke s3tc.exe from within tc program.
46     changed some routines to accommodate the new texture creation path.
47 
48     4     8/26/99 4:59p Mikepc
49     renamed file extensions from .c to .cpp.
50     .cpp extension allows addition of namespace protection to remove
51     potential name collisions with tool code.  Exceptions are CreateTplFile
52     and QuickConvert.  These are extern "C" linked.
53 
54     3     8/26/99 11:38a Mikepc
55 
56     2     8/26/99 11:03a Mikepc
57     tplCon rewrite for efficient memory usage, batch file processing
58     ability.
59 
60  $NoKeywords: $
61 
62 -----------------------------------------------------------------------*/
63 
64 #include <stdio.h>
65 #include <string.h>
66 #include <stdlib.h>
67 
68 #include <charPipeline/tc/TCCommon.h>
69 
70 #include "TCFileInternal.h"
71 #include "TCMem.h"
72 
73 /********************************/
74 // global file cache
75 u32      DFSize = 1;
76 TCFile*  DF     = NULL;       // cache for decoded files
77 
78 u32 (*FileFn)( u32 rawSize, u8* rawBits, TCFile* dfPtr ) = NULL;      // ptr to current file-reading function
79 TCFileNode* FileTable                                    = NULL;      // head of file type/fn table
80 
81 /*>*******************************(*)*******************************<*/
TCSetFileCacheSize(u32 size)82 void TCSetFileCacheSize ( u32 size )
83 {
84 	// safety check
85 	if( !size )
86 	{
87 		size = 1;
88 	}
89 
90 	DFSize = size;
91 
92 	DF = (TCFile*)TCCalloc( size, sizeof(TCFile) );
93 }
94 
95 /*>*******************************(*)*******************************<*/
96 // add a new file type to FileTable; install a pointer to the
97 // file-reading function 'ext' must be a 3-letter null-terminated
98 // string giving the extension of the new file type.
99 /*>*******************************(*)*******************************<*/
TCInstallFileReadFn(char * ext,u32 (* fileFn)(u32 rawSize,u8 * rawBits,TCFile * dfPtr))100 void TCInstallFileReadFn ( char* ext, u32 (*fileFn)( u32 rawSize,
101 						   u8* rawBits, TCFile* dfPtr ))
102 {
103     u32         i           = 0;
104     u32         found       = 0;
105 	TCFileNode *fileNode;
106     TCFileNode *newFile;
107     char        pExt[4];
108 
109 
110     TCAssertMsg( (ext != NULL), "TCInstallFileReadFn: null file extension\n" );
111     TCAssertMsg( (strlen(ext) == 3), "TCInstallFileReadFn: extension is not 3 characters\n" );
112     TCAssertMsg( (fileFn != NULL), "TCInstallFileReadFn: null file pointer\n" );
113 
114 
115 	// if the user forgot to set the file cache, default the size to 1
116 	if( DF == NULL )
117 	{
118 		TCSetFileCacheSize( 1 );
119 	}
120 
121 
122 	// convert the file extension to upper case
123     strcpy( pExt, ext );
124     TCStrToUpper( pExt );
125 
126 	// if FileTable is empty, register the type
127 	if( FileTable == NULL )
128 	{
129 		newFile = (TCFileNode*)TCCalloc(1, sizeof(TCFileNode));
130 
131 		FileTable = newFile;
132 
133 		strcpy( newFile->ext, pExt );
134 		newFile->fileFn = fileFn;
135 		return;
136 	}
137 
138 	else
139 	{
140 		// search FileTable for this type- if already registered, replace fileFn*
141 		// otherwise, add a new TCFileNode to the table
142 		fileNode = FileTable;
143 		while( fileNode )
144 		{
145 			if( (strcmp( fileNode->ext, pExt )) == 0 )
146 			{
147 				fileNode->fileFn = fileFn;  // replace fileFn*
148 				found = 1;
149 				break;
150 			}
151 			fileNode = fileNode->next;
152 		}
153 
154 		// file type was not already registered- add a new node
155 		if( found == 0 )
156 		{
157 			fileNode = FileTable;
158 			while( fileNode->next != NULL )
159 				fileNode = fileNode->next;
160 
161 			newFile = (TCFileNode*)TCCalloc( 1, sizeof(TCFileNode) );
162 
163 			fileNode->next = newFile;
164 			newFile->prev  = fileNode;
165 
166 			strcpy( newFile->ext, pExt );
167 			newFile->fileFn = fileFn;
168 			return;
169 		}
170 
171 	} // end else
172 }
173 
174 /*>*******************************(*)*******************************<*/
175 // scan the file cache for the file; if not there, use the extension to
176 // locate the file type in the FileTable and call the user-installed
177 // file-reading function to decode the file into a free cache element
178 /*>*******************************(*)*******************************<*/
TCReadFile(char * fileName)179 TCFile* TCReadFile ( char* fileName )
180 {
181 	char        ext[4];
182 	u32         i, len, found;
183 	u32         rawSize = 0;
184 	s32         tmp;
185 	u8*         rawBits = NULL, *cPtr = NULL;
186 	FILE*       fp;
187 	TCFilePtr   dfPtr;
188 	TCFileNode* fileNode;
189 
190 
191     TCAssertMsg( (fileName != NULL),  "TCReadFile: NULL fileName\n" );
192     TCAssertMsg( (*fileName != '\0'), "TCReadFile: NULL fileName\n" );
193 
194 
195 	// scan file cache for file
196 	// if found, return DFPtr
197 	for( i=0; i< DFSize; i++ )
198 	{
199 		if( (strcmp( fileName, DF[i].name )) == 0 ) // file is already in the cache
200 		{
201 			return &( DF[i] );
202 		}
203 	}
204 
205 	// otherwise, scan the FileTable for a matching extension,
206 	// and set the file-read fn ptr
207 
208 	// get the 3-letter uppercase extension after the last '.'
209 	len = strlen( fileName ) - 3;
210 	strcpy( ext, ( fileName + len ) );
211     TCStrToUpper( ext );
212 
213 	fileNode = FileTable;
214 	found    = 0;
215 	while( fileNode != NULL )
216 	{
217 		if( (strcmp( ext, fileNode->ext )) == 0 )
218 		{
219 			found = 1;
220 			break;
221 		}
222 
223 		fileNode = fileNode->next;
224 	}
225 
226 	if( found == 0 )
227 	{
228 		TCErrorMsg( "ReadFile: file %s is an unregistered type\n", fileName );
229 		return NULL;
230 	}
231 
232 	// set current file-read fn ptr
233 	FileFn = fileNode->fileFn;
234 
235 	// look for a clear entry in the file cache; if none is
236 	// available, clear and use entry 0
237 	dfPtr = &( DF[0] );
238 	for( i=0; i<DFSize; i++)
239 	{
240 		if( DF[i].name[0] == '\0' )
241 		{
242 			dfPtr = &( DF[i] );
243 			break;
244 		}
245 	}
246 
247 	// clear and zero all fields prior to use
248 	dfPtr->name[0] = '\0';
249 
250 	if( dfPtr->lyColor != NULL )
251 	{
252 		if( dfPtr->lyColor->data != NULL )
253 		{
254 			TCFree( (void**)( &(dfPtr->lyColor->data) ) );
255 		}
256 		TCFree( (void**)(&(dfPtr->lyColor)) );
257 	}
258 
259 	if( dfPtr->lyAlpha != NULL )
260 	{
261 		if( dfPtr->lyAlpha->data != NULL )
262 		{
263 			TCFree( (void**)( &(dfPtr->lyAlpha->data) ) );
264 		}
265 		TCFree( (void**)( &(dfPtr->lyAlpha)) );
266 	}
267 
268 	if( dfPtr->palPtr != NULL )
269 	{
270 		if( dfPtr->palPtr->rgba != NULL )
271 		{
272 			TCFree( (void**)( &(dfPtr->palPtr->rgba) ) );
273 		}
274 		dfPtr->palPtr->numEntry = 0;
275 		TCFree( (void**)(&(dfPtr->palPtr)) );
276 	}
277 
278 	// open the file, get its raw size, and read it to a buffer
279 	if( (fp = fopen( fileName, "rb" )) == 0 )
280 	{
281 		TCErrorMsg( "ReadFile: unable to open %s for read\n", fileName );
282 		return NULL;
283 	}
284 
285 	// copy the file name to dfPtr
286 	strcpy( dfPtr->name, fileName );
287 
288 	// get the file size
289 	rawSize = 0;
290 	while( 1 )
291 	{
292 		fgetc( fp );
293 		if( (feof( fp )) != 0 )
294 		{
295 			break;
296 		}
297 		rawSize++;
298 	}
299 	rewind( fp );
300 
301 	// allocate a file buffer
302 	rawBits = (u8*)TCMalloc( rawSize );
303 
304 	// copy the raw file to the buffer
305 	cPtr = rawBits;
306 	for( i=0; i< rawSize; i++ )
307 	{
308 		tmp = getc( fp );
309 		*cPtr++ = (u8)tmp;
310 	}
311 	fclose( fp );
312 
313 	// call file reading function
314 	(*FileFn)( rawSize, rawBits, dfPtr );
315 
316 	// free up the raw file memory
317 	TCFree( (void**)(&rawBits) );
318 
319 	// return a ptr to the decoded file in the file cache
320 	return dfPtr;
321 }
322 
323 /*>*******************************(*)*******************************<*/
324