1 /*
2 	crc.c
3 
4 	Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
5 	and the "Aleph One" developers.
6 
7 	This program is free software; you can redistribute it and/or modify
8 	it under the terms of the GNU General Public License as published by
9 	the Free Software Foundation; either version 3 of the License, or
10 	(at your option) any later version.
11 
12 	This program is distributed in the hope that it will be useful,
13 	but WITHOUT ANY WARRANTY; without even the implied warranty of
14 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 	GNU General Public License for more details.
16 
17 	This license is contained in the file "COPYING",
18 	which is included with this source code; it is available online at
19 	http://www.gnu.org/licenses/gpl.html
20 
21 	Sunday, March 5, 1995 6:21:30 PM
22 
23 	CRC Checksum generation for a file.
24 
25 Aug 15, 2000 (Loren Petrich):
26 	Using object-oriented file handler
27 
28 Nov 6, 2000 (Loren Petrich);
29 	Suppressed commented-out FileSpecifier function
30 */
31 
32 #include <stdlib.h>
33 
34 #include "cseries.h"
35 #include "FileHandler.h"
36 #include "crc.h"
37 
38 /* ---------- constants */
39 #define TABLE_SIZE (256)
40 #define CRC32_POLYNOMIAL 0xEDB88320L
41 #define BUFFER_SIZE 1024
42 
43 /* ---------- local data */
44 static uint32 *crc_table= NULL;
45 
46 /* ---------- local prototypes ------- */
47 static uint32 calculate_file_crc(unsigned char *buffer,
48 	short buffer_size, OpenedFile& OFile);
49 static uint32 calculate_buffer_crc(int32 count, uint32 crc, void *buffer);
50 static bool build_crc_table(void);
51 static void free_crc_table(void);
52 
53 /* -------------- Entry Point ----------- */
calculate_crc_for_file(FileSpecifier & File)54 uint32 calculate_crc_for_file(FileSpecifier& File)
55 {
56 	uint32 crc = 0;
57 
58 	OpenedFile OFile;
59 	if (File.Open(OFile))
60 	{
61 		crc= calculate_crc_for_opened_file(OFile);
62 		OFile.Close();
63 	}
64 
65 	return crc;
66 }
67 
calculate_crc_for_opened_file(OpenedFile & OFile)68 uint32 calculate_crc_for_opened_file(OpenedFile& OFile)
69 {
70 	uint32 crc = 0;
71 	unsigned char *buffer;
72 
73 	/* Build the crc table */
74 	if(build_crc_table())
75 	{
76 		buffer = new byte[BUFFER_SIZE];
77 		if(buffer)
78 		{
79 			crc= calculate_file_crc(buffer, BUFFER_SIZE, OFile);
80 			delete []buffer;
81 		}
82 
83 		/* free the crc table! */
84 		free_crc_table();
85 	}
86 
87 	return crc;
88 }
89 
90 /* Calculate the crc for a file using the given buffer.. */
calculate_data_crc(unsigned char * buffer,int32 length)91 uint32 calculate_data_crc(
92 	unsigned char *buffer,
93 	int32 length)
94 {
95 	uint32 crc = 0;
96 
97 	assert(buffer);
98 
99 	/* Build the crc table */
100 	if(build_crc_table())
101 	{
102 		/* The odd permutions ensure that we get the same crc as for a file */
103 		crc = 0xFFFFFFFFL;
104 		crc = calculate_buffer_crc(length, crc, buffer);
105 		crc ^= 0xFFFFFFFFL;
106 
107 		/* free the crc table! */
108 		free_crc_table();
109 	}
110 
111 	return crc;
112 }
113 
114 /* ---------------- Private Code --------------- */
build_crc_table(void)115 static bool build_crc_table(
116 	void)
117 {
118 	bool success= false;
119 
120 	assert(!crc_table);
121 	crc_table= new uint32[TABLE_SIZE];
122 	if(crc_table)
123 	{
124 		/* Build the table */
125 		short index, j;
126 		uint32 crc;
127 
128 		for(index= 0; index<TABLE_SIZE; ++index)
129 		{
130 			crc= index;
131 			for(j=0; j<8; j++)
132 			{
133 				if(crc & 1) crc=(crc>>1) ^ CRC32_POLYNOMIAL;
134 				else crc>>=1;
135 			}
136 			crc_table[index] = crc;
137 		}
138 
139 		success= true;
140 	}
141 
142 	return success;
143 }
144 
free_crc_table(void)145 static void free_crc_table(
146 	void)
147 {
148 	assert(crc_table);
149 	delete []crc_table;
150 	crc_table= NULL;
151 }
152 
153 /* Calculate for a block of data incrementally */
calculate_buffer_crc(int32 count,uint32 crc,void * buffer)154 static uint32 calculate_buffer_crc(
155 	int32 count,
156 	uint32 crc,
157 	void *buffer)
158 {
159 	unsigned char *p;
160 	uint32 a;
161 	uint32 b;
162 
163 	p= (unsigned char *) buffer;
164 	while (count--)
165 	{
166 		a= (crc >> 8) & 0x00FFFFFFL;
167 		b= crc_table[((int) crc ^ *p++) & 0xff];
168 		crc= a^b;
169 	}
170 	return crc;
171 }
172 
173 /* Calculate the crc for a file using the given buffer.. */
calculate_file_crc(unsigned char * buffer,short buffer_size,OpenedFile & OFile)174 static uint32 calculate_file_crc(
175 	unsigned char *buffer,
176 	short buffer_size,
177 	OpenedFile& OFile)
178 {
179 	uint32 crc;
180 	int32 count;
181 	int32 file_length, initial_position;
182 
183 	/* Save and restore the initial file position */
184 	if (!OFile.GetPosition(initial_position))
185 		return 0;
186 
187 	/* Get the file_length */
188 	if (!OFile.GetLength(file_length))
189 		return 0;
190 
191 	/* Set to the start of the file */
192 	if (!OFile.SetPosition(0))
193 		return 0;
194 
195 	crc = 0xFFFFFFFFL;
196 	while(file_length)
197 	{
198 		if(file_length>buffer_size)
199 		{
200 			count= buffer_size;
201 		} else {
202 			count= file_length;
203 		}
204 
205 		if (!OFile.Read(count, buffer))
206 			return 0;
207 
208 		crc = calculate_buffer_crc(count, crc, buffer);
209 		file_length -= count;
210 	}
211 
212 	/* Restore the file position */
213 	OFile.SetPosition(initial_position);
214 
215 	return (crc ^= 0xFFFFFFFFL);
216 }
217 
218 /*  crcccitt.c - a demonstration of look up table based CRC
219  *               computation using the non-reversed CCITT_CRC
220  *               polynomial 0x1021 (truncated)
221  *
222  *  Copyright (C) 2000  Jack Klein
223  *                      Macmillan Computer Publishing
224  *  Adapted for Aleph One, 2006, by Gregory Smith
225  *  License: GPL 2 or newer (as above)
226  *
227  *  Jack Klein may be contacted by email at:
228  *     The_C_Guru@yahoo.com
229  *
230  *  ghs: this is from http://home.att.net/~jackklein/C_Unleashed/crcccitt.c
231  */
232 
233 static uint16 crc_ccitt_table [256] =
234 {
235   0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5,
236   0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b,
237   0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210,
238   0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
239   0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c,
240   0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401,
241   0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b,
242   0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
243   0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6,
244   0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738,
245   0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5,
246   0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
247   0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969,
248   0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96,
249   0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc,
250   0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
251   0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03,
252   0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd,
253   0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6,
254   0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
255   0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a,
256   0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb,
257   0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1,
258   0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
259   0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c,
260   0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2,
261   0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb,
262   0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
263   0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447,
264   0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8,
265   0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2,
266   0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
267   0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9,
268   0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827,
269   0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c,
270   0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
271   0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0,
272   0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d,
273   0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07,
274   0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
275   0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba,
276   0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74,
277   0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
278 };
279 
calculate_data_crc_ccitt(unsigned char * data,int32 length)280 uint16 calculate_data_crc_ccitt(unsigned char *data, int32 length)
281 {
282   int32 count;
283   uint32 crc = 0xffff;
284   uint32 temp;
285 
286   for (count = 0; count < length; ++count)
287   {
288     temp = (*data++ ^ (crc >> 8)) & 0xff;
289     crc = crc_ccitt_table[temp] ^ (crc << 8);
290   }
291   return (uint16)(crc ^ 0);
292 }
293