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