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