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