Commit | Line | Data |
3e09a0ee |
1 | /*****************************************************************************/ |
2 | /* wave.cpp Copyright (c) Ladislav Zezula 2003 */ |
3 | /*---------------------------------------------------------------------------*/ |
4 | /* This module contains decompression methods used by Storm.dll to decompress*/ |
5 | /* WAVe files. Thanks to Tom Amigo for releasing his sources. */ |
6 | /*---------------------------------------------------------------------------*/ |
7 | /* Date Ver Who Comment */ |
8 | /* -------- ---- --- ------- */ |
9 | /* 11.03.03 1.00 Lad Splitted from Pkware.cpp */ |
10 | /* 20.05.03 2.00 Lad Added compression */ |
11 | /*****************************************************************************/ |
12 | |
13 | #include "wave.h" |
14 | |
15 | //------------------------------------------------------------------------------ |
16 | // Structures |
17 | |
18 | union TByteAndWordPtr |
19 | { |
20 | unsigned short * pw; |
21 | unsigned char * pb; |
22 | }; |
23 | |
24 | //----------------------------------------------------------------------------- |
25 | // Tables necessary dor decompression |
26 | |
27 | static unsigned long Table1503F120[] = |
28 | { |
29 | 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000006, |
30 | 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007, |
31 | 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007, |
32 | 0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000006, 0xFFFFFFFF, 0x00000008 |
33 | }; |
34 | |
35 | static unsigned long Table1503F1A0[] = |
36 | { |
37 | 0x00000007, 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E, |
38 | 0x00000010, 0x00000011, 0x00000013, 0x00000015, 0x00000017, 0x00000019, 0x0000001C, 0x0000001F, |
39 | 0x00000022, 0x00000025, 0x00000029, 0x0000002D, 0x00000032, 0x00000037, 0x0000003C, 0x00000042, |
40 | 0x00000049, 0x00000050, 0x00000058, 0x00000061, 0x0000006B, 0x00000076, 0x00000082, 0x0000008F, |
41 | 0x0000009D, 0x000000AD, 0x000000BE, 0x000000D1, 0x000000E6, 0x000000FD, 0x00000117, 0x00000133, |
42 | 0x00000151, 0x00000173, 0x00000198, 0x000001C1, 0x000001EE, 0x00000220, 0x00000256, 0x00000292, |
43 | 0x000002D4, 0x0000031C, 0x0000036C, 0x000003C3, 0x00000424, 0x0000048E, 0x00000502, 0x00000583, |
44 | 0x00000610, 0x000006AB, 0x00000756, 0x00000812, 0x000008E0, 0x000009C3, 0x00000ABD, 0x00000BD0, |
45 | 0x00000CFF, 0x00000E4C, 0x00000FBA, 0x0000114C, 0x00001307, 0x000014EE, 0x00001706, 0x00001954, |
46 | 0x00001BDC, 0x00001EA5, 0x000021B6, 0x00002515, 0x000028CA, 0x00002CDF, 0x0000315B, 0x0000364B, |
47 | 0x00003BB9, 0x000041B2, 0x00004844, 0x00004F7E, 0x00005771, 0x0000602F, 0x000069CE, 0x00007462, |
48 | 0x00007FFF |
49 | }; |
50 | |
51 | //---------------------------------------------------------------------------- |
52 | // CompressWave |
53 | |
54 | int CompressWave(unsigned char * pbOutBuffer, int dwOutLength, short * pwInBuffer, int dwInLength, int nChannels, int nCmpLevel) |
55 | { |
56 | TByteAndWordPtr out; // Output buffer |
57 | long nArray3[2]; // EBP-48 |
58 | long nArray2[2]; // EBP-40 |
59 | long nArray1[2]; // EBP-38 |
60 | long nWords; // EBP-30 |
61 | unsigned EBP2C; // EBP-2C |
62 | long nRemains = dwOutLength; // EBP-28 : Number of bytes remaining |
63 | long nCmpType2; // EBP-24 |
64 | unsigned dwStopBit; // EBP-20 |
65 | long EBP1C; // EBP-1C |
66 | unsigned dwBitBuff; // EBP-18 |
67 | // char * pbOutPos = pbOutBuffer; // EBP-14 : Saved pointer to the output buffer |
68 | long nLength; // EBP-10 : |
69 | long nIndex; // EBP-0C : |
70 | // short * pwOutPos = pwInBuffer; // EBP-08 : Current output pointer |
71 | // EBP-04 : |
72 | unsigned short wCmp; // EBP-02 : |
73 | unsigned dwBit; // EBP+08 : A Bit |
74 | long nTableValue; |
75 | long nOneWord; |
76 | long nValue; |
77 | |
78 | if(dwInLength < 2) |
79 | return 2; |
80 | |
81 | // ebx = nChannels; |
82 | wCmp = (unsigned char)(nCmpLevel - 1); |
83 | out.pb = pbOutBuffer; |
84 | *out.pb++ = 0; |
85 | *out.pb++ = (unsigned char)wCmp; |
86 | |
87 | if((out.pb - pbOutBuffer + nChannels * 2) > nRemains) |
88 | return out.pb - pbOutBuffer + nChannels * 2; |
89 | |
90 | nArray1[0] = nArray1[1] = 0x2C; |
91 | |
92 | if(nChannels > 0) |
93 | { |
94 | for(int i = 0; i < nChannels; i++) |
95 | { |
96 | nOneWord = *pwInBuffer++; |
97 | *out.pw++ = (unsigned short)nOneWord; |
98 | nArray2[i] = nOneWord; |
99 | } |
100 | } |
101 | |
102 | nLength = dwInLength; |
103 | if(nLength < 0) // mov eax, dwInLength; cdq; sub eax, edx; |
104 | nLength++; |
105 | nLength = (nLength / 2) - (out.pb - pbOutBuffer); |
106 | nLength = (nLength < 0) ? 0 : nLength; |
107 | nCmpType2 = nChannels; |
108 | |
109 | nIndex = nChannels - 1; // edi |
110 | nWords = dwInLength / 2; // eax |
111 | if(nWords <= nChannels) |
112 | return out.pb - pbOutBuffer; |
113 | |
114 | // ebx - nChannels |
115 | // ecx - pwOutPos |
116 | do // 1500F02D |
117 | { |
118 | if((out.pb - pbOutBuffer + 2) > nRemains) |
119 | return out.pb - pbOutBuffer + 2; |
120 | |
121 | if(nChannels == 2) |
122 | nIndex = (nIndex == 0) ? 1 : 0; |
123 | |
124 | nOneWord = *pwInBuffer++; // ecx - nOneWord |
125 | // esi - nArray2[nIndex] |
126 | nValue = nOneWord - nArray2[nIndex]; |
127 | if(nValue < 0) |
128 | nValue = ~nValue + 1; // eax |
129 | |
130 | unsigned ebx = (nOneWord >= nArray2[nIndex]) ? 1 : 0; |
131 | // esi - nArray1[nIndex] |
132 | // edx - Table1503F1A0[nArray1[nIndex]] |
133 | nArray3[nIndex] = nOneWord; |
134 | |
135 | // edi - Table1503F1A0[nArray1[nIndex]] >> nCmpLevel |
136 | ebx = (ebx - 1) & 0x40; |
137 | dwStopBit = nCmpLevel; |
138 | |
139 | // edi - nIndex; |
140 | nTableValue = Table1503F1A0[nArray1[nIndex]]; |
141 | if(nValue < (nTableValue >> nCmpLevel)) |
142 | { |
143 | if(nArray1[nIndex] != 0) |
144 | nArray1[nIndex]--; |
145 | *out.pb++ = 0x80; |
146 | } |
147 | else |
148 | { |
149 | while(nValue > nTableValue * 2) |
150 | { // 1500F0C0 |
151 | if(nArray1[nIndex] >= 0x58 || nLength == 0) |
152 | break; |
153 | |
154 | nArray1[nIndex] += 8; |
155 | if(nArray1[nIndex] > 0x58) |
156 | nArray1[nIndex] = 0x58; |
157 | |
158 | nTableValue = Table1503F1A0[nArray1[nIndex]]; |
159 | *out.pb++ = 0x81; |
160 | nLength--; |
161 | } |
162 | |
163 | dwBitBuff = 0; |
164 | EBP2C = nTableValue >> wCmp; |
165 | unsigned esi = 1 << (dwStopBit - 2); |
166 | EBP1C = 0; |
167 | dwBit = 1; |
168 | dwStopBit = 0x20; |
169 | |
170 | if(esi <= 0x20) |
171 | dwStopBit = esi; |
172 | for(;;) |
173 | { |
174 | // esi = EBP1C + nTableValue; |
175 | if((EBP1C + nTableValue) <= nValue) |
176 | { |
177 | EBP1C += nTableValue; |
178 | dwBitBuff |= dwBit; |
179 | } |
180 | if(dwBit == dwStopBit) |
181 | break; |
182 | |
183 | nTableValue >>= 1; |
184 | dwBit <<= 1; |
185 | } |
186 | |
187 | nValue = nArray2[nIndex]; |
188 | if(ebx != 0) |
189 | { |
190 | nValue -= (EBP1C + EBP2C); |
191 | if(nValue < (int)0xFFFF8000) |
192 | nValue = (int)0xFFFF8000; |
193 | } |
194 | else |
195 | { |
196 | nValue += (EBP1C + EBP2C); |
197 | if(nValue > 0x00007FFF) |
198 | nValue = 0x00007FFF; |
199 | } |
200 | |
201 | nArray2[nIndex] = nValue; |
202 | *out.pb++ = (unsigned char)(dwBitBuff | ebx); |
203 | nTableValue = Table1503F120[dwBitBuff & 0x1F]; |
204 | nArray1[nIndex] += nTableValue; |
205 | if(nArray1[nIndex] < 0) |
206 | nArray1[nIndex] = 0; |
207 | else if(nArray1[nIndex] > 0x58) |
208 | nArray1[nIndex] = 0x58; |
209 | } |
210 | // 1500F1D8 |
211 | } |
212 | while(++nCmpType2 < nWords); |
213 | |
214 | return out.pb - pbOutBuffer; |
215 | } |
216 | |
217 | //---------------------------------------------------------------------------- |
218 | // DecompressWave |
219 | |
220 | // 1500F230 |
221 | int DecompressWave(unsigned char * pbOutBuffer, int dwOutLength, unsigned char * pbInBuffer, int dwInLength, int nChannels) |
222 | { |
223 | TByteAndWordPtr out; |
224 | TByteAndWordPtr in; |
225 | unsigned char * pbInEnd = pbInBuffer + dwInLength; // End on input buffer |
226 | unsigned long index; |
227 | long nArray1[2]; |
228 | long nArray2[2]; |
229 | |
230 | out.pb = pbOutBuffer; |
231 | in.pb = pbInBuffer; |
232 | nArray1[0] = 0x2C; |
233 | nArray1[1] = 0x2C; |
234 | in.pw++; |
235 | |
236 | // 15007AD7 |
237 | if(nChannels > 0) |
238 | { |
239 | for(int count = 0; count < nChannels; count++) |
240 | { |
241 | long temp; |
242 | |
243 | temp = *(short *)in.pw++; |
244 | nArray2[count] = temp; |
245 | |
246 | if(dwOutLength < 2) |
247 | return out.pb - pbOutBuffer; |
248 | |
249 | *out.pw++ = (unsigned short)temp; |
250 | dwOutLength -= 2; |
251 | } |
252 | } |
253 | |
254 | index = nChannels - 1; |
255 | while(in.pb < pbInEnd) |
256 | { |
257 | unsigned char oneByte = *in.pb++; |
258 | |
259 | if(nChannels == 2) |
260 | index = (index == 0) ? 1 : 0; |
261 | |
262 | // Get one byte from input buffer |
263 | // 15007B25 |
264 | if(oneByte & 0x80) |
265 | { |
266 | // 15007B32 |
267 | switch(oneByte & 0x7F) |
268 | { |
269 | case 0: // 15007B8E |
270 | if(nArray1[index] != 0) |
271 | nArray1[index]--; |
272 | |
273 | if(dwOutLength < 2) |
274 | break; |
275 | |
276 | *out.pw++ = (unsigned short)nArray2[index]; |
277 | dwOutLength -= 2; |
278 | continue; |
279 | |
280 | case 1: // 15007B72 |
281 | nArray1[index] += 8; // EBX also |
282 | if(nArray1[index] > 0x58) |
283 | nArray1[index] = 0x58; |
284 | if(nChannels == 2) |
285 | index = (index == 0) ? 1 : 0; |
286 | continue; |
287 | |
288 | case 2: |
289 | continue; |
290 | |
291 | default: |
292 | nArray1[index] -= 8; |
293 | if(nArray1[index] < 0) |
294 | nArray1[index] = 0; |
295 | |
296 | if(nChannels != 2) |
297 | continue; |
298 | |
299 | index = (index == 0) ? 1 : 0; |
300 | continue; |
301 | } |
302 | } |
303 | else |
304 | { |
305 | unsigned long temp1 = Table1503F1A0[nArray1[index]]; // EDI |
306 | unsigned long temp2 = temp1 >> pbInBuffer[1]; // ESI |
307 | long temp3 = nArray2[index]; // ECX |
308 | |
309 | if(oneByte & 0x01) // EBX = oneByte |
310 | temp2 += (temp1 >> 0); |
311 | |
312 | if(oneByte & 0x02) |
313 | temp2 += (temp1 >> 1); |
314 | |
315 | if(oneByte & 0x04) |
316 | temp2 += (temp1 >> 2); |
317 | |
318 | if(oneByte & 0x08) |
319 | temp2 += (temp1 >> 3); |
320 | |
321 | if(oneByte & 0x10) |
322 | temp2 += (temp1 >> 4); |
323 | |
324 | if(oneByte & 0x20) |
325 | temp2 += (temp1 >> 5); |
326 | |
327 | if(oneByte & 0x40) |
328 | { |
329 | temp3 -= temp2; |
330 | if(temp3 <= (long)0xFFFF8000) |
331 | temp3 = (long)0xFFFF8000; |
332 | } |
333 | else |
334 | { |
335 | temp3 += temp2; |
336 | if(temp3 >= 0x7FFF) |
337 | temp3 = 0x7FFF; |
338 | } |
339 | nArray2[index] = temp3; |
340 | if(dwOutLength < 2) |
341 | break; |
342 | |
343 | temp2 = nArray1[index]; |
344 | oneByte &= 0x1F; |
345 | |
346 | *out.pw++ = (unsigned short)temp3; |
347 | dwOutLength -= 2; |
348 | |
349 | temp2 += Table1503F120[oneByte]; |
350 | nArray1[index] = temp2; |
351 | |
352 | if(nArray1[index] < 0) |
353 | nArray1[index] = 0; |
354 | else if(nArray1[index] > 0x58) |
355 | nArray1[index] = 0x58; |
356 | } |
357 | } |
358 | return (out.pb - pbOutBuffer); |
359 | } |
360 | |