1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - MATH -
3 File: checksum.c
4
5 Copyright 2003-2008 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 $Date:: 2008-11-07#$
14 $Rev: 9262 $
15 $Author:$
16 *---------------------------------------------------------------------------*/
17
18 #include <nitro/math/checksum.h>
19
20 /*---------------------------------------------------------------------------*
21 Name: MATHi_Checksum16Update
22
23 Description: Finds the 16-bit Checksum value.
24
25 Arguments: input: Pointer to input data
26 length: Length of input data
27
28 Returns: Calculation result.
29 *---------------------------------------------------------------------------*/
MATHi_Checksum16Update(const void * input,u32 length)30 static inline u32 MATHi_Checksum16Update(const void *input, u32 length)
31 {
32 u32 sum;
33 u32 n;
34 BOOL fSwap = FALSE;
35
36 sum = 0;
37
38 if (((u32)input) & 1)
39 {
40 sum += (*((u8 *)input) << 8); // BIGENDIAN
41 input = (u8 *)input + 1;
42 length--;
43 fSwap = TRUE;
44 }
45
46 while ((length >> 17) > 0)
47 {
48 length -= (1 << 17);
49 for (n = (1 << 16); n > 0; n--)
50 {
51 sum += *(u16 *)input;
52 input = (u16 *)input + 1;
53 }
54
55 sum = (sum >> 16) + (sum & 0xffff);
56 sum = (u16)((sum >> 16) + sum);
57 }
58
59 for (n = (length >> 1); n > 0; n--)
60 {
61 sum += *(u16 *)input;
62 input = (u16 *)input + 1;
63 }
64
65 if (length & 1)
66 {
67 sum += *((u8 *)input);
68 }
69
70 sum = (sum >> 16) + (sum & 0xffff);
71 sum = (sum >> 16) + (sum & 0xffff);
72
73 if (fSwap)
74 {
75 sum = ((sum << 24) | (sum << 8)) >> 16;
76 }
77
78 return sum;
79 }
80
81 /*---------------------------------------------------------------------------*
82 Name: MATH_Checksum16Update
83
84 Description: Updates the 16bit Checksum value with added data.
85
86 Arguments: context: MATHChecksum16Context structure
87 input: Pointer to input data
88 length: Length of input data
89
90 Returns: None.
91 *---------------------------------------------------------------------------*/
MATH_Checksum16Update(MATHChecksum16Context * context,const void * input,u32 length)92 void MATH_Checksum16Update(MATHChecksum16Context * context, const void *input, u32 length)
93 {
94 u32 sum;
95
96 sum = MATHi_Checksum16Update(input, length);
97
98 sum += *context;
99 sum += (sum >> 16);
100
101 *context = (u16)sum;
102 }
103
104 /*---------------------------------------------------------------------------*
105 Name: MATH_CalcChecksum16
106
107 Description: Calculates the 16bit Checksum.
108
109 Arguments: data: Pointer to input data
110 dataLength: Length of input data
111
112 Returns: Checksum value.
113 *---------------------------------------------------------------------------*/
MATH_CalcChecksum16(const void * data,u32 dataLength)114 u16 MATH_CalcChecksum16(const void *data, u32 dataLength)
115 {
116 u32 sum;
117
118 sum = MATHi_Checksum16Update(data, dataLength);
119
120 return (u16)(~sum);
121 }
122
123 /*---------------------------------------------------------------------------*
124 Name: MATH_Checksum8Update
125
126 Description: Finds the 8-bit Checksum value.
127
128 Arguments: input: Pointer to input data
129 length: Length of input data
130
131 Returns: Calculation result.
132 *---------------------------------------------------------------------------*/
MATHi_Checksum8Update(const void * input,u32 length)133 static inline u32 MATHi_Checksum8Update(const void *input, u32 length)
134 {
135 u32 sum;
136 u32 n;
137
138 sum = 0;
139
140 if (((u32)input) & 1)
141 {
142 sum += *(u8 *)input;
143 input = (u8 *)input + 1;
144 length--;
145 }
146
147 while ((length >> 17) > 0)
148 {
149 length -= (1 << 17);
150 for (n = (1 << 16); n > 0; n--)
151 {
152 sum += *(u16 *)input;
153 input = (u16 *)input + 1;
154 }
155
156 sum = (sum >> 16) + (sum & 0xffff);
157 sum = (u16)(sum + (sum >> 16));
158 }
159
160 for (n = (length >> 1); n > 0; n--)
161 {
162 sum += *(u16 *)input;
163 input = (u16 *)input + 1;
164 }
165
166 if (length & 1)
167 {
168 sum += *((u8 *)input);
169 }
170
171 sum = (sum >> 16) + (sum & 0xffff);
172 sum += (sum >> 16);
173
174 return (u16)sum;
175 }
176
177 /*---------------------------------------------------------------------------*
178 Name: MATH_Checksum8Update
179
180 Description: Updates the 8bit Checksum value with added data.
181
182 Arguments: context: MATHChecksum8Context structure
183 input: Pointer to input data
184 length: Length of input data
185
186 Returns: None.
187 *---------------------------------------------------------------------------*/
MATH_Checksum8Update(MATHChecksum8Context * context,const void * input,u32 length)188 void MATH_Checksum8Update(MATHChecksum8Context * context, const void *input, u32 length)
189 {
190 u32 sum;
191
192 sum = MATHi_Checksum8Update(input, length);
193
194 sum += *context;
195 sum += (sum >> 16);
196
197 *context = (u16)sum;
198 }
199
200 /*---------------------------------------------------------------------------*
201 Name: MATH_CalcChecksum8
202
203 Description: Calculates the 16bit Checksum.
204
205 Arguments: data: Pointer to input data
206 dataLength: Length of input data
207
208 Returns: Checksum value.
209 *---------------------------------------------------------------------------*/
MATH_CalcChecksum8(const void * data,u32 dataLength)210 u8 MATH_CalcChecksum8(const void *data, u32 dataLength)
211 {
212 u32 sum;
213
214 sum = MATHi_Checksum8Update(data, dataLength);
215
216 sum = (sum >> 8) + (sum & 0xff);
217 sum += (sum >> 8);
218
219 return (u8)(~sum);
220 }
221