Line | Count | Source (jump to first uncovered line) |
1 | | #include "rar.hpp" |
2 | | |
3 | | void Unpack::CopyString20(uint Length,uint Distance) |
4 | 0 | { |
5 | 0 | LastDist=OldDist[OldDistPtr++]=Distance; |
6 | 0 | OldDistPtr = OldDistPtr & 3; // Needed if RAR 1.5 file is called after RAR 2.0. |
7 | 0 | LastLength=Length; |
8 | 0 | DestUnpSize-=Length; |
9 | 0 | CopyString(Length,Distance); |
10 | 0 | } |
11 | | |
12 | | |
13 | | void Unpack::Unpack20(bool Solid) |
14 | 0 | { |
15 | 0 | static unsigned char LDecode[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224}; |
16 | 0 | static unsigned char LBits[]= {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5}; |
17 | 0 | static uint DDecode[]={0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576,32768U,49152U,65536,98304,131072,196608,262144,327680,393216,458752,524288,589824,655360,720896,786432,851968,917504,983040}; |
18 | 0 | static unsigned char DBits[]= {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; |
19 | 0 | static unsigned char SDDecode[]={0,4,8,16,32,64,128,192}; |
20 | 0 | static unsigned char SDBits[]= {2,2,3, 4, 5, 6, 6, 6}; |
21 | 0 | uint Bits; |
22 | |
|
23 | 0 | if (Suspended) |
24 | 0 | UnpPtr=WrPtr; |
25 | 0 | else |
26 | 0 | { |
27 | 0 | UnpInitData(Solid); |
28 | 0 | if (!UnpReadBuf()) |
29 | 0 | return; |
30 | 0 | if ((!Solid || !TablesRead2) && !ReadTables20()) |
31 | 0 | return; |
32 | 0 | --DestUnpSize; |
33 | 0 | } |
34 | | |
35 | 0 | while (DestUnpSize>=0) |
36 | 0 | { |
37 | 0 | UnpPtr&=MaxWinMask; |
38 | |
|
39 | 0 | if (Inp.InAddr>ReadTop-30) |
40 | 0 | if (!UnpReadBuf()) |
41 | 0 | break; |
42 | 0 | if (((WrPtr-UnpPtr) & MaxWinMask)<270 && WrPtr!=UnpPtr) |
43 | 0 | { |
44 | 0 | UnpWriteBuf20(); |
45 | 0 | if (Suspended) |
46 | 0 | return; |
47 | 0 | } |
48 | 0 | if (UnpAudioBlock) |
49 | 0 | { |
50 | 0 | uint AudioNumber=DecodeNumber(Inp,&MD[UnpCurChannel]); |
51 | |
|
52 | 0 | if (AudioNumber==256) |
53 | 0 | { |
54 | 0 | if (!ReadTables20()) |
55 | 0 | break; |
56 | 0 | continue; |
57 | 0 | } |
58 | 0 | Window[UnpPtr++]=DecodeAudio((int)AudioNumber); |
59 | 0 | if (++UnpCurChannel==UnpChannels) |
60 | 0 | UnpCurChannel=0; |
61 | 0 | --DestUnpSize; |
62 | 0 | continue; |
63 | 0 | } |
64 | | |
65 | 0 | uint Number=DecodeNumber(Inp,&BlockTables.LD); |
66 | 0 | if (Number<256) |
67 | 0 | { |
68 | 0 | Window[UnpPtr++]=(byte)Number; |
69 | 0 | --DestUnpSize; |
70 | 0 | continue; |
71 | 0 | } |
72 | 0 | if (Number>269) |
73 | 0 | { |
74 | 0 | uint Length=LDecode[Number-=270]+3; |
75 | 0 | if ((Bits=LBits[Number])>0) |
76 | 0 | { |
77 | 0 | Length+=Inp.getbits()>>(16-Bits); |
78 | 0 | Inp.addbits(Bits); |
79 | 0 | } |
80 | |
|
81 | 0 | uint DistNumber=DecodeNumber(Inp,&BlockTables.DD); |
82 | 0 | uint Distance=DDecode[DistNumber]+1; |
83 | 0 | if ((Bits=DBits[DistNumber])>0) |
84 | 0 | { |
85 | 0 | Distance+=Inp.getbits()>>(16-Bits); |
86 | 0 | Inp.addbits(Bits); |
87 | 0 | } |
88 | |
|
89 | 0 | if (Distance>=0x2000) |
90 | 0 | { |
91 | 0 | Length++; |
92 | 0 | if (Distance>=0x40000L) |
93 | 0 | Length++; |
94 | 0 | } |
95 | |
|
96 | 0 | CopyString20(Length,Distance); |
97 | 0 | continue; |
98 | 0 | } |
99 | 0 | if (Number==269) |
100 | 0 | { |
101 | 0 | if (!ReadTables20()) |
102 | 0 | break; |
103 | 0 | continue; |
104 | 0 | } |
105 | 0 | if (Number==256) |
106 | 0 | { |
107 | 0 | CopyString20(LastLength,LastDist); |
108 | 0 | continue; |
109 | 0 | } |
110 | 0 | if (Number<261) |
111 | 0 | { |
112 | 0 | uint Distance=OldDist[(OldDistPtr-(Number-256)) & 3]; |
113 | 0 | uint LengthNumber=DecodeNumber(Inp,&BlockTables.RD); |
114 | 0 | uint Length=LDecode[LengthNumber]+2; |
115 | 0 | if ((Bits=LBits[LengthNumber])>0) |
116 | 0 | { |
117 | 0 | Length+=Inp.getbits()>>(16-Bits); |
118 | 0 | Inp.addbits(Bits); |
119 | 0 | } |
120 | 0 | if (Distance>=0x101) |
121 | 0 | { |
122 | 0 | Length++; |
123 | 0 | if (Distance>=0x2000) |
124 | 0 | { |
125 | 0 | Length++; |
126 | 0 | if (Distance>=0x40000) |
127 | 0 | Length++; |
128 | 0 | } |
129 | 0 | } |
130 | 0 | CopyString20(Length,Distance); |
131 | 0 | continue; |
132 | 0 | } |
133 | 0 | if (Number<270) |
134 | 0 | { |
135 | 0 | uint Distance=SDDecode[Number-=261]+1; |
136 | 0 | if ((Bits=SDBits[Number])>0) |
137 | 0 | { |
138 | 0 | Distance+=Inp.getbits()>>(16-Bits); |
139 | 0 | Inp.addbits(Bits); |
140 | 0 | } |
141 | 0 | CopyString20(2,Distance); |
142 | 0 | continue; |
143 | 0 | } |
144 | 0 | } |
145 | 0 | ReadLastTables(); |
146 | 0 | UnpWriteBuf20(); |
147 | 0 | } |
148 | | |
149 | | |
150 | | void Unpack::UnpWriteBuf20() |
151 | 0 | { |
152 | 0 | if (UnpPtr!=WrPtr) |
153 | 0 | UnpSomeRead=true; |
154 | 0 | if (UnpPtr<WrPtr) |
155 | 0 | { |
156 | 0 | UnpIO->UnpWrite(&Window[WrPtr],-(int)WrPtr & MaxWinMask); |
157 | 0 | UnpIO->UnpWrite(Window,UnpPtr); |
158 | 0 | UnpAllBuf=true; |
159 | 0 | } |
160 | 0 | else |
161 | 0 | UnpIO->UnpWrite(&Window[WrPtr],UnpPtr-WrPtr); |
162 | 0 | WrPtr=UnpPtr; |
163 | 0 | } |
164 | | |
165 | | |
166 | | bool Unpack::ReadTables20() |
167 | 0 | { |
168 | 0 | byte BitLength[BC20]; |
169 | 0 | byte Table[MC20*4]; |
170 | 0 | if (Inp.InAddr>ReadTop-25) |
171 | 0 | if (!UnpReadBuf()) |
172 | 0 | return false; |
173 | 0 | uint BitField=Inp.getbits(); |
174 | 0 | UnpAudioBlock=(BitField & 0x8000)!=0; |
175 | |
|
176 | 0 | if (!(BitField & 0x4000)) |
177 | 0 | memset(UnpOldTable20,0,sizeof(UnpOldTable20)); |
178 | 0 | Inp.addbits(2); |
179 | |
|
180 | 0 | uint TableSize; |
181 | 0 | if (UnpAudioBlock) |
182 | 0 | { |
183 | 0 | UnpChannels=((BitField>>12) & 3)+1; |
184 | 0 | if (UnpCurChannel>=UnpChannels) |
185 | 0 | UnpCurChannel=0; |
186 | 0 | Inp.addbits(2); |
187 | 0 | TableSize=MC20*UnpChannels; |
188 | 0 | } |
189 | 0 | else |
190 | 0 | TableSize=NC20+DC20+RC20; |
191 | |
|
192 | 0 | for (uint I=0;I<BC20;I++) |
193 | 0 | { |
194 | 0 | BitLength[I]=(byte)(Inp.getbits() >> 12); |
195 | 0 | Inp.addbits(4); |
196 | 0 | } |
197 | 0 | MakeDecodeTables(BitLength,&BlockTables.BD,BC20); |
198 | 0 | for (uint I=0;I<TableSize;) |
199 | 0 | { |
200 | 0 | if (Inp.InAddr>ReadTop-5) |
201 | 0 | if (!UnpReadBuf()) |
202 | 0 | return false; |
203 | 0 | uint Number=DecodeNumber(Inp,&BlockTables.BD); |
204 | 0 | if (Number<16) |
205 | 0 | { |
206 | 0 | Table[I]=(Number+UnpOldTable20[I]) & 0xf; |
207 | 0 | I++; |
208 | 0 | } |
209 | 0 | else |
210 | 0 | if (Number==16) |
211 | 0 | { |
212 | 0 | uint N=(Inp.getbits() >> 14)+3; |
213 | 0 | Inp.addbits(2); |
214 | 0 | if (I==0) |
215 | 0 | return false; // We cannot have "repeat previous" code at the first position. |
216 | 0 | else |
217 | 0 | while (N-- > 0 && I<TableSize) |
218 | 0 | { |
219 | 0 | Table[I]=Table[I-1]; |
220 | 0 | I++; |
221 | 0 | } |
222 | 0 | } |
223 | 0 | else |
224 | 0 | { |
225 | 0 | uint N; |
226 | 0 | if (Number==17) |
227 | 0 | { |
228 | 0 | N=(Inp.getbits() >> 13)+3; |
229 | 0 | Inp.addbits(3); |
230 | 0 | } |
231 | 0 | else |
232 | 0 | { |
233 | 0 | N=(Inp.getbits() >> 9)+11; |
234 | 0 | Inp.addbits(7); |
235 | 0 | } |
236 | 0 | while (N-- > 0 && I<TableSize) |
237 | 0 | Table[I++]=0; |
238 | 0 | } |
239 | 0 | } |
240 | 0 | TablesRead2=true; |
241 | 0 | if (Inp.InAddr>ReadTop) |
242 | 0 | return true; |
243 | 0 | if (UnpAudioBlock) |
244 | 0 | for (uint I=0;I<UnpChannels;I++) |
245 | 0 | MakeDecodeTables(&Table[I*MC20],&MD[I],MC20); |
246 | 0 | else |
247 | 0 | { |
248 | 0 | MakeDecodeTables(&Table[0],&BlockTables.LD,NC20); |
249 | 0 | MakeDecodeTables(&Table[NC20],&BlockTables.DD,DC20); |
250 | 0 | MakeDecodeTables(&Table[NC20+DC20],&BlockTables.RD,RC20); |
251 | 0 | } |
252 | 0 | memcpy(UnpOldTable20,Table,TableSize); |
253 | 0 | return true; |
254 | 0 | } |
255 | | |
256 | | |
257 | | void Unpack::ReadLastTables() |
258 | 0 | { |
259 | 0 | if (ReadTop>=Inp.InAddr+5) |
260 | 0 | if (UnpAudioBlock) |
261 | 0 | { |
262 | 0 | if (DecodeNumber(Inp,&MD[UnpCurChannel])==256) |
263 | 0 | ReadTables20(); |
264 | 0 | } |
265 | 0 | else |
266 | 0 | if (DecodeNumber(Inp,&BlockTables.LD)==269) |
267 | 0 | ReadTables20(); |
268 | 0 | } |
269 | | |
270 | | |
271 | | void Unpack::UnpInitData20(int Solid) |
272 | 2 | { |
273 | 2 | if (!Solid) |
274 | 2 | { |
275 | 2 | TablesRead2=false; |
276 | 2 | UnpAudioBlock=false; |
277 | 2 | UnpChannelDelta=0; |
278 | 2 | UnpCurChannel=0; |
279 | 2 | UnpChannels=1; |
280 | | |
281 | 2 | memset(AudV,0,sizeof(AudV)); |
282 | 2 | memset(UnpOldTable20,0,sizeof(UnpOldTable20)); |
283 | 2 | memset(MD,0,sizeof(MD)); |
284 | 2 | } |
285 | 2 | } |
286 | | |
287 | | |
288 | | byte Unpack::DecodeAudio(int Delta) |
289 | 0 | { |
290 | 0 | struct AudioVariables *V=&AudV[UnpCurChannel]; |
291 | 0 | V->ByteCount++; |
292 | 0 | V->D4=V->D3; |
293 | 0 | V->D3=V->D2; |
294 | 0 | V->D2=V->LastDelta-V->D1; |
295 | 0 | V->D1=V->LastDelta; |
296 | 0 | int PCh=8*V->LastChar+V->K1*V->D1+V->K2*V->D2+V->K3*V->D3+V->K4*V->D4+V->K5*UnpChannelDelta; |
297 | 0 | PCh=(PCh>>3) & 0xFF; |
298 | |
|
299 | 0 | uint Ch=PCh-Delta; |
300 | |
|
301 | 0 | int D=(signed char)Delta; |
302 | | // Left shift of negative value is undefined behavior in C++, |
303 | | // so we cast it to unsigned to follow the standard. |
304 | 0 | D=(uint)D<<3; |
305 | |
|
306 | 0 | V->Dif[0]+=abs(D); |
307 | 0 | V->Dif[1]+=abs(D-V->D1); |
308 | 0 | V->Dif[2]+=abs(D+V->D1); |
309 | 0 | V->Dif[3]+=abs(D-V->D2); |
310 | 0 | V->Dif[4]+=abs(D+V->D2); |
311 | 0 | V->Dif[5]+=abs(D-V->D3); |
312 | 0 | V->Dif[6]+=abs(D+V->D3); |
313 | 0 | V->Dif[7]+=abs(D-V->D4); |
314 | 0 | V->Dif[8]+=abs(D+V->D4); |
315 | 0 | V->Dif[9]+=abs(D-UnpChannelDelta); |
316 | 0 | V->Dif[10]+=abs(D+UnpChannelDelta); |
317 | |
|
318 | 0 | UnpChannelDelta=V->LastDelta=(signed char)(Ch-V->LastChar); |
319 | 0 | V->LastChar=Ch; |
320 | |
|
321 | 0 | if ((V->ByteCount & 0x1F)==0) |
322 | 0 | { |
323 | 0 | uint MinDif=V->Dif[0],NumMinDif=0; |
324 | 0 | V->Dif[0]=0; |
325 | 0 | for (uint I=1;I<ASIZE(V->Dif);I++) |
326 | 0 | { |
327 | 0 | if (V->Dif[I]<MinDif) |
328 | 0 | { |
329 | 0 | MinDif=V->Dif[I]; |
330 | 0 | NumMinDif=I; |
331 | 0 | } |
332 | 0 | V->Dif[I]=0; |
333 | 0 | } |
334 | 0 | switch(NumMinDif) |
335 | 0 | { |
336 | 0 | case 1: |
337 | 0 | if (V->K1>=-16) |
338 | 0 | V->K1--; |
339 | 0 | break; |
340 | 0 | case 2: |
341 | 0 | if (V->K1<16) |
342 | 0 | V->K1++; |
343 | 0 | break; |
344 | 0 | case 3: |
345 | 0 | if (V->K2>=-16) |
346 | 0 | V->K2--; |
347 | 0 | break; |
348 | 0 | case 4: |
349 | 0 | if (V->K2<16) |
350 | 0 | V->K2++; |
351 | 0 | break; |
352 | 0 | case 5: |
353 | 0 | if (V->K3>=-16) |
354 | 0 | V->K3--; |
355 | 0 | break; |
356 | 0 | case 6: |
357 | 0 | if (V->K3<16) |
358 | 0 | V->K3++; |
359 | 0 | break; |
360 | 0 | case 7: |
361 | 0 | if (V->K4>=-16) |
362 | 0 | V->K4--; |
363 | 0 | break; |
364 | 0 | case 8: |
365 | 0 | if (V->K4<16) |
366 | 0 | V->K4++; |
367 | 0 | break; |
368 | 0 | case 9: |
369 | 0 | if (V->K5>=-16) |
370 | 0 | V->K5--; |
371 | 0 | break; |
372 | 0 | case 10: |
373 | 0 | if (V->K5<16) |
374 | 0 | V->K5++; |
375 | 0 | break; |
376 | 0 | } |
377 | 0 | } |
378 | 0 | return (byte)Ch; |
379 | 0 | } |