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