1 /*---------------------------------------------------------------------------*
2 
3   Copyright (C) Nintendo.  All rights reserved.
4 
5   These coded instructions, statements, and computer programs contain
6   proprietary information of Nintendo of America Inc. and/or Nintendo
7   Company Ltd., and are protected by Federal copyright law.  They may
8   not be disclosed to third parties or copied or duplicated in any form,
9   in whole or in part, without the prior written consent of Nintendo.
10 
11  *---------------------------------------------------------------------------*/
12 
13 #include <stdio.h>
14 #include <string.h>
15 #include <assert.h>
16 #include <types.h>
17 #include <stdlib.h>
18 
19 #include "windows/gx2.h"
20 
21 #include "cafe/gfd.h"
22 #include "gfdFile.h"
23 
GFDWriteFileHeader(FILE * fp,GFDGPUVersion gpuVer,GFDAlignMode alignMode)24 bool GFD_API GFDWriteFileHeader(FILE *fp, GFDGPUVersion gpuVer, GFDAlignMode alignMode)
25 {
26     GFDHeader  header;
27     memset(&header, 0, sizeof(header));
28     header.magic         = GFD_SWAP_8_IN_32(GFD_HEADER_MAGIC);
29     header.size          = GFD_HEADER_SIZE;
30     header.majorVersion  = GFD_HEADER_MAJOR;
31     header.minorVersion  = GFD_HEADER_MINOR;
32     header.gpuVersion    = gpuVer;
33     header.alignMode     = alignMode;
34 
35     return GFDWriteFilePPCData(fp, (GFD_HEADER_SIZE + 3) / 4, GFD_ELEMENT_SIZE_32, (u32 *) &header);
36 }
37 
GFDWriteFileBlockHeader(FILE * fp,GFDBlockType type,u32 size)38 bool GFD_API GFDWriteFileBlockHeader(FILE *fp, GFDBlockType type, u32 size)
39 {
40     GFDBlockHeader  blockHeader;
41     memset(&blockHeader, 0, sizeof(blockHeader));
42     blockHeader.magic        = GFD_SWAP_8_IN_32(GFD_BLOCK_HEADER_MAGIC);
43     blockHeader.size         = GFD_BLOCK_HEADER_SIZE;
44     blockHeader.type         = type;
45     blockHeader.majorVersion        = GFD_BLOCK_HEADER_MAJOR;
46     blockHeader.minorVersion        = GFD_BLOCK_HEADER_MINOR;
47 
48     blockHeader.dataSize   = size;  // following data block size in bytes, doesn't include this header
49 
50     return GFDWriteFilePPCData(fp, (GFD_BLOCK_HEADER_SIZE + 3) / 4, GFD_ELEMENT_SIZE_32, (u32 *) &blockHeader);
51 }
52 
GFDWriteFileGPUData(FILE * fp,u32 numElements,GFDElementSize elemSize,GFDEndianSwapMode swapMode,void * pData)53 bool GFD_API GFDWriteFileGPUData(FILE *fp, u32 numElements, GFDElementSize elemSize, GFDEndianSwapMode swapMode, void *pData)
54 {
55 	size_t retWords = 0;
56 
57     // Set Swap Enable
58 	if(swapMode == GFD_ENDIAN_SWAP_MODE_8_IN_32)
59 	{
60 		u32 scale = GFD_ELEMENT_SIZE_32/elemSize;
61         u32 elems = (numElements + scale - 1)/scale;
62 
63 		// Swap Endian
64  		GFDEndianSwap((u32*)pData, elems, GFD_ELEMENT_SIZE_32);
65 
66 		// Write data
67 		retWords = fwrite((u32*)pData, GFD_ELEMENT_SIZE_32, elems,  fp);
68 
69 		// Revert Endian
70  		GFDEndianSwap((u32*)pData, elems, GFD_ELEMENT_SIZE_32);
71 	}
72 	else if((swapMode == (GFD_ENDIAN_SWAP_MODE_8_IN_32 | GFD_ENDIAN_SWAP_MODE_BIG)) && _GFD_LITTLE_ENDIAN_CPU)
73 	{
74 		u32 scale = GFD_ELEMENT_SIZE_32/elemSize;
75         u32 elems = (numElements + scale - 1)/scale;
76 
77 		// Swap Endian
78 		GFDEndianSwap(pData, numElements, elemSize);
79 
80 		// Swap Endian
81  		GFDEndianSwap((u32*)pData, elems, GFD_ELEMENT_SIZE_32);
82 
83 		// Write data
84 		retWords = fwrite((u32*)pData, GFD_ELEMENT_SIZE_32, elems,  fp);
85 
86 		// Revert Endian
87  		GFDEndianSwap((u32*)pData, elems, GFD_ELEMENT_SIZE_32);
88 
89 	    // Revert Endian
90 		GFDEndianSwap(pData, numElements, elemSize);
91 	}
92 	else if((swapMode == GFD_ENDIAN_SWAP_MODE_BIG) && _GFD_LITTLE_ENDIAN_CPU)
93 	{
94 		// Swap Endian
95 		GFDEndianSwap(pData, numElements, elemSize);
96 
97 		// Write data
98 		retWords = fwrite(pData, elemSize, numElements,  fp);
99 
100 		// Revert Endian
101 		GFDEndianSwap(pData, numElements, elemSize);
102 	}
103 	else
104 	{
105 		// Write data
106 		retWords = fwrite(pData, elemSize, numElements,  fp);
107 	}
108 
109 	if(retWords != numElements)
110 		return false;
111 
112 	return true;
113 }
114 
GFDOpenFile(FILE ** fp,const char * fileName,const char * mode)115 errno_t GFD_API GFDOpenFile(FILE **fp, const char* fileName,  const char *mode)
116 {
117     // ABoggs - Adding more logging to determine why this is failing in autotest. (Bug8147)
118     errno_t err = fopen_s(fp, fileName, mode);
119     if( err != 0 )
120         perror( "An error occurred in GFDOpenFile" );
121     return( err );
122 }
123 
GFDCloseFile(FILE * fp)124 int GFD_API GFDCloseFile(FILE *fp)
125 {
126     return fclose(fp);
127 }
128 
GFDReadFileGPUData(void * pData,u32 numElements,GFDElementSize elemSize,GFDEndianSwapMode swapMode,FILE * fp)129 bool GFD_API GFDReadFileGPUData(void *pData, u32 numElements, GFDElementSize elemSize, GFDEndianSwapMode swapMode, FILE *fp)
130 {
131 	// read data
132 	size_t retWords = fread( pData, elemSize, numElements , fp);
133 
134 	if(retWords != numElements)
135 		return false;
136 
137     // Set Swap Enable
138 	if(swapMode == GFD_ENDIAN_SWAP_MODE_8_IN_32)
139 	{
140 		u32 scale = GFD_ELEMENT_SIZE_32/elemSize;
141         u32 elems = (numElements + scale - 1)/scale;
142 
143 		// Swap Endian
144  		GFDEndianSwap((u32*)pData, elems, GFD_ELEMENT_SIZE_32);
145 	}
146 	else if((swapMode == (GFD_ENDIAN_SWAP_MODE_8_IN_32 | GFD_ENDIAN_SWAP_MODE_BIG)) && _GFD_LITTLE_ENDIAN_CPU)
147 	{
148 		u32 scale = GFD_ELEMENT_SIZE_32/elemSize;
149         u32 elems = (numElements + scale - 1)/scale;
150 
151 		// Swap Endian
152  		GFDEndianSwap((u32*)pData, elems, GFD_ELEMENT_SIZE_32);
153 
154 	    // Swap Endian
155 		GFDEndianSwap(pData, numElements, elemSize);
156 	}
157 	else if((swapMode == GFD_ENDIAN_SWAP_MODE_BIG) && _GFD_LITTLE_ENDIAN_CPU)
158 	{
159     	// Swap Endian
160 		GFDEndianSwap(pData, numElements, elemSize);
161 	}
162 	return true;
163 }
164 
GFDWriteFilePadBlock(FILE * fp,u32 padSize)165 bool GFD_API GFDWriteFilePadBlock(FILE *fp, u32 padSize)
166 {
167 	if(padSize < 0)
168 		return false;
169 
170     // write header for pad header
171     if(!GFDWriteFileBlockHeader(fp, GFD_BLOCK_TYPE_PAD, padSize))
172 		return false;
173 
174 	// seek file pointer for padding
175 	fseek(fp, padSize, SEEK_CUR);
176 
177 	return true;
178 }
179