Merge pull request #4011 from fritsch/vdpau-settings
[vuplus_xbmc] / lib / UnrarXLib / unpack15.cpp
1 #define STARTL1  2
2 static unsigned int DecL1[]={0x8000,0xa000,0xc000,0xd000,0xe000,0xea00,
3                              0xee00,0xf000,0xf200,0xf200,0xffff};
4 static unsigned int PosL1[]={0,0,0,2,3,5,7,11,16,20,24,32,32};
5
6 #define STARTL2  3
7 static unsigned int DecL2[]={0xa000,0xc000,0xd000,0xe000,0xea00,0xee00,
8                              0xf000,0xf200,0xf240,0xffff};
9 static unsigned int PosL2[]={0,0,0,0,5,7,9,13,18,22,26,34,36};
10
11 #define STARTHF0  4
12 static unsigned int DecHf0[]={0x8000,0xc000,0xe000,0xf200,0xf200,0xf200,
13                               0xf200,0xf200,0xffff};
14 static unsigned int PosHf0[]={0,0,0,0,0,8,16,24,33,33,33,33,33};
15
16
17 #define STARTHF1  5
18 static unsigned int DecHf1[]={0x2000,0xc000,0xe000,0xf000,0xf200,0xf200,
19                               0xf7e0,0xffff};
20 static unsigned int PosHf1[]={0,0,0,0,0,0,4,44,60,76,80,80,127};
21
22
23 #define STARTHF2  5
24 static unsigned int DecHf2[]={0x1000,0x2400,0x8000,0xc000,0xfa00,0xffff,
25                               0xffff,0xffff};
26 static unsigned int PosHf2[]={0,0,0,0,0,0,2,7,53,117,233,0,0};
27
28
29 #define STARTHF3  6
30 static unsigned int DecHf3[]={0x800,0x2400,0xee00,0xfe80,0xffff,0xffff,
31                               0xffff};
32 static unsigned int PosHf3[]={0,0,0,0,0,0,0,2,16,218,251,0,0};
33
34
35 #define STARTHF4  8
36 static unsigned int DecHf4[]={0xff00,0xffff,0xffff,0xffff,0xffff,0xffff};
37 static unsigned int PosHf4[]={0,0,0,0,0,0,0,0,0,255,0,0,0};
38
39
40 void Unpack::Unpack15(bool Solid)
41 {
42   if (Suspended)
43     UnpPtr=WrPtr;
44   else
45   {
46     UnpInitData(Solid);
47     OldUnpInitData(Solid);
48     UnpReadBuf();
49     if (!Solid)
50     {
51       InitHuff();
52       UnpPtr=0;
53     }
54     else
55       UnpPtr=WrPtr;
56     --DestUnpSize;
57   }
58   if (DestUnpSize>=0)
59   {
60     GetFlagsBuf();
61     FlagsCnt=8;
62   }
63
64   while (DestUnpSize>=0)
65   {
66     if (UnpIO->hQuit->WaitMSec(1))
67       return;
68
69     UnpPtr&=MAXWINMASK;
70
71     if (InAddr>ReadTop-30 && !UnpReadBuf())
72       break;
73     if (((WrPtr-UnpPtr) & MAXWINMASK)<270 && WrPtr!=UnpPtr)
74     {
75       OldUnpWriteBuf();
76       if (Suspended)
77         return;
78     }
79     if (StMode)
80     {
81       HuffDecode();
82       continue;
83     }
84
85     if (--FlagsCnt < 0)
86     {
87       GetFlagsBuf();
88       FlagsCnt=7;
89     }
90
91     if (FlagBuf & 0x80)
92     {
93       FlagBuf<<=1;
94       if (Nlzb > Nhfb)
95         LongLZ();
96       else
97         HuffDecode();
98     }
99     else
100     {
101       FlagBuf<<=1;
102       if (--FlagsCnt < 0)
103       {
104         GetFlagsBuf();
105         FlagsCnt=7;
106       }
107       if (FlagBuf & 0x80)
108       {
109         FlagBuf<<=1;
110         if (Nlzb > Nhfb)
111           HuffDecode();
112         else
113           LongLZ();
114       }
115       else
116       {
117         FlagBuf<<=1;
118         ShortLZ();
119       }
120     }
121   }
122   OldUnpWriteBuf();
123 }
124
125
126 void Unpack::OldUnpWriteBuf()
127 {
128   if (UnpPtr!=WrPtr)
129     UnpSomeRead=true;
130   if (UnpPtr<WrPtr)
131   {
132     UnpIO->UnpWrite(&Window[WrPtr],-WrPtr & MAXWINMASK);
133     UnpIO->UnpWrite(Window,UnpPtr);
134     UnpAllBuf=true;
135   }
136   else
137     UnpIO->UnpWrite(&Window[WrPtr],UnpPtr-WrPtr);
138   WrPtr=UnpPtr;
139 }
140
141
142 void Unpack::ShortLZ()
143 {
144   static unsigned int ShortLen1[]={1,3,4,4,5,6,7,8,8,4,4,5,6,6,4,0};
145   static unsigned int ShortXor1[]={0,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xfe,
146                                    0xff,0xc0,0x80,0x90,0x98,0x9c,0xb0};
147   static unsigned int ShortLen2[]={2,3,3,3,4,4,5,6,6,4,4,5,6,6,4,0};
148   static unsigned int ShortXor2[]={0,0x40,0x60,0xa0,0xd0,0xe0,0xf0,0xf8,
149                                    0xfc,0xc0,0x80,0x90,0x98,0x9c,0xb0};
150
151
152   unsigned int Length,SaveLength;
153   unsigned int LastDistance;
154   unsigned int Distance;
155   int DistancePlace;
156   NumHuf=0;
157
158   unsigned int BitField=fgetbits();
159   if (LCount==2)
160   {
161     faddbits(1);
162     if (BitField >= 0x8000)
163     {
164       OldCopyString((unsigned int)LastDist,LastLength);
165       return;
166     }
167     BitField <<= 1;
168     LCount=0;
169   }
170
171   BitField>>=8;
172
173   ShortLen1[1]=ShortLen2[3]=Buf60+3;
174
175   if (AvrLn1<37)
176   {
177     for (Length=0;;Length++)
178       if (((BitField^ShortXor1[Length]) & (~(0xff>>ShortLen1[Length])))==0)
179         break;
180     faddbits(ShortLen1[Length]);
181   }
182   else
183   {
184     for (Length=0;;Length++)
185       if (((BitField^ShortXor2[Length]) & (~(0xff>>ShortLen2[Length])))==0)
186         break;
187     faddbits(ShortLen2[Length]);
188   }
189
190   if (Length >= 9)
191   {
192     if (Length == 9)
193     {
194       LCount++;
195       OldCopyString((unsigned int)LastDist,LastLength);
196       return;
197     }
198     if (Length == 14)
199     {
200       LCount=0;
201       Length=DecodeNum(fgetbits(),STARTL2,DecL2,PosL2)+5;
202       Distance=(fgetbits()>>1) | 0x8000;
203       faddbits(15);
204       LastLength=Length;
205       LastDist=Distance;
206       OldCopyString(Distance,Length);
207       return;
208     }
209
210     LCount=0;
211     SaveLength=Length;
212     Distance=OldDist[(OldDistPtr-(Length-9)) & 3];
213     Length=DecodeNum(fgetbits(),STARTL1,DecL1,PosL1)+2;
214     if (Length==0x101 && SaveLength==10)
215     {
216       Buf60 ^= 1;
217       return;
218     }
219     if (Distance > 256)
220       Length++;
221     if (Distance >= MaxDist3)
222       Length++;
223
224     OldDist[OldDistPtr++]=Distance;
225     OldDistPtr = OldDistPtr & 3;
226     LastLength=Length;
227     LastDist=Distance;
228     OldCopyString(Distance,Length);
229     return;
230   }
231
232   LCount=0;
233   AvrLn1 += Length;
234   AvrLn1 -= AvrLn1 >> 4;
235
236   DistancePlace=DecodeNum(fgetbits(),STARTHF2,DecHf2,PosHf2) & 0xff;
237   Distance=ChSetA[DistancePlace];
238   if (--DistancePlace != -1)
239   {
240     PlaceA[Distance]--;
241     LastDistance=ChSetA[DistancePlace];
242     PlaceA[LastDistance]++;
243     ChSetA[DistancePlace+1]=LastDistance;
244     ChSetA[DistancePlace]=Distance;
245   }
246   Length+=2;
247   OldDist[OldDistPtr++] = ++Distance;
248   OldDistPtr = OldDistPtr & 3;
249   LastLength=Length;
250   LastDist=Distance;
251   OldCopyString(Distance,Length);
252 }
253
254
255 void Unpack::LongLZ()
256 {
257   unsigned int Length;
258   unsigned int Distance;
259   unsigned int DistancePlace,NewDistancePlace;
260   unsigned int OldAvr2,OldAvr3;
261
262   NumHuf=0;
263   Nlzb+=16;
264   if (Nlzb > 0xff)
265   {
266     Nlzb=0x90;
267     Nhfb >>= 1;
268   }
269   OldAvr2=AvrLn2;
270
271   unsigned int BitField=fgetbits();
272   if (AvrLn2 >= 122)
273     Length=DecodeNum(BitField,STARTL2,DecL2,PosL2);
274   else
275     if (AvrLn2 >= 64)
276       Length=DecodeNum(BitField,STARTL1,DecL1,PosL1);
277     else
278       if (BitField < 0x100)
279       {
280         Length=BitField;
281         faddbits(16);
282       }
283       else
284       {
285         for (Length=0;((BitField<<Length)&0x8000)==0;Length++)
286           ;
287         faddbits(Length+1);
288       }
289
290   AvrLn2 += Length;
291   AvrLn2 -= AvrLn2 >> 5;
292
293   BitField=fgetbits();
294   if (AvrPlcB > 0x28ff)
295     DistancePlace=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2);
296   else if (AvrPlcB > 0x6ff)
297     DistancePlace=DecodeNum(BitField,STARTHF1,DecHf1,PosHf1);
298   else
299     DistancePlace=DecodeNum(BitField,STARTHF0,DecHf0,PosHf0);
300
301   AvrPlcB += DistancePlace;
302   AvrPlcB -= AvrPlcB >> 8;
303   while (1)
304   {
305     Distance = ChSetB[DistancePlace & 0xff];
306     NewDistancePlace = NToPlB[Distance++ & 0xff]++;
307     if (!(Distance & 0xff))
308       CorrHuff(ChSetB,NToPlB);
309     else
310       break;
311   }
312
313   ChSetB[DistancePlace]=ChSetB[NewDistancePlace];
314   ChSetB[NewDistancePlace]=Distance;
315
316   Distance=((Distance & 0xff00) | (fgetbits() >> 8)) >> 1;
317   faddbits(7);
318
319   OldAvr3=AvrLn3;
320   if (Length!=1 && Length!=4)
321   {
322     if (Length==0 && Distance <= MaxDist3)
323     {
324       AvrLn3++;
325       AvrLn3 -= AvrLn3 >> 8;
326     }
327     else if (AvrLn3 > 0)
328       AvrLn3--;
329   }
330   Length+=3;
331   if (Distance >= MaxDist3)
332     Length++;
333   if (Distance <= 256)
334     Length+=8;
335   if (OldAvr3 > 0xb0 || (AvrPlc >= 0x2a00 && OldAvr2 < 0x40))
336     MaxDist3=0x7f00;
337   else
338     MaxDist3=0x2001;
339   OldDist[OldDistPtr++]=Distance;
340   OldDistPtr = OldDistPtr & 3;
341   LastLength=Length;
342   LastDist=Distance;
343   OldCopyString(Distance,Length);
344 }
345
346
347 void Unpack::HuffDecode()
348 {
349   unsigned int CurByte,NewBytePlace;
350   unsigned int Length;
351   unsigned int Distance;
352   int BytePlace;
353
354   unsigned int BitField=fgetbits();
355
356   if (AvrPlc > 0x75ff)
357     BytePlace=DecodeNum(BitField,STARTHF4,DecHf4,PosHf4);
358   else if (AvrPlc > 0x5dff)
359     BytePlace=DecodeNum(BitField,STARTHF3,DecHf3,PosHf3);
360   else if (AvrPlc > 0x35ff)
361     BytePlace=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2);
362   else if (AvrPlc > 0x0dff)
363     BytePlace=DecodeNum(BitField,STARTHF1,DecHf1,PosHf1);
364   else
365     BytePlace=DecodeNum(BitField,STARTHF0,DecHf0,PosHf0);
366   BytePlace&=0xff;
367   if (StMode)
368   {
369     if (BytePlace==0 && BitField > 0xfff)
370       BytePlace=0x100;
371     if (--BytePlace==-1)
372     {
373       BitField=fgetbits();
374       faddbits(1);
375       if (BitField & 0x8000)
376       {
377         NumHuf=StMode=0;
378         return;
379       }
380       else
381       {
382         Length = (BitField & 0x4000) ? 4 : 3;
383         faddbits(1);
384         Distance=DecodeNum(fgetbits(),STARTHF2,DecHf2,PosHf2);
385         Distance = (Distance << 5) | (fgetbits() >> 11);
386         faddbits(5);
387         OldCopyString(Distance,Length);
388         return;
389       }
390     }
391   }
392   else
393     if (NumHuf++ >= 16 && FlagsCnt==0)
394       StMode=1;
395   AvrPlc += BytePlace;
396   AvrPlc -= AvrPlc >> 8;
397   Nhfb+=16;
398   if (Nhfb > 0xff)
399   {
400     Nhfb=0x90;
401     Nlzb >>= 1;
402   }
403
404   Window[UnpPtr++]=(byte)(ChSet[BytePlace]>>8);
405   --DestUnpSize;
406
407   while (1)
408   {
409     CurByte=ChSet[BytePlace];
410     NewBytePlace=NToPl[CurByte++ & 0xff]++;
411     if ((CurByte & 0xff) > 0xa1)
412       CorrHuff(ChSet,NToPl);
413     else
414       break;
415   }
416
417   ChSet[BytePlace]=ChSet[NewBytePlace];
418   ChSet[NewBytePlace]=CurByte;
419 }
420
421
422 void Unpack::GetFlagsBuf()
423 {
424   unsigned int Flags,NewFlagsPlace;
425   unsigned int FlagsPlace=DecodeNum(fgetbits(),STARTHF2,DecHf2,PosHf2);
426
427   while (1)
428   {
429     Flags=ChSetC[FlagsPlace];
430     FlagBuf=Flags>>8;
431     NewFlagsPlace=NToPlC[Flags++ & 0xff]++;
432     if ((Flags & 0xff) != 0)
433       break;
434     CorrHuff(ChSetC,NToPlC);
435   }
436
437   ChSetC[FlagsPlace]=ChSetC[NewFlagsPlace];
438   ChSetC[NewFlagsPlace]=Flags;
439 }
440
441
442 void Unpack::OldUnpInitData(int Solid)
443 {
444   if (!Solid)
445   {
446     AvrPlcB=AvrLn1=AvrLn2=AvrLn3=NumHuf=Buf60=0;
447     AvrPlc=0x3500;
448     MaxDist3=0x2001;
449     Nhfb=Nlzb=0x80;
450   }
451   FlagsCnt=0;
452   FlagBuf=0;
453   StMode=0;
454   LCount=0;
455   ReadTop=0;
456 }
457
458
459 void Unpack::InitHuff()
460 {
461   for (unsigned int I=0;I<256;I++)
462   {
463     Place[I]=PlaceA[I]=PlaceB[I]=I;
464     PlaceC[I]=(~I+1) & 0xff;
465     ChSet[I]=ChSetB[I]=I<<8;
466     ChSetA[I]=I;
467     ChSetC[I]=((~I+1) & 0xff)<<8;
468   }
469   memset(NToPl,0,sizeof(NToPl));
470   memset(NToPlB,0,sizeof(NToPlB));
471   memset(NToPlC,0,sizeof(NToPlC));
472   CorrHuff(ChSetB,NToPlB);
473 }
474
475
476 void Unpack::CorrHuff(unsigned int *CharSet,unsigned int *NumToPlace)
477 {
478   int I,J;
479   for (I=7;I>=0;I--)
480     for (J=0;J<32;J++,CharSet++)
481       *CharSet=(*CharSet & ~0xff) | I;
482   memset(NumToPlace,0,sizeof(NToPl));
483   for (I=6;I>=0;I--)
484     NumToPlace[I]=(7-I)*32;
485 }
486
487
488 void Unpack::OldCopyString(unsigned int Distance,unsigned int Length)
489 {
490   DestUnpSize-=Length;
491   while (Length--)
492   {
493     Window[UnpPtr]=Window[(UnpPtr-Distance) & MAXWINMASK];
494     UnpPtr=(UnpPtr+1) & MAXWINMASK;
495   }
496 }
497
498
499 unsigned int Unpack::DecodeNum(int Num,unsigned int StartPos,
500                                unsigned int *DecTab,unsigned int *PosTab)
501 {
502   int I;
503   for (Num&=0xfff0,I=0;(int)DecTab[I]<=Num;I++)
504     StartPos++;
505   faddbits(StartPos);
506   return(((Num-(I ? DecTab[I-1]:0))>>(16-StartPos))+PosTab[StartPos]);
507 }