Merge pull request #4011 from fritsch/vdpau-settings
[vuplus_xbmc] / lib / UnrarXLib / unpack.cpp
1 #include "rar.hpp"
2
3 #include "coder.cpp"
4 #include "suballoc.cpp"
5 #include "model.cpp"
6 #ifndef SFX_MODULE
7 #include "unpack15.cpp"
8 #include "unpack20.cpp"
9 #endif
10
11 Unpack::Unpack(ComprDataIO *DataIO)
12 {
13   UnpIO=DataIO;
14   Window=NULL;
15   ExternalWindow=false;
16   Suspended=false;
17   UnpAllBuf=false;
18   UnpSomeRead=false;
19 }
20
21
22 Unpack::~Unpack()
23 {
24   if (Window!=NULL && !ExternalWindow)
25     delete[] Window;
26   InitFilters();
27 }
28
29
30 void Unpack::Init(byte *Window)
31 {
32   if (Window==NULL)
33   {
34     if (UnpIO->UnpackToMemorySize > -1)
35       Unpack::Window = new byte[MAXWINMEMSIZE];
36     else
37       Unpack::Window=new byte[MAXWINSIZE];
38 #ifndef ALLOW_EXCEPTIONS
39     if (Unpack::Window==NULL)
40       ErrHandler.MemoryError();
41 #endif
42   }
43   else
44   {
45     Unpack::Window=Window;
46     ExternalWindow=true;
47   }
48   UnpInitData(false);
49 }
50
51
52 void Unpack::DoUnpack(int Method,bool Solid)
53 {
54   switch(Method)
55   {
56 #ifndef SFX_MODULE
57     case 15:
58       Unpack15(Solid);
59       break;
60     case 20:
61     case 26:
62       Unpack20(Solid);
63       break;
64 #endif
65     case 29:
66       Unpack29(Solid);
67       break;
68   }
69 }
70
71
72 inline void Unpack::InsertOldDist(unsigned int Distance)
73 {
74   OldDist[3]=OldDist[2];
75   OldDist[2]=OldDist[1];
76   OldDist[1]=OldDist[0];
77   OldDist[0]=Distance;
78 }
79
80
81 inline void Unpack::InsertLastMatch(unsigned int Length,unsigned int Distance)
82 {
83   LastDist=Distance;
84   LastLength=Length;
85 }
86
87
88 void Unpack::CopyString(unsigned int Length,unsigned int Distance)
89 {
90   unsigned int DestPtr=UnpPtr-Distance;
91   if (DestPtr<MAXWINSIZE-260 && UnpPtr<MAXWINSIZE-260)
92   {
93     Window[UnpPtr++]=Window[DestPtr++];
94     while (--Length>0)
95       Window[UnpPtr++]=Window[DestPtr++];
96   }
97   else
98     while (Length--)
99     {
100       Window[UnpPtr]=Window[DestPtr++ & MAXWINMASK];
101       UnpPtr=(UnpPtr+1) & MAXWINMASK;
102     }
103 }
104
105
106 int Unpack::DecodeNumber(struct Decode *Dec)
107 {
108   unsigned int Bits;
109   unsigned int BitField=getbits() & 0xfffe;
110   if (BitField<Dec->DecodeLen[8])
111     if (BitField<Dec->DecodeLen[4])
112       if (BitField<Dec->DecodeLen[2])
113         if (BitField<Dec->DecodeLen[1])
114           Bits=1;
115         else
116           Bits=2;
117       else
118         if (BitField<Dec->DecodeLen[3])
119           Bits=3;
120         else
121           Bits=4;
122     else
123       if (BitField<Dec->DecodeLen[6])
124         if (BitField<Dec->DecodeLen[5])
125           Bits=5;
126         else
127           Bits=6;
128       else
129         if (BitField<Dec->DecodeLen[7])
130           Bits=7;
131         else
132           Bits=8;
133   else
134     if (BitField<Dec->DecodeLen[12])
135       if (BitField<Dec->DecodeLen[10])
136         if (BitField<Dec->DecodeLen[9])
137           Bits=9;
138         else
139           Bits=10;
140       else
141         if (BitField<Dec->DecodeLen[11])
142           Bits=11;
143         else
144           Bits=12;
145     else
146       if (BitField<Dec->DecodeLen[14])
147         if (BitField<Dec->DecodeLen[13])
148           Bits=13;
149         else
150           Bits=14;
151       else
152         Bits=15;
153
154   addbits(Bits);
155   unsigned int N=Dec->DecodePos[Bits]+((BitField-Dec->DecodeLen[Bits-1])>>(16-Bits));
156   if (N>=Dec->MaxNum)
157     N=0;
158   return(Dec->DecodeNum[N]);
159 }
160
161
162 void Unpack::Unpack29(bool Solid)
163 {
164   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};
165   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};
166   static int DDecode[DC];
167   static byte DBits[DC];
168   static unsigned int DBitLengthCounts[]= {4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,14,0,12};
169   static unsigned char SDDecode[]={0,4,8,16,32,64,128,192};
170   static unsigned char SDBits[]=  {2,2,3, 4, 5, 6,  6,  6};
171   unsigned int Bits;
172
173   if (DDecode[1]==0)
174   {
175     int Dist=0,BitLength=0,Slot=0;
176     for (unsigned int I=0;I<sizeof(DBitLengthCounts)/sizeof(DBitLengthCounts[0]);I++,BitLength++)
177       for (unsigned int J=0;J<DBitLengthCounts[I];J++,Slot++,Dist+=(1<<BitLength))
178       {
179         DDecode[Slot]=Dist;
180         DBits[Slot]=BitLength;
181       }
182   }
183
184   FileExtracted=true;
185
186   if (!Suspended)
187   {
188     UnpInitData(Solid);
189     if (!UnpReadBuf())
190       return;
191     if (!TablesRead)
192       if (!ReadTables())
193         return;
194 //    if (!TablesRead && Solid)
195   //    if (!ReadTables())
196   //      return;
197     //if ((!Solid || !TablesRead) && !ReadTables())
198     //  return;
199   }
200
201   if (PPMError)
202     return;
203
204   while (true)
205   {
206     if (UnpIO->bQuit) 
207     {
208       FileExtracted=false;
209       return;
210     }
211
212     UnpPtr&=MAXWINMASK;
213
214     if (InAddr>ReadBorder)
215     {
216       if (!UnpReadBuf())
217         break;
218     }
219     if (((WrPtr-UnpPtr) & MAXWINMASK)<260 && WrPtr!=UnpPtr)
220     {
221       UnpWriteBuf();
222       if (WrittenFileSize>DestUnpSize)
223         return;
224       if (Suspended)
225       {
226         FileExtracted=false;
227         return;
228       }
229     }
230     if (UnpBlockType==BLOCK_PPM)
231     {
232       int Ch=PPM.DecodeChar();
233       if (Ch==-1)
234       {
235         PPMError=true;
236         break;
237       }
238       if (Ch==PPMEscChar)
239       {
240         int NextCh=PPM.DecodeChar();
241         if (NextCh==0)
242         {
243           if (!ReadTables())
244             break;
245           continue;
246         }
247         if (NextCh==2 || NextCh==-1)
248           break;
249         if (NextCh==3)
250         {
251           if (!ReadVMCodePPM())
252             break;
253           continue;
254         }
255         if (NextCh==4)
256         {
257           unsigned int Distance=0,Length=0;
258           bool Failed=false;
259           for (int I=0;I<4 && !Failed;I++)
260           {
261             int Ch=PPM.DecodeChar();
262             if (Ch==-1)
263               Failed=true;
264             else
265               if (I==3)
266                 Length=(byte)Ch;
267               else
268                 Distance=(Distance<<8)+(byte)Ch;
269           }
270           if (Failed)
271             break;
272           CopyString(Length+32,Distance+2);
273           continue;
274         }
275         if (NextCh==5)
276         {
277           int Length=PPM.DecodeChar();
278           if (Length==-1)
279             break;
280           CopyString(Length+4,1);
281           continue;
282         }
283       }
284       Window[UnpPtr++]=Ch;
285       continue;
286     }
287
288     int Number=DecodeNumber((struct Decode *)&LD);
289     if (Number<256)
290     {
291       Window[UnpPtr++]=(byte)Number;
292       continue;
293     }
294     if (Number>=271)
295     {
296       int Length=LDecode[Number-=271]+3;
297       if ((Bits=LBits[Number])>0)
298       {
299         Length+=getbits()>>(16-Bits);
300         addbits(Bits);
301       }
302
303       int DistNumber=DecodeNumber((struct Decode *)&DD);
304       unsigned int Distance=DDecode[DistNumber]+1;
305       if ((Bits=DBits[DistNumber])>0)
306       {
307         if (DistNumber>9)
308         {
309           if (Bits>4)
310           {
311             Distance+=((getbits()>>(20-Bits))<<4);
312             addbits(Bits-4);
313           }
314           if (LowDistRepCount>0)
315           {
316             LowDistRepCount--;
317             Distance+=PrevLowDist;
318           }
319           else
320           {
321             int LowDist=DecodeNumber((struct Decode *)&LDD);
322             if (LowDist==16)
323             {
324               LowDistRepCount=LOW_DIST_REP_COUNT-1;
325               Distance+=PrevLowDist;
326             }
327             else
328             {
329               Distance+=LowDist;
330               PrevLowDist=LowDist;
331             }
332           }
333         }
334         else
335         {
336           Distance+=getbits()>>(16-Bits);
337           addbits(Bits);
338         }
339       }
340
341       if (Distance>=0x2000)
342       {
343         Length++;
344         if (Distance>=0x40000L)
345           Length++;
346       }
347
348       InsertOldDist(Distance);
349       InsertLastMatch(Length,Distance);
350       CopyString(Length,Distance);
351       continue;
352     }
353     if (Number==256)
354     {
355       if (!ReadEndOfBlock())
356         break;
357       continue;
358     }
359     if (Number==257)
360     {
361       if (!ReadVMCode())
362         break;
363       continue;
364     }
365     if (Number==258)
366     {
367       if (LastLength!=0)
368         CopyString(LastLength,LastDist);
369       continue;
370     }
371     if (Number<263)
372     {
373       int DistNum=Number-259;
374       unsigned int Distance=OldDist[DistNum];
375       for (int I=DistNum;I>0;I--)
376         OldDist[I]=OldDist[I-1];
377       OldDist[0]=Distance;
378
379       int LengthNumber=DecodeNumber((struct Decode *)&RD);
380       int Length=LDecode[LengthNumber]+2;
381       if ((Bits=LBits[LengthNumber])>0)
382       {
383         Length+=getbits()>>(16-Bits);
384         addbits(Bits);
385       }
386       InsertLastMatch(Length,Distance);
387       CopyString(Length,Distance);
388       continue;
389     }
390     if (Number<272)
391     {
392       unsigned int Distance=SDDecode[Number-=263]+1;
393       if ((Bits=SDBits[Number])>0)
394       {
395         Distance+=getbits()>>(16-Bits);
396         addbits(Bits);
397       }
398       InsertOldDist(Distance);
399       InsertLastMatch(2,Distance);
400       CopyString(2,Distance);
401       continue;
402     }
403   }
404   UnpWriteBuf();
405
406   if (UnpIO->UnpackToMemorySize > -1)
407   {
408     UnpIO->hBufferEmpty->Set();
409     while (! UnpIO->hBufferFilled->WaitMSec(1))
410       if (UnpIO->hQuit->WaitMSec(1))
411         return;
412   }
413 }
414
415 bool Unpack::ReadEndOfBlock()
416 {
417   unsigned int BitField=getbits();
418   bool NewTable,NewFile=false;
419   if (BitField & 0x8000)
420   {
421     NewTable=true;
422     addbits(1);
423   }
424   else
425   {
426     NewFile=true;
427     NewTable=(BitField & 0x4000);
428     addbits(2);
429   }
430   TablesRead=!NewTable;
431   return !(NewFile || (NewTable && !ReadTables()));
432 }
433
434
435 bool Unpack::ReadVMCode()
436 {
437   unsigned int FirstByte=getbits()>>8;
438   addbits(8);
439   int Length=(FirstByte & 7)+1;
440   if (Length==7)
441   {
442     Length=(getbits()>>8)+7;
443     addbits(8);
444   }
445   else
446     if (Length==8)
447     {
448       Length=getbits();
449       addbits(16);
450     }
451   Array<byte> VMCode(Length);
452   for (int I=0;I<Length;I++)
453   {
454     if (InAddr>=ReadTop-1 && !UnpReadBuf() && I<Length-1)
455       return(false);
456     VMCode[I]=getbits()>>8;
457     addbits(8);
458   }
459   return(AddVMCode(FirstByte,&VMCode[0],Length));
460 }
461
462
463 bool Unpack::ReadVMCodePPM()
464 {
465   unsigned int FirstByte=PPM.DecodeChar();
466   if ((int)FirstByte==-1)
467     return(false);
468   int Length=(FirstByte & 7)+1;
469   if (Length==7)
470       {
471     int B1=PPM.DecodeChar();
472     if (B1==-1)
473       return(false);
474     Length=B1+7;
475   }
476   else
477     if (Length==8)
478     {
479       int B1=PPM.DecodeChar();
480       if (B1==-1)
481         return(false);
482       int B2=PPM.DecodeChar();
483       if (B2==-1)
484         return(false);
485       Length=B1*256+B2;
486     }  
487   Array<byte> VMCode(Length);
488   for (int I=0;I<Length;I++)
489   {
490     int Ch=PPM.DecodeChar();
491     if (Ch==-1)
492       return(false);
493     VMCode[I]=Ch;
494   }
495   return(AddVMCode(FirstByte,&VMCode[0],Length));
496 }
497
498
499 bool Unpack::AddVMCode(unsigned int FirstByte,byte *Code,int CodeSize)
500 {
501   BitInput Inp;
502   Inp.InitBitInput();
503   memcpy(Inp.InBuf,Code,Min(BitInput::MAX_SIZE,CodeSize));
504   VM.Init();
505
506   int FiltPos;
507   if (FirstByte & 0x80)
508   {
509     FiltPos=RarVM::ReadData(Inp);
510     if (FiltPos==0)
511       InitFilters();
512     else
513       FiltPos--;
514   }
515   else
516     FiltPos=LastFilter;
517   if (FiltPos>Filters.Size() || FiltPos>OldFilterLengths.Size())
518     return(false);
519   LastFilter=FiltPos;
520   bool NewFilter=(FiltPos==Filters.Size());
521
522   UnpackFilter *Filter;
523   if (NewFilter)
524   {
525     Filters.Add(1);
526     Filters[Filters.Size()-1]=Filter=new UnpackFilter;
527     OldFilterLengths.Add(1);
528     Filter->ExecCount=0;
529   }
530   else
531   {
532     Filter=Filters[FiltPos];
533     Filter->ExecCount++;
534   }
535
536   UnpackFilter *StackFilter=new UnpackFilter;
537
538   int EmptyCount=0;
539   for (int I=0;I<PrgStack.Size();I++)
540   {
541     PrgStack[I-EmptyCount]=PrgStack[I];
542     if (PrgStack[I]==NULL)
543       EmptyCount++;
544     if (EmptyCount>0)
545       PrgStack[I]=NULL;
546   }
547   if (EmptyCount==0)
548   {
549     PrgStack.Add(1);
550     EmptyCount=1;
551   }
552   int StackPos=PrgStack.Size()-EmptyCount;
553   PrgStack[StackPos]=StackFilter;
554   StackFilter->ExecCount=Filter->ExecCount;
555  
556   uint BlockStart=RarVM::ReadData(Inp);
557   if (FirstByte & 0x40)
558     BlockStart+=258;
559   StackFilter->BlockStart=(BlockStart+UnpPtr)&MAXWINMASK;
560   if (FirstByte & 0x20)
561     StackFilter->BlockLength=RarVM::ReadData(Inp);
562   else
563     StackFilter->BlockLength=FiltPos<OldFilterLengths.Size() ? OldFilterLengths[FiltPos]:0;
564   StackFilter->NextWindow=WrPtr!=UnpPtr && ((WrPtr-UnpPtr)&MAXWINMASK)<=BlockStart;
565
566 //  DebugLog("\nNextWindow: UnpPtr=%08x WrPtr=%08x BlockStart=%08x",UnpPtr,WrPtr,BlockStart);
567
568   OldFilterLengths[FiltPos]=StackFilter->BlockLength;
569
570   memset(StackFilter->Prg.InitR,0,sizeof(StackFilter->Prg.InitR));
571   StackFilter->Prg.InitR[3]=VM_GLOBALMEMADDR;
572   StackFilter->Prg.InitR[4]=StackFilter->BlockLength;
573   StackFilter->Prg.InitR[5]=StackFilter->ExecCount;
574   if (FirstByte & 0x10)
575   {
576     unsigned int InitMask=Inp.fgetbits()>>9;
577     Inp.faddbits(7);
578     for (int I=0;I<7;I++)
579       if (InitMask & (1<<I))
580         StackFilter->Prg.InitR[I]=RarVM::ReadData(Inp);
581   }
582   if (NewFilter)
583   {
584     uint VMCodeSize=RarVM::ReadData(Inp);
585     if (VMCodeSize>=0x10000 || VMCodeSize==0)
586       return(false);
587     Array<byte> VMCode(VMCodeSize);
588     for (uint I=0;I<VMCodeSize;I++)
589     {
590       VMCode[I]=Inp.fgetbits()>>8;
591       Inp.faddbits(8);
592     }
593     VM.Prepare(&VMCode[0],VMCodeSize,&Filter->Prg);
594   }
595   StackFilter->Prg.AltCmd=&Filter->Prg.Cmd[0];
596   StackFilter->Prg.CmdCount=Filter->Prg.CmdCount;
597
598   int StaticDataSize=Filter->Prg.StaticData.Size();
599   if (StaticDataSize>0 && StaticDataSize<VM_GLOBALMEMSIZE)
600   {
601     StackFilter->Prg.StaticData.Add(StaticDataSize);
602     memcpy(&StackFilter->Prg.StaticData[0],&Filter->Prg.StaticData[0],StaticDataSize);
603   }
604
605   if (StackFilter->Prg.GlobalData.Size()<VM_FIXEDGLOBALSIZE)
606   {
607     StackFilter->Prg.GlobalData.Reset();
608     StackFilter->Prg.GlobalData.Add(VM_FIXEDGLOBALSIZE);
609   }
610   byte *GlobalData=&StackFilter->Prg.GlobalData[0];
611   for (int I=0;I<7;I++)
612     VM.SetValue((uint *)&GlobalData[I*4],StackFilter->Prg.InitR[I]);
613   VM.SetValue((uint *)&GlobalData[0x1c],StackFilter->BlockLength);
614   VM.SetValue((uint *)&GlobalData[0x20],0);
615   VM.SetValue((uint *)&GlobalData[0x2c],StackFilter->ExecCount);
616   memset(&GlobalData[0x30],0,16);
617
618   if (FirstByte & 8)
619   {
620     uint DataSize=RarVM::ReadData(Inp);
621     if (DataSize>=0x10000)
622       return(false);
623     unsigned int CurSize=StackFilter->Prg.GlobalData.Size();
624     if (CurSize<DataSize+VM_FIXEDGLOBALSIZE)
625       StackFilter->Prg.GlobalData.Add(DataSize+VM_FIXEDGLOBALSIZE-CurSize);
626     byte *GlobalData=&StackFilter->Prg.GlobalData[VM_FIXEDGLOBALSIZE];
627     for (uint I=0;I<DataSize;I++)
628     {
629       GlobalData[I]=Inp.fgetbits()>>8;
630       Inp.faddbits(8);
631     }
632   }
633   return(true);
634 }
635
636
637 bool Unpack::UnpReadBuf()
638 {
639   int DataSize=ReadTop-InAddr;
640   if (DataSize<0)
641     return(false);
642   if (InAddr>BitInput::MAX_SIZE/2)
643   {
644     if (DataSize>0)
645       memmove(InBuf,InBuf+InAddr,DataSize);
646     InAddr=0;
647     ReadTop=DataSize;
648   }
649   else
650     DataSize=ReadTop;
651   int ReadCode=UnpIO->UnpRead(InBuf+DataSize,(BitInput::MAX_SIZE-DataSize)&~0xf);
652   if (ReadCode>0)
653     ReadTop+=ReadCode;
654   ReadBorder=ReadTop-30;
655   return(ReadCode!=-1);
656 }
657
658
659 void Unpack::UnpWriteBuf()
660 {
661   unsigned int WrittenBorder=WrPtr;
662   unsigned int WriteSize=(UnpPtr-WrittenBorder)&MAXWINMASK;
663   for (int I=0;I<PrgStack.Size();I++)
664   {
665     UnpackFilter *flt=PrgStack[I];
666     if (flt==NULL)
667       continue;
668     if (flt->NextWindow)
669     {
670       flt->NextWindow=false;
671       continue;
672     }
673     unsigned int BlockStart=flt->BlockStart;
674     unsigned int BlockLength=flt->BlockLength;
675     if (((BlockStart-WrittenBorder)&MAXWINMASK)<WriteSize)
676     {
677       if (WrittenBorder!=BlockStart)
678       {
679         UnpWriteArea(WrittenBorder,BlockStart);
680         WrittenBorder=BlockStart;
681         WriteSize=(UnpPtr-WrittenBorder)&MAXWINMASK;
682       }
683       if (BlockLength<=WriteSize)
684       {
685         unsigned int BlockEnd=(BlockStart+BlockLength)&MAXWINMASK;
686         if (BlockStart<BlockEnd || BlockEnd==0)
687           VM.SetMemory(0,Window+BlockStart,BlockLength);
688         else
689         {
690           unsigned int FirstPartLength=MAXWINSIZE-BlockStart;
691           VM.SetMemory(0,Window+BlockStart,FirstPartLength);
692           VM.SetMemory(FirstPartLength,Window,BlockEnd);
693         }
694         VM_PreparedProgram *Prg=&flt->Prg;
695         ExecuteCode(Prg);
696
697         byte *FilteredData=Prg->FilteredData;
698         unsigned int FilteredDataSize=Prg->FilteredDataSize;
699
700         delete PrgStack[I];
701         PrgStack[I]=NULL;
702         while (I+1<PrgStack.Size())
703         {
704           UnpackFilter *NextFilter=PrgStack[I+1];
705           if (NextFilter==NULL || NextFilter->BlockStart!=BlockStart ||
706               NextFilter->BlockLength!=FilteredDataSize || NextFilter->NextWindow)
707             break;
708           VM.SetMemory(0,FilteredData,FilteredDataSize);
709           VM_PreparedProgram *NextPrg=&PrgStack[I+1]->Prg;
710           ExecuteCode(NextPrg);
711           FilteredData=NextPrg->FilteredData;
712           FilteredDataSize=NextPrg->FilteredDataSize;
713           I++;
714           delete PrgStack[I];
715           PrgStack[I]=NULL;
716         }
717         UnpIO->UnpWrite(FilteredData,FilteredDataSize);
718         UnpSomeRead=true;
719         WrittenFileSize+=FilteredDataSize;
720         WrittenBorder=BlockEnd;
721         WriteSize=(UnpPtr-WrittenBorder)&MAXWINMASK;
722       }
723       else
724       {
725         for (int J=I;J<PrgStack.Size();J++)
726         {
727           UnpackFilter *flt=PrgStack[J];
728           if (flt!=NULL && flt->NextWindow)
729             flt->NextWindow=false;
730         }
731         WrPtr=WrittenBorder;
732         return;
733       }
734     }
735   }
736    
737   UnpWriteArea(WrittenBorder,UnpPtr);
738   WrPtr=UnpPtr;
739 }
740
741
742 void Unpack::ExecuteCode(VM_PreparedProgram *Prg)
743 {
744   if (Prg->GlobalData.Size()>0)
745   {
746     Prg->InitR[6]=int64to32(WrittenFileSize);
747     VM.SetValue((uint *)&Prg->GlobalData[0x24],int64to32(WrittenFileSize));
748     VM.SetValue((uint *)&Prg->GlobalData[0x28],int64to32(WrittenFileSize>>32));
749     VM.Execute(Prg);
750   }
751 }
752
753
754 void Unpack::UnpWriteArea(unsigned int StartPtr,unsigned int EndPtr)
755 {
756   if (EndPtr!=StartPtr)
757     UnpSomeRead=true;
758   if (EndPtr<StartPtr)
759   {
760     UnpWriteData(&Window[StartPtr],-StartPtr & MAXWINMASK);
761     UnpWriteData(Window,EndPtr);
762     UnpAllBuf=true;
763   }
764   else
765     UnpWriteData(&Window[StartPtr],EndPtr-StartPtr);
766 }
767
768
769 void Unpack::UnpWriteData(byte *Data,int Size)
770 {
771   if (WrittenFileSize>=DestUnpSize)
772     return;
773   int WriteSize=Size;
774   Int64 LeftToWrite=DestUnpSize-WrittenFileSize;
775   if (WriteSize>LeftToWrite)
776     WriteSize=int64to32(LeftToWrite);
777   UnpIO->UnpWrite(Data,WriteSize);
778   WrittenFileSize+=Size;
779 }
780
781
782 bool Unpack::ReadTables()
783 {
784   byte BitLength[BC];
785   unsigned char Table[HUFF_TABLE_SIZE];
786   if (InAddr>ReadTop-25)
787     if (!UnpReadBuf())
788       return(false);
789   faddbits((8-InBit)&7);
790   unsigned int BitField=fgetbits();
791   if (BitField & 0x8000)
792   {
793     UnpBlockType=BLOCK_PPM;
794     return(PPM.DecodeInit(this,PPMEscChar));
795   }
796   UnpBlockType=BLOCK_LZ;
797   
798   PrevLowDist=0;
799   LowDistRepCount=0;
800
801   if (!(BitField & 0x4000))
802     memset(UnpOldTable,0,sizeof(UnpOldTable));
803   faddbits(2);
804
805   for (uint I=0;I<BC;I++)
806   {
807     int Length=(byte)(fgetbits() >> 12);
808     faddbits(4);
809     if (Length==15)
810     {
811       int ZeroCount=(byte)(fgetbits() >> 12);
812       faddbits(4);
813       if (ZeroCount==0)
814         BitLength[I]=15;
815       else
816       {
817         ZeroCount+=2;
818         while (ZeroCount-- > 0 && I<sizeof(BitLength)/sizeof(BitLength[0]))
819           BitLength[I++]=0;
820         I--;
821       }
822     }
823     else
824       BitLength[I]=Length;
825   }
826   MakeDecodeTables(BitLength,(struct Decode *)&BD,BC);
827
828   const int TableSize=HUFF_TABLE_SIZE;
829   for (int I=0;I<TableSize;)
830   {
831     if (InAddr>ReadTop-5)
832       if (!UnpReadBuf())
833         return(false);
834     int Number=DecodeNumber((struct Decode *)&BD);
835     if (Number<16)
836     {
837       Table[I]=(Number+UnpOldTable[I]) & 0xf;
838       I++;
839     }
840     else
841       if (Number<18)
842       {
843         int N;
844         if (Number==16)
845         {
846           N=(fgetbits() >> 13)+3;
847           faddbits(3);
848         }
849         else
850         {
851           N=(fgetbits() >> 9)+11;
852           faddbits(7);
853         }
854         while (N-- > 0 && I<TableSize)
855         {
856           Table[I]=Table[I-1];
857           I++;
858         }
859       }
860       else
861       {
862         int N;
863         if (Number==18)
864         {
865           N=(fgetbits() >> 13)+3;
866           faddbits(3);
867         }
868         else
869         {
870           N=(fgetbits() >> 9)+11;
871           faddbits(7);
872         }
873         while (N-- > 0 && I<TableSize)
874           Table[I++]=0;
875       }
876   }
877   TablesRead=true;
878   if (InAddr>ReadTop)
879     return(false);
880   MakeDecodeTables(&Table[0],(struct Decode *)&LD,NC);
881   MakeDecodeTables(&Table[NC],(struct Decode *)&DD,DC);
882   MakeDecodeTables(&Table[NC+DC],(struct Decode *)&LDD,LDC);
883   MakeDecodeTables(&Table[NC+DC+LDC],(struct Decode *)&RD,RC);
884   memcpy(UnpOldTable,Table,sizeof(UnpOldTable));
885   return(true);
886 }
887
888
889 void Unpack::UnpInitData(int Solid)
890 {
891   if (!Solid)
892   {
893     TablesRead=false;
894     memset(OldDist,0,sizeof(OldDist));
895     OldDistPtr=0;
896     LastDist=LastLength=0;
897     if (UnpIO->UnpackToMemorySize > -1)
898       memset(Window,0,MAXWINMEMSIZE);
899     else
900       memset(Window,0,MAXWINSIZE);
901     memset(UnpOldTable,0,sizeof(UnpOldTable));
902     UnpPtr=WrPtr=0;
903     PPMEscChar=2;
904
905     InitFilters();
906   }
907   InitBitInput();
908   PPMError=false;
909   WrittenFileSize=0;
910   ReadTop=0;
911   ReadBorder=0;
912 #ifndef SFX_MODULE
913   UnpInitData20(Solid);
914 #endif
915 }
916
917
918 void Unpack::InitFilters()
919 {
920   OldFilterLengths.Reset();
921   LastFilter=0;
922
923   for (int I=0;I<Filters.Size();I++)
924     delete Filters[I];
925   Filters.Reset();
926   for (int I=0;I<PrgStack.Size();I++)
927     delete PrgStack[I];
928   PrgStack.Reset();
929 }
930
931
932 void Unpack::MakeDecodeTables(unsigned char *LenTab,struct Decode *Dec,int Size)
933 {
934   int LenCount[16],TmpPos[16],I;
935   long M,N;
936   memset(LenCount,0,sizeof(LenCount));
937   memset(Dec->DecodeNum,0,Size*sizeof(*Dec->DecodeNum));
938   for (I=0;I<Size;I++)
939     LenCount[LenTab[I] & 0xF]++;
940
941   LenCount[0]=0;
942   for (TmpPos[0]=Dec->DecodePos[0]=Dec->DecodeLen[0]=0,N=0,I=1;I<16;I++)
943   {
944     N=2*(N+LenCount[I]);
945     M=N<<(15-I);
946     if (M>0xFFFF)
947       M=0xFFFF;
948     Dec->DecodeLen[I]=(unsigned int)M;
949     TmpPos[I]=Dec->DecodePos[I]=Dec->DecodePos[I-1]+LenCount[I-1];
950   }
951
952   for (I=0;I<Size;I++)
953     if (LenTab[I]!=0)
954       Dec->DecodeNum[TmpPos[LenTab[I] & 0xF]++]=I;
955   Dec->MaxNum=Size;
956 }