1 /*---------------------------------------------------------------------------*
2 Project: Dolphin/Revolution GD library
3 File: GDFile.c
4
5 Copyright 2001 - 2006 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 $Log: GDFile.c,v $
14 Revision 1.5 2007/11/22 13:12:27 iwai_yuma
15 (none)
16
17 Revision 1.4 2007/11/21 19:34:35 iwai
18 Replaced unsecure functions with secure functions.
19
20 Revision 1.3 2006/02/20 04:24:39 mitu
21 Changed include path from dolphin/ to revolution/.
22
23 Revision 1.2 2006/02/03 08:54:48 hirose
24 Avoided use of EPPC and use WIN32.
25
26 Revision 1.1.1.1 2005/05/12 02:15:49 yasuh-to
27 Ported from dolphin sheath tree.
28
29
30 3 2002/08/05 19:53 Hirose
31 Const type specifier support.
32
33 2 2001/09/14 4:03p Carl
34 Fixed binary mode issue.
35 Rewrote host-side file reader to mirror target-side.
36
37 1 2001/09/12 1:52p Carl
38 Initial revision of GD: Graphics Display List Library.
39
40 $NoKeywords: $
41 *---------------------------------------------------------------------------*/
42
43 #include <revolution/gd.h>
44
45 #ifndef WIN32
46 #include <revolution/os.h>
47 #include <revolution/dvd.h>
48
49 #else
50
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <sys/stat.h>
54 #include <assert.h>
55
56 #define ASSERT assert
57 #define OSRoundUp32B(x) (((u32)(x) + 31) & ~31)
58 #define OSAlloc(x) ((void*)OSRoundUp32B(malloc((x)+31)))
59 #define OSFree(x) free(x)
60
61 #endif
62
63 /*---------------------------------------------------------------------------*/
64
65 #ifdef WIN32
66
67 /*---------------------------------------------------------------------------*/
68 // Name: myFwrite, myFread...
69 //
70 // Description: Internal file access routines.
71 //
72 // Arguments: As shown
73 //
74 // Returns: 0 for no error
75 // -1 for write error
76 // -2 for read error
77 //
78 /*---------------------------------------------------------------------------*/
79
80 // Write a u32 in big-endian format
81
myFwrite_u32(FILE * fp,u32 data)82 static s32 myFwrite_u32( FILE *fp, u32 data )
83 {
84 u32 count;
85 u8 db[4];
86
87 db[0] = (u8)((data >> 24) & 0xff);
88 db[1] = (u8)((data >> 16) & 0xff);
89 db[2] = (u8)((data >> 8) & 0xff);
90 db[3] = (u8)((data >> 0) & 0xff);
91
92 count = fwrite( db, 1, 4, fp );
93
94 if (count != 4)
95 {
96 return -1;
97 } else {
98 return 0;
99 }
100 }
101
102 // Write a stream of bytes
103
myFwrite_u8s(FILE * fp,u8 * data,u32 length)104 static s32 myFwrite_u8s( FILE *fp, u8 *data, u32 length )
105 {
106 u32 count;
107
108 count = fwrite( data, 1, length, fp );
109
110 if (count != length)
111 {
112 return -1;
113 }
114 else
115 {
116 return 0;
117 }
118 }
119
120 // Read a u32 in big-endian format
121
myFread_u32(FILE * fp,u32 * data)122 static s32 myFread_u32( FILE *fp, u32 *data )
123 {
124 u32 count;
125 u8 db[4];
126
127 count = fread( db, 1, 4, fp );
128
129 *data = ((u32) db[0] << 24) | ((u32) db[1] << 16) |
130 ((u32) db[2] << 8) | ((u32) db[3] << 0);
131
132 if (count != 4)
133 {
134 return -2;
135 } else {
136 return 0;
137 }
138 }
139
140 // Read a stream of bytes
141
myFread_u8s(FILE * fp,u8 * data,u32 length)142 static s32 myFread_u8s( FILE *fp, u8 *data, u32 length )
143 {
144 u32 count;
145
146 count = fread( data, 1, length, fp );
147
148 if (count != length)
149 {
150 return -2;
151 } else {
152 return 0;
153 }
154 }
155
156 // File error-checking macro:
157 #define CHECKERR(err, fp) \
158 if (err) { \
159 fclose(fp); \
160 return err; \
161 }
162
163 /*---------------------------------------------------------------------------*/
164 // Name: GDWriteDLFile
165 //
166 // Description: This host-side routine is for writing a file containing
167 // multiple display lists and patch lists. Note that all
168 // numbers written out are written in big-endian format.
169 // This speeds up target-side reading of the file.
170 //
171 // Arguments: fName File name
172 // numDLs How many display lists to write
173 // numPLs How many patch lists to write
174 // DLDescArray Array describing display lists to write
175 // PLDescArray Array describing patch lists to write
176 //
177 // Returns: 0 No error
178 // -1 Error writing file
179 // -3 Error opening file
180 //
181 /*---------------------------------------------------------------------------*/
182
GDWriteDLFile(char * fName,u32 numDLs,u32 numPLs,GDGList * DLDescArray,GDGList * PLDescArray)183 s32 GDWriteDLFile(char *fName, u32 numDLs, u32 numPLs,
184 GDGList *DLDescArray, GDGList *PLDescArray)
185 {
186 FILE *fp;
187 s32 err;
188 u32 i;
189 u32 j;
190 u32 offset;
191 u32 padBytes;
192 u32 *patchList;
193 u32 plLength;
194
195 errno_t errno;
196
197 if ( ( errno = fopen_s( &fp, fName, "wb" ) ) != 0 )
198 // if ( (fp = fopen(fName, "wb")) == NULL )
199 {
200 // Cannot open file
201 return -3;
202 }
203
204 err = myFwrite_u32(fp, GDFileVersionNumber);
205 CHECKERR(err, fp);
206 err = myFwrite_u32(fp, numDLs);
207 CHECKERR(err, fp);
208 err = myFwrite_u32(fp, numPLs);
209
210 // The first offset points to the DLDescArray
211 offset = 20;
212 err = myFwrite_u32(fp, offset);
213 CHECKERR(err, fp);
214
215 // The second offset points to the PLDescArray
216 offset += numDLs * sizeof(GDGList);
217 err = myFwrite_u32(fp, offset);
218 CHECKERR(err, fp);
219
220 // Advance offset past the PLDescArray
221 offset += numPLs * sizeof(GDGList);
222
223 // Need to compute offset alignment to 32 bytes here.
224 // The actual padding is added after the tables themselves.
225 padBytes = OSRoundUp32B(offset) - offset;
226 offset += padBytes;
227
228 // Write out the DL table
229 for(i=0; i<numDLs; i++)
230 {
231 err = myFwrite_u32( fp, offset );
232 CHECKERR(err, fp);
233 ASSERT((DLDescArray[i].byteLength & 31) == 0);
234 err = myFwrite_u32( fp, DLDescArray[i].byteLength );
235 CHECKERR(err, fp);
236 offset += DLDescArray[i].byteLength;
237 }
238
239 // Write out the PL table
240 for(i=0; i<numPLs; i++)
241 {
242 err = myFwrite_u32( fp, offset );
243 CHECKERR(err, fp);
244 err = myFwrite_u32( fp, PLDescArray[i].byteLength );
245 CHECKERR(err, fp);
246 offset += PLDescArray[i].byteLength;
247 }
248
249 // Insert alignment padding bytes here
250 err = myFwrite_u8s( fp, "00000000000000000000000000000000", padBytes);
251 CHECKERR(err, fp);
252
253 for(i=0; i<numDLs; i++)
254 {
255 err = myFwrite_u8s(fp, DLDescArray[i].ptr, DLDescArray[i].byteLength);
256 CHECKERR(err, fp);
257 }
258
259 for(i=0; i<numPLs; i++)
260 {
261 patchList = (u32 *) PLDescArray[i].ptr;
262 plLength = PLDescArray[i].byteLength/sizeof(u32);
263
264 for(j=0; j<plLength; j++)
265 {
266 err = myFwrite_u32( fp, patchList[j] );
267 CHECKERR(err, fp);
268 }
269 }
270
271 fclose(fp);
272
273 return 0;
274 }
275
276 /*---------------------------------------------------------------------------*/
277 // Name: GDReadDLFile
278 //
279 // Description: This host-side routine is for reading a file containing
280 // multiple display lists and patch lists.
281 //
282 // Arguments: fName File name
283 // numDLs How many display lists were read
284 // numPLs How many patch lists were read
285 // DLDescArray Array describing display lists read
286 // PLDescArray Array describing patch lists read
287 //
288 // Returns: 0 No error
289 // -2 Error reading file
290 // -3 Error opening file
291 // -4 Bad file version number
292 // -5 Error allocating space for data
293 //
294 /*---------------------------------------------------------------------------*/
295
u32swap(u32 * num)296 static inline void u32swap(u32 *num)
297 {
298 u32 swap;
299 u8 *numb = (u8 *) num;
300
301 swap = ((u32) num[0] << 24) | ((u32) num[1] << 16) |
302 ((u32) num[2] << 8) | ((u32) num[3] << 0);
303
304 *num = swap;
305 }
306
GDReadDLFile(const char * fName,u32 * numDLs,u32 * numPLs,GDGList ** DLDescArray,GDGList ** PLDescArray)307 s32 GDReadDLFile(const char *fName, u32 *numDLs, u32 *numPLs,
308 GDGList **DLDescArray, GDGList **PLDescArray)
309 {
310 FILE *fp;
311 s32 err;
312 struct stat statbuf;
313 u32 length;
314 u32 i;
315 u8 *buf;
316 GDLFileHeader *hdr;
317 errno_t errno;
318
319 *numDLs = *numPLs = 0;
320 *DLDescArray = *PLDescArray = NULL;
321
322 if ( ( errno = fopen_s( &fp, fName, "rb" ) ) != 0 )
323 // if ((fp = fopen(fName, "rb")) == FALSE)
324 {
325 return -3;
326 }
327
328 // Get file length
329 err = fstat( _fileno(fp), &statbuf );
330 // err = fstat(fileno(fp), &statbuf);
331 if (err)
332 {
333 fclose(fp);
334 return -2;
335 }
336 length = statbuf.st_size;
337
338 // Allocate buffer
339 if( NULL == (buf = OSAlloc(OSRoundUp32B(length))) )
340 {
341 fclose(fp);
342 return -5;
343 }
344
345 // Read file
346 err = myFread_u8s( fp, buf, length );
347 if (err)
348 {
349 fclose(fp);
350 OSFree(buf);
351 return -2;
352 }
353
354 fclose(fp);
355
356 hdr = (GDLFileHeader *) buf;
357
358 u32swap( &hdr->versionNumber );
359
360 if (hdr->versionNumber != GDFileVersionNumber)
361 {
362 OSFree(buf);
363 return -4;
364 }
365
366 u32swap( &hdr->numDLs );
367 *numDLs = hdr->numDLs;
368
369 u32swap( &hdr->numPLs );
370 *numPLs = hdr->numPLs;
371
372 u32swap( (u32*) &hdr->DLDescArray );
373 *DLDescArray = (GDGList *) ( (u32) hdr->DLDescArray + (u32) hdr );
374
375 u32swap( (u32*) &hdr->PLDescArray );
376 *PLDescArray = (GDGList *) ( (u32) hdr->PLDescArray + (u32) hdr );
377
378 // Convert offsets into pointers
379 for(i=0; i<*numDLs; i++)
380 {
381 u32swap( (u32*) &(*DLDescArray)[i].ptr );
382 (*DLDescArray)[i].ptr = (void*)((u32)(*DLDescArray)[i].ptr + (u32)hdr);
383
384 u32swap( &(*DLDescArray)[i].byteLength );
385 }
386
387 for(i=0; i<*numPLs; i++)
388 {
389 u32swap( (u32*) &(*PLDescArray)[i].ptr );
390 (*PLDescArray)[i].ptr = (void*)((u32)(*PLDescArray)[i].ptr + (u32)hdr);
391
392 u32swap( &(*PLDescArray)[i].byteLength );
393 }
394
395 return 0;
396 }
397
398
399 #else
400
401
402 /*---------------------------------------------------------------------------*/
403 // Name: GDReadDLFile
404 //
405 // Description: This target-side routine is for reading a file containing
406 // multiple display lists and patch lists.
407 //
408 // Arguments: fName File name
409 // numDLs How many display lists were read
410 // numPLs How many patch lists were read
411 // DLDescArray Array describing display lists read
412 // PLDescArray Array describing patch lists read
413 //
414 // Returns: 0 No error
415 // -2 Error reading file
416 // -3 Error opening file
417 // -4 Bad file version number
418 // -5 Error allocating space for data
419 //
420 /*---------------------------------------------------------------------------*/
421
GDReadDLFile(const char * fName,u32 * numDLs,u32 * numPLs,GDGList ** DLDescArray,GDGList ** PLDescArray)422 s32 GDReadDLFile(const char *fName, u32 *numDLs, u32 *numPLs,
423 GDGList **DLDescArray, GDGList **PLDescArray)
424 {
425 DVDFileInfo finfo;
426 u32 length;
427 u32 i;
428 u8 *buf;
429 GDLFileHeader *hdr;
430
431 *numDLs = *numPLs = 0;
432 *DLDescArray = *PLDescArray = NULL;
433
434 if (FALSE == DVDOpen(fName, &finfo))
435 {
436 OSReport("Can't open file %s\n", fName);
437 return -3;
438 }
439
440 length = DVDGetLength(&finfo);
441
442 if( NULL == (buf = OSAlloc(OSRoundUp32B(length))) )
443 {
444 OSReport("Alloc failed\n");
445 DVDClose(&finfo);
446 return -5;
447 }
448
449 if (OSRoundUp32B(length) !=
450 DVDRead(&finfo, buf, (s32)OSRoundUp32B(length), 0))
451 {
452 OSReport("Error occurred when reading %s\n", fName);
453 DVDClose(&finfo);
454 OSFree(buf);
455 return -2;
456 }
457
458 DVDClose(&finfo);
459
460 hdr = (GDLFileHeader *) buf;
461
462 if (hdr->versionNumber != GDFileVersionNumber)
463 {
464 OSReport("Bad version number for GDL file %s\n", fName);
465 OSFree(buf);
466 return -4;
467 }
468
469 *numDLs = hdr->numDLs;
470 *numPLs = hdr->numPLs;
471 *DLDescArray = (GDGList *) ( (u32) hdr->DLDescArray + (u32) hdr );
472 *PLDescArray = (GDGList *) ( (u32) hdr->PLDescArray + (u32) hdr );
473
474 // Convert offsets into pointers
475 for(i=0; i<*numDLs; i++)
476 {
477 (*DLDescArray)[i].ptr = (void*)((u32)(*DLDescArray)[i].ptr + (u32)hdr);
478 }
479
480 for(i=0; i<*numPLs; i++)
481 {
482 (*PLDescArray)[i].ptr = (void*)((u32)(*PLDescArray)[i].ptr + (u32)hdr);
483 }
484
485 return 0;
486 }
487
488 #endif
489