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