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 /*>*******************************(*)*******************************<*/