1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: tpl_crc32.cpp
4
5 Copyright (C)2009-2012 Nintendo Co., Ltd. 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 $Rev: 46347 $
14 *---------------------------------------------------------------------------*/
15
16 #include <stdlib.h>
17 #include <nn/util.h>
18 #include <nn/tpl.h>
19 #include <cstring>
20
21 #include "tpl_crc32.h"
22 #include "tpl_Internal.h"
23
24 namespace nn { namespace tpl { namespace CTR {
25
26
27 static const unsigned int _crcTable_[256] =
28 {
29 0x00000000,0x77073096,0xee0e612c,0x990951ba,
30 0x076dc419,0x706af48f,0xe963a535,0x9e6495a3,
31 0x0edb8832,0x79dcb8a4,0xe0d5e91e,0x97d2d988,
32 0x09b64c2b,0x7eb17cbd,0xe7b82d07,0x90bf1d91,
33 0x1db71064,0x6ab020f2,0xf3b97148,0x84be41de,
34 0x1adad47d,0x6ddde4eb,0xf4d4b551,0x83d385c7,
35 0x136c9856,0x646ba8c0,0xfd62f97a,0x8a65c9ec,
36 0x14015c4f,0x63066cd9,0xfa0f3d63,0x8d080df5,
37 0x3b6e20c8,0x4c69105e,0xd56041e4,0xa2677172,
38 0x3c03e4d1,0x4b04d447,0xd20d85fd,0xa50ab56b,
39 0x35b5a8fa,0x42b2986c,0xdbbbc9d6,0xacbcf940,
40 0x32d86ce3,0x45df5c75,0xdcd60dcf,0xabd13d59,
41 0x26d930ac,0x51de003a,0xc8d75180,0xbfd06116,
42 0x21b4f4b5,0x56b3c423,0xcfba9599,0xb8bda50f,
43 0x2802b89e,0x5f058808,0xc60cd9b2,0xb10be924,
44 0x2f6f7c87,0x58684c11,0xc1611dab,0xb6662d3d,
45 0x76dc4190,0x01db7106,0x98d220bc,0xefd5102a,
46 0x71b18589,0x06b6b51f,0x9fbfe4a5,0xe8b8d433,
47 0x7807c9a2,0x0f00f934,0x9609a88e,0xe10e9818,
48 0x7f6a0dbb,0x086d3d2d,0x91646c97,0xe6635c01,
49 0x6b6b51f4,0x1c6c6162,0x856530d8,0xf262004e,
50 0x6c0695ed,0x1b01a57b,0x8208f4c1,0xf50fc457,
51 0x65b0d9c6,0x12b7e950,0x8bbeb8ea,0xfcb9887c,
52 0x62dd1ddf,0x15da2d49,0x8cd37cf3,0xfbd44c65,
53 0x4db26158,0x3ab551ce,0xa3bc0074,0xd4bb30e2,
54 0x4adfa541,0x3dd895d7,0xa4d1c46d,0xd3d6f4fb,
55 0x4369e96a,0x346ed9fc,0xad678846,0xda60b8d0,
56 0x44042d73,0x33031de5,0xaa0a4c5f,0xdd0d7cc9,
57 0x5005713c,0x270241aa,0xbe0b1010,0xc90c2086,
58 0x5768b525,0x206f85b3,0xb966d409,0xce61e49f,
59 0x5edef90e,0x29d9c998,0xb0d09822,0xc7d7a8b4,
60 0x59b33d17,0x2eb40d81,0xb7bd5c3b,0xc0ba6cad,
61 0xedb88320,0x9abfb3b6,0x03b6e20c,0x74b1d29a,
62 0xead54739,0x9dd277af,0x04db2615,0x73dc1683,
63 0xe3630b12,0x94643b84,0x0d6d6a3e,0x7a6a5aa8,
64 0xe40ecf0b,0x9309ff9d,0x0a00ae27,0x7d079eb1,
65 0xf00f9344,0x8708a3d2,0x1e01f268,0x6906c2fe,
66 0xf762575d,0x806567cb,0x196c3671,0x6e6b06e7,
67 0xfed41b76,0x89d32be0,0x10da7a5a,0x67dd4acc,
68 0xf9b9df6f,0x8ebeeff9,0x17b7be43,0x60b08ed5,
69 0xd6d6a3e8,0xa1d1937e,0x38d8c2c4,0x4fdff252,
70 0xd1bb67f1,0xa6bc5767,0x3fb506dd,0x48b2364b,
71 0xd80d2bda,0xaf0a1b4c,0x36034af6,0x41047a60,
72 0xdf60efc3,0xa867df55,0x316e8eef,0x4669be79,
73 0xcb61b38c,0xbc66831a,0x256fd2a0,0x5268e236,
74 0xcc0c7795,0xbb0b4703,0x220216b9,0x5505262f,
75 0xc5ba3bbe,0xb2bd0b28,0x2bb45a92,0x5cb36a04,
76 0xc2d7ffa7,0xb5d0cf31,0x2cd99e8b,0x5bdeae1d,
77 0x9b64c2b0,0xec63f226,0x756aa39c,0x026d930a,
78 0x9c0906a9,0xeb0e363f,0x72076785,0x05005713,
79 0x95bf4a82,0xe2b87a14,0x7bb12bae,0x0cb61b38,
80 0x92d28e9b,0xe5d5be0d,0x7cdcefb7,0x0bdbdf21,
81 0x86d3d2d4,0xf1d4e242,0x68ddb3f8,0x1fda836e,
82 0x81be16cd,0xf6b9265b,0x6fb077e1,0x18b74777,
83 0x88085ae6,0xff0f6a70,0x66063bca,0x11010b5c,
84 0x8f659eff,0xf862ae69,0x616bffd3,0x166ccf45,
85 0xa00ae278,0xd70dd2ee,0x4e048354,0x3903b3c2,
86 0xa7672661,0xd06016f7,0x4969474d,0x3e6e77db,
87 0xaed16a4a,0xd9d65adc,0x40df0b66,0x37d83bf0,
88 0xa9bcae53,0xdebb9ec5,0x47b2cf7f,0x30b5ffe9,
89 0xbdbdf21c,0xcabac28a,0x53b39330,0x24b4a3a6,
90 0xbad03605,0xcdd70693,0x54de5729,0x23d967bf,
91 0xb3667a2e,0xc4614ab8,0x5d681b02,0x2a6f2b94,
92 0xb40bbe37,0xc30c8ea1,0x5a05df1b,0x2d02ef8d,
93 };
94
95 //----------------------------------------------------------------------------
96 // Calculate CRC32 code for data block.
calculate_crc32(const void * data,unsigned int size)97 unsigned int calculate_crc32(
98 const void *data,
99 unsigned int size)
100 {
101 unsigned int i;
102 const unsigned char *m = (const unsigned char *)(data);
103 unsigned int crc = 0xffffffff;
104
105 for(i = 0; i < size; i++)
106 {
107 crc = (crc >> 8) ^ _crcTable_[(crc & 0xFF) ^ (unsigned int)(*m) ];
108 m++;
109 }
110
111 return crc ^ 0xffffffff;
112 }
113
114 //----------------------------------------------------------------------------
115 // Searches for structure that has CRC32 at the start. (Binary search)
search_crc32_index(const void * _base,unsigned int num,unsigned int width,unsigned int crc)116 int search_crc32_index(
117 const void *_base, unsigned int num, unsigned int width, unsigned int crc)
118 {
119 int n = 0;
120 int m = (int)num - 1;
121 const char *base = (const char *)_base;
122
123 while(n <= m)
124 {
125 int c = (n + m) / 2;
126 unsigned int k = *(const unsigned int *)(base + (width * c));
127
128 // If the data CRC matches the search key, searches for same start values and returns those indices considering that the same value may appear consecutively.
129 //
130 if(k == crc)
131 {
132 while(0 < c)
133 {
134 unsigned int kk = *(const unsigned int *)(base + (width * (c - 1)));
135 if(kk != crc) break;
136 c--;
137 }
138 return c;
139 }
140
141 // Assuming data is in order by alignment, repeat the process by refining search targets to front and back halves.
142 //
143 if(k < crc)
144 {
145 // Searches the back half since searching for larger values.
146 n = c + 1;
147 }
148 else /* if(crc < k) */
149 {
150 // Searches the front half since searching for smaller values.
151 m = c - 1;
152 }
153 }
154
155 // Returns -1 if no matching CRC is found.
156 return -1;
157 }
158
159
160 //----------------------------------------------------------------------------
161 // Gets the texture path string from the texture package memory image.
getTextureFilePath(const void * infoData,int index)162 const char *getTextureFilePath(const void *infoData, int index)
163 {
164 const CtrTexturePackageHeader *header =
165 reinterpret_cast<const CtrTexturePackageHeader *>(infoData);
166 NN_TASSERT_(index < header->numTexture);
167
168 const CtrTextureInfo *texInfo =
169 reinterpret_cast<const CtrTextureInfo *>(header + 1) + index;
170
171 const char *szTexPath =
172 reinterpret_cast<const char *>(infoData) + texInfo->filePathOffset;
173
174 return szTexPath;
175 }
176
cmpTpkSearchData(const void * data,const void * value)177 int cmpTpkSearchData(const void *data, const void *value)
178 {
179 const CtrTextureHash &hash = *(const CtrTextureHash *)data;
180 const TPK_SEARCH_DATA &s = *(const TPK_SEARCH_DATA *)value;
181
182 // Gets filename recorded in TPK from header information.
183 const char *filePath = getTextureFilePath(s.infoData, hash.index);
184
185 // Compares the filename.
186 return (::std::strncmp(filePath, s.szFileName, s.fileNameLen) == 0)? 1: 0;
187 }
188
189 //----------------------------------------------------------------------------
190 // Searches for structure that has CRC32 at the start. (Binary search)
search_crc32_data(const void * _base,unsigned int num,unsigned int width,unsigned int crc,const void * value)191 int search_crc32_data(
192 const void *_base, unsigned int num, unsigned int width, unsigned int crc,
193 const void *value)
194 {
195 const char *base = (const char *)_base;
196
197 // First searches for the index with the CRC32 code.
198 // If there is no candidate at this time, -1 is returned and process terminates.
199 int t = search_crc32_index(_base, num, width, crc);
200 if(t < 0) return -1;
201
202 // Since there can be several of same CRC32 code lined up, compare data in a range where the CRC32 codes matche.
203 //
204 for(; t < (int)num; t++)
205 {
206 // If the CRC32 code is different, no match.
207 const unsigned int *k = (const unsigned int *)(base + (width * t));
208 if(*k != crc) return -1;
209
210 // Check if the data is really a search target by using a comparison function.
211 if(cmpTpkSearchData((const void*)k, value) != 0)
212 {
213 return t;
214 }
215 }
216 return -1;
217 }
218
219
220 }}} // Namespace
221