/*---------------------------------------------------------------------------* Project: Dolphin/Revolution GD library File: GDFile.c Copyright 2001-2006 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Log: GDFile.c,v $ Revision 1.3 02/20/2006 04:24:39 mitu changed include path from dolphin/ to revolution/. Revision 1.2 02/03/2006 08:54:48 hirose Avoided use of EPPC and use WIN32. Revision 1.1.1.1 2005/05/12 02:15:49 yasuh-to transitioned from the Dolphin source tree 3 02/08/05 19:53 Hirose Const type specifier support. 2 9/14/01 4:03p Carl Fixed binary mode issue. Rewrote host-side file reader to mirror target-side. 1 9/12/01 1:52p Carl Initial revision of GD: Graphics Display List Library. $NoKeywords: $ *---------------------------------------------------------------------------*/ #include #ifndef WIN32 #include #include #else #include #include #include #include #define ASSERT assert #define OSRoundUp32B(x) (((u32)(x) + 31) & ~31) #define OSAlloc(x) ((void*)OSRoundUp32B(malloc((x)+31))) #define OSFree(x) free(x) #endif /*---------------------------------------------------------------------------*/ #ifdef WIN32 /*---------------------------------------------------------------------------*/ // Name: myFwrite, myFread... // // Description: Internal file access routines. // // Arguments: as shown // // Returns: 0 for no error // -1 for write error // -2 for read error // /*---------------------------------------------------------------------------*/ // Write a u32 in big-endian format static s32 myFwrite_u32( FILE *fp, u32 data ) { u32 count; u8 db[4]; db[0] = (u8)((data >> 24) & 0xff); db[1] = (u8)((data >> 16) & 0xff); db[2] = (u8)((data >> 8) & 0xff); db[3] = (u8)((data >> 0) & 0xff); count = fwrite( db, 1, 4, fp ); if (count != 4) { return -1; } else { return 0; } } // Write a stream of bytes static s32 myFwrite_u8s( FILE *fp, u8 *data, u32 length ) { u32 count; count = fwrite( data, 1, length, fp ); if (count != length) { return -1; } else { return 0; } } // Read a u32 in big-endian format static s32 myFread_u32( FILE *fp, u32 *data ) { u32 count; u8 db[4]; count = fread( db, 1, 4, fp ); *data = ((u32) db[0] << 24) | ((u32) db[1] << 16) | ((u32) db[2] << 8) | ((u32) db[3] << 0); if (count != 4) { return -2; } else { return 0; } } // Read a stream of bytes static s32 myFread_u8s( FILE *fp, u8 *data, u32 length ) { u32 count; count = fread( data, 1, length, fp ); if (count != length) { return -2; } else { return 0; } } // File error-checking macro: #define CHECKERR(err, fp) \ if (err) { \ fclose(fp); \ return err; \ } /*---------------------------------------------------------------------------*/ // Name: GDWriteDLFile // // Description: This host-side routine is for writing a file containing // multiple display lists and patch lists. Note that all // numbers written out are written in big-endian format. // This speeds up target-side reading of the file. // // Arguments: fName file name // numDLs how many display lists to write // numPLs how many patch lists to write // DLDescArray array describing display lists to write // PLDescArray array describing patch lists to write // // Returns: 0 no error // -1 error writing file // -3 error opening file // /*---------------------------------------------------------------------------*/ s32 GDWriteDLFile(char *fName, u32 numDLs, u32 numPLs, GDGList *DLDescArray, GDGList *PLDescArray) { FILE *fp; s32 err; u32 i; u32 j; u32 offset; u32 padBytes; u32 *patchList; u32 plLength; if ( (fp = fopen(fName, "wb")) == NULL ) { // Cannot open file return -3; } err = myFwrite_u32(fp, GDFileVersionNumber); CHECKERR(err, fp); err = myFwrite_u32(fp, numDLs); CHECKERR(err, fp); err = myFwrite_u32(fp, numPLs); // The first offset points to the DLDescArray offset = 20; err = myFwrite_u32(fp, offset); CHECKERR(err, fp); // The second offset points to the PLDescArray offset += numDLs * sizeof(GDGList); err = myFwrite_u32(fp, offset); CHECKERR(err, fp); // Advance offset past the PLDescArray offset += numPLs * sizeof(GDGList); // Need to compute offset alignment to 32 bytes here. // The actual padding is added after the tables themselves. padBytes = OSRoundUp32B(offset) - offset; offset += padBytes; // write out the DL table for(i=0; iversionNumber ); if (hdr->versionNumber != GDFileVersionNumber) { OSFree(buf); return -4; } u32swap( &hdr->numDLs ); *numDLs = hdr->numDLs; u32swap( &hdr->numPLs ); *numPLs = hdr->numPLs; u32swap( (u32*) &hdr->DLDescArray ); *DLDescArray = (GDGList *) ( (u32) hdr->DLDescArray + (u32) hdr ); u32swap( (u32*) &hdr->PLDescArray ); *PLDescArray = (GDGList *) ( (u32) hdr->PLDescArray + (u32) hdr ); // Convert offsets into pointers for(i=0; i<*numDLs; i++) { u32swap( (u32*) &(*DLDescArray)[i].ptr ); (*DLDescArray)[i].ptr = (void*)((u32)(*DLDescArray)[i].ptr + (u32)hdr); u32swap( &(*DLDescArray)[i].byteLength ); } for(i=0; i<*numPLs; i++) { u32swap( (u32*) &(*PLDescArray)[i].ptr ); (*PLDescArray)[i].ptr = (void*)((u32)(*PLDescArray)[i].ptr + (u32)hdr); u32swap( &(*PLDescArray)[i].byteLength ); } return 0; } #else /*---------------------------------------------------------------------------*/ // Name: GDReadDLFile // // Description: This target-side routine is for reading a file containing // multiple display lists and patch lists. // // Arguments: fName file name // numDLs how many display lists were read // numPLs how many patch lists were read // DLDescArray array describing display lists read // PLDescArray array describing patch lists read // // Returns: 0 no error // -2 error reading file // -3 error opening file // -4 bad file version number // -5 error allocating space for data // /*---------------------------------------------------------------------------*/ s32 GDReadDLFile(const char *fName, u32 *numDLs, u32 *numPLs, GDGList **DLDescArray, GDGList **PLDescArray) { DVDFileInfo finfo; u32 length; u32 i; u8 *buf; GDLFileHeader *hdr; *numDLs = *numPLs = 0; *DLDescArray = *PLDescArray = NULL; if (FALSE == DVDOpen(fName, &finfo)) { OSReport("Can't open file %s\n", fName); return -3; } length = DVDGetLength(&finfo); if( NULL == (buf = OSAlloc(OSRoundUp32B(length))) ) { OSReport("Alloc failed\n"); DVDClose(&finfo); return -5; } if (OSRoundUp32B(length) != DVDRead(&finfo, buf, (s32)OSRoundUp32B(length), 0)) { OSReport("Error occurred when reading %s\n", fName); DVDClose(&finfo); OSFree(buf); return -2; } DVDClose(&finfo); hdr = (GDLFileHeader *) buf; if (hdr->versionNumber != GDFileVersionNumber) { OSReport("Bad version number for GDL file %s\n", fName); OSFree(buf); return -4; } *numDLs = hdr->numDLs; *numPLs = hdr->numPLs; *DLDescArray = (GDGList *) ( (u32) hdr->DLDescArray + (u32) hdr ); *PLDescArray = (GDGList *) ( (u32) hdr->PLDescArray + (u32) hdr ); // Convert offsets into pointers for(i=0; i<*numDLs; i++) { (*DLDescArray)[i].ptr = (void*)((u32)(*DLDescArray)[i].ptr + (u32)hdr); } for(i=0; i<*numPLs; i++) { (*PLDescArray)[i].ptr = (void*)((u32)(*PLDescArray)[i].ptr + (u32)hdr); } return 0; } #endif