Unpack5(bool Solid,bool SuspendAfterInit)1 void Unpack::Unpack5(bool Solid,bool SuspendAfterInit)
2 {
3   FileExtracted=true;
4 
5   if (!Suspended)
6   {
7     UnpInitData(Solid);
8     if (!UnpReadBuf())
9       return;
10 
11     // Check TablesRead5 to be sure that we read tables at least once
12     // regardless of current block header TablePresent flag.
13     // So we can safefly use these tables below.
14     if (!ReadBlockHeader(Inp,BlockHeader) ||
15         !ReadTables(Inp,BlockHeader,BlockTables) || !TablesRead5)
16       return;
17   }
18 
19   if (SuspendAfterInit) {
20     Suspended = true;
21   }
22 
23   while (true)
24   {
25     UnpPtr&=MaxWinMask;
26 
27     if (Inp.InAddr>=ReadBorder)
28     {
29       bool FileDone=false;
30 
31       // We use 'while', because for empty block containing only Huffman table,
32       // we'll be on the block border once again just after reading the table.
33       while (Inp.InAddr>BlockHeader.BlockStart+BlockHeader.BlockSize-1 ||
34              Inp.InAddr==BlockHeader.BlockStart+BlockHeader.BlockSize-1 &&
35              Inp.InBit>=BlockHeader.BlockBitSize)
36       {
37         if (BlockHeader.LastBlockInFile)
38         {
39           FileDone=true;
40           break;
41         }
42         if (!ReadBlockHeader(Inp,BlockHeader) || !ReadTables(Inp,BlockHeader,BlockTables))
43           return;
44       }
45       if (FileDone || !UnpReadBuf())
46         break;
47     }
48 
49     if (((WriteBorder-UnpPtr) & MaxWinMask)<MAX_INC_LZ_MATCH && WriteBorder!=UnpPtr)
50     {
51       UnpWriteBuf();
52       if (WrittenFileSize>DestUnpSize)
53         return;
54       if (Suspended)
55       {
56         FileExtracted=false;
57         return;
58       }
59     }
60 
61     uint MainSlot=DecodeNumber(Inp,&BlockTables.LD);
62     if (MainSlot<256)
63     {
64       if (Fragmented)
65         FragWindow[UnpPtr++]=(byte)MainSlot;
66       else
67         Window[UnpPtr++]=(byte)MainSlot;
68       continue;
69     }
70     if (MainSlot>=262)
71     {
72       uint Length=SlotToLength(Inp,MainSlot-262);
73 
74       uint DBits,Distance=1,DistSlot=DecodeNumber(Inp,&BlockTables.DD);
75       if (DistSlot<4)
76       {
77         DBits=0;
78         Distance+=DistSlot;
79       }
80       else
81       {
82         DBits=DistSlot/2 - 1;
83         Distance+=(2 | (DistSlot & 1)) << DBits;
84       }
85 
86       if (DBits>0)
87       {
88         if (DBits>=4)
89         {
90           if (DBits>4)
91           {
92             Distance+=((Inp.getbits32()>>(36-DBits))<<4);
93             Inp.addbits(DBits-4);
94           }
95           uint LowDist=DecodeNumber(Inp,&BlockTables.LDD);
96           Distance+=LowDist;
97         }
98         else
99         {
100           Distance+=Inp.getbits32()>>(32-DBits);
101           Inp.addbits(DBits);
102         }
103       }
104 
105       if (Distance>0x100)
106       {
107         Length++;
108         if (Distance>0x2000)
109         {
110           Length++;
111           if (Distance>0x40000)
112             Length++;
113         }
114       }
115 
116       InsertOldDist(Distance);
117       LastLength=Length;
118       if (Fragmented)
119         FragWindow.CopyString(Length,Distance,UnpPtr,MaxWinMask);
120       else
121         CopyString(Length,Distance);
122       continue;
123     }
124     if (MainSlot==256)
125     {
126       UnpackFilter Filter;
127       if (!ReadFilter(Inp,Filter) || !AddFilter(Filter))
128         break;
129       continue;
130     }
131     if (MainSlot==257)
132     {
133       if (LastLength!=0)
134         if (Fragmented)
135           FragWindow.CopyString(LastLength,OldDist[0],UnpPtr,MaxWinMask);
136         else
137           CopyString(LastLength,OldDist[0]);
138       continue;
139     }
140     if (MainSlot<262)
141     {
142       uint DistNum=MainSlot-258;
143       uint Distance=OldDist[DistNum];
144       for (uint I=DistNum;I>0;I--)
145         OldDist[I]=OldDist[I-1];
146       OldDist[0]=Distance;
147 
148       uint LengthSlot=DecodeNumber(Inp,&BlockTables.RD);
149       uint Length=SlotToLength(Inp,LengthSlot);
150       LastLength=Length;
151       if (Fragmented)
152         FragWindow.CopyString(Length,Distance,UnpPtr,MaxWinMask);
153       else
154         CopyString(Length,Distance);
155       continue;
156     }
157   }
158   UnpWriteBuf();
159 }
160 
161 
ReadFilterData(BitInput & Inp)162 uint Unpack::ReadFilterData(BitInput &Inp)
163 {
164   uint ByteCount=(Inp.fgetbits()>>14)+1;
165   Inp.addbits(2);
166 
167   uint Data=0;
168   for (uint I=0;I<ByteCount;I++)
169   {
170     Data+=(Inp.fgetbits()>>8)<<(I*8);
171     Inp.addbits(8);
172   }
173   return Data;
174 }
175 
176 
ReadFilter(BitInput & Inp,UnpackFilter & Filter)177 bool Unpack::ReadFilter(BitInput &Inp,UnpackFilter &Filter)
178 {
179   if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-16)
180     if (!UnpReadBuf())
181       return false;
182 
183   Filter.BlockStart=ReadFilterData(Inp);
184   Filter.BlockLength=ReadFilterData(Inp);
185   if (Filter.BlockLength>MAX_FILTER_BLOCK_SIZE)
186     Filter.BlockLength=0;
187 
188   Filter.Type=Inp.fgetbits()>>13;
189   Inp.faddbits(3);
190 
191   if (Filter.Type==FILTER_DELTA)
192   {
193     Filter.Channels=(Inp.fgetbits()>>11)+1;
194     Inp.faddbits(5);
195   }
196 
197   return true;
198 }
199 
200 
AddFilter(UnpackFilter & Filter)201 bool Unpack::AddFilter(UnpackFilter &Filter)
202 {
203   if (Filters.Size()>=MAX_UNPACK_FILTERS)
204   {
205     UnpWriteBuf(); // Write data, apply and flush filters.
206     if (Filters.Size()>=MAX_UNPACK_FILTERS)
207       InitFilters(); // Still too many filters, prevent excessive memory use.
208   }
209 
210   // If distance to filter start is that large that due to circular dictionary
211   // mode now it points to old not written yet data, then we set 'NextWindow'
212   // flag and process this filter only after processing that older data.
213   Filter.NextWindow=WrPtr!=UnpPtr && ((WrPtr-UnpPtr)&MaxWinMask)<=Filter.BlockStart;
214 
215   Filter.BlockStart=uint((Filter.BlockStart+UnpPtr)&MaxWinMask);
216   Filters.Push(Filter);
217   return true;
218 }
219 
220 
UnpReadBuf()221 bool Unpack::UnpReadBuf()
222 {
223   int DataSize=ReadTop-Inp.InAddr; // Data left to process.
224   if (DataSize<0)
225     return false;
226   BlockHeader.BlockSize-=Inp.InAddr-BlockHeader.BlockStart;
227   if (Inp.InAddr>BitInput::MAX_SIZE/2)
228   {
229     // If we already processed more than half of buffer, let's move
230     // remaining data into beginning to free more space for new data
231     // and ensure that calling function does not cross the buffer border
232     // even if we did not read anything here. Also it ensures that read size
233     // is not less than CRYPT_BLOCK_SIZE, so we can align it without risk
234     // to make it zero.
235     if (DataSize>0)
236       memmove(Inp.InBuf,Inp.InBuf+Inp.InAddr,DataSize);
237     Inp.InAddr=0;
238     ReadTop=DataSize;
239   }
240   else
241     DataSize=ReadTop;
242   int ReadCode=0;
243   if (BitInput::MAX_SIZE!=DataSize)
244     ReadCode=UnpIO->UnpRead(Inp.InBuf+DataSize,BitInput::MAX_SIZE-DataSize);
245   if (ReadCode>0) // Can be also -1.
246     ReadTop+=ReadCode;
247   ReadBorder=ReadTop-30;
248   BlockHeader.BlockStart=Inp.InAddr;
249   if (BlockHeader.BlockSize!=-1) // '-1' means not defined yet.
250   {
251     // We may need to quit from main extraction loop and read new block header
252     // and trees earlier than data in input buffer ends.
253     ReadBorder=Min(ReadBorder,BlockHeader.BlockStart+BlockHeader.BlockSize-1);
254   }
255   return ReadCode!=-1;
256 }
257 
258 
UnpWriteBuf()259 void Unpack::UnpWriteBuf()
260 {
261   size_t WrittenBorder=WrPtr;
262   size_t FullWriteSize=(UnpPtr-WrittenBorder)&MaxWinMask;
263   size_t WriteSizeLeft=FullWriteSize;
264   bool NotAllFiltersProcessed=false;
265   for (size_t I=0;I<Filters.Size();I++)
266   {
267     // Here we apply filters to data which we need to write.
268     // We always copy data to another memory block before processing.
269     // We cannot process them just in place in Window buffer, because
270     // these data can be used for future string matches, so we must
271     // preserve them in original form.
272 
273     UnpackFilter *flt=&Filters[I];
274     if (flt->Type==FILTER_NONE)
275       continue;
276     if (flt->NextWindow)
277     {
278       // Here we skip filters which have block start in current data range
279       // due to address wrap around in circular dictionary, but actually
280       // belong to next dictionary block. If such filter start position
281       // is included to current write range, then we reset 'NextWindow' flag.
282       // In fact we can reset it even without such check, because current
283       // implementation seems to guarantee 'NextWindow' flag reset after
284       // buffer writing for all existing filters. But let's keep this check
285       // just in case. Compressor guarantees that distance between
286       // filter block start and filter storing position cannot exceed
287       // the dictionary size. So if we covered the filter block start with
288       // our write here, we can safely assume that filter is applicable
289       // to next block on no further wrap arounds is possible.
290       if (((flt->BlockStart-WrPtr)&MaxWinMask)<=FullWriteSize)
291         flt->NextWindow=false;
292       continue;
293     }
294     uint BlockStart=flt->BlockStart;
295     uint BlockLength=flt->BlockLength;
296     if (((BlockStart-WrittenBorder)&MaxWinMask)<WriteSizeLeft)
297     {
298       if (WrittenBorder!=BlockStart)
299       {
300         UnpWriteArea(WrittenBorder,BlockStart);
301         WrittenBorder=BlockStart;
302         WriteSizeLeft=(UnpPtr-WrittenBorder)&MaxWinMask;
303       }
304       if (BlockLength<=WriteSizeLeft)
305       {
306         if (BlockLength>0) // We set it to 0 also for invalid filters.
307         {
308           uint BlockEnd=(BlockStart+BlockLength)&MaxWinMask;
309 
310           FilterSrcMemory.Alloc(BlockLength);
311           byte *Mem=&FilterSrcMemory[0];
312           if (BlockStart<BlockEnd || BlockEnd==0)
313           {
314             if (Fragmented)
315               FragWindow.CopyData(Mem,BlockStart,BlockLength);
316             else
317               memcpy(Mem,Window+BlockStart,BlockLength);
318           }
319           else
320           {
321             size_t FirstPartLength=size_t(MaxWinSize-BlockStart);
322             if (Fragmented)
323             {
324               FragWindow.CopyData(Mem,BlockStart,FirstPartLength);
325               FragWindow.CopyData(Mem+FirstPartLength,0,BlockEnd);
326             }
327             else
328             {
329               memcpy(Mem,Window+BlockStart,FirstPartLength);
330               memcpy(Mem+FirstPartLength,Window,BlockEnd);
331             }
332           }
333 
334           byte *OutMem=ApplyFilter(Mem,BlockLength,flt);
335 
336           Filters[I].Type=FILTER_NONE;
337 
338           if (OutMem!=NULL)
339             UnpIO->UnpWrite(OutMem,BlockLength);
340 
341           UnpSomeRead=true;
342           WrittenFileSize+=BlockLength;
343           WrittenBorder=BlockEnd;
344           WriteSizeLeft=(UnpPtr-WrittenBorder)&MaxWinMask;
345         }
346       }
347       else
348       {
349         // Current filter intersects the window write border, so we adjust
350         // the window border to process this filter next time, not now.
351         WrPtr=WrittenBorder;
352 
353         // Since Filter start position can only increase, we quit processing
354         // all following filters for this data block and reset 'NextWindow'
355         // flag for them.
356         for (size_t J=I;J<Filters.Size();J++)
357         {
358           UnpackFilter *flt=&Filters[J];
359           if (flt->Type!=FILTER_NONE)
360             flt->NextWindow=false;
361         }
362 
363         // Do not write data left after current filter now.
364         NotAllFiltersProcessed=true;
365         break;
366       }
367     }
368   }
369 
370   // Remove processed filters from queue.
371   size_t EmptyCount=0;
372   for (size_t I=0;I<Filters.Size();I++)
373   {
374     if (EmptyCount>0)
375       Filters[I-EmptyCount]=Filters[I];
376     if (Filters[I].Type==FILTER_NONE)
377       EmptyCount++;
378   }
379   if (EmptyCount>0)
380     Filters.Alloc(Filters.Size()-EmptyCount);
381 
382   if (!NotAllFiltersProcessed) // Only if all filters are processed.
383   {
384     // Write data left after last filter.
385     UnpWriteArea(WrittenBorder,UnpPtr);
386     WrPtr=UnpPtr;
387   }
388 
389   // We prefer to write data in blocks not exceeding UNPACK_MAX_WRITE
390   // instead of potentially huge MaxWinSize blocks. It also allows us
391   // to keep the size of Filters array reasonable.
392   WriteBorder=(UnpPtr+Min(MaxWinSize,UNPACK_MAX_WRITE))&MaxWinMask;
393 
394   // Choose the nearest among WriteBorder and WrPtr actual written border.
395   // If border is equal to UnpPtr, it means that we have MaxWinSize data ahead.
396   if (WriteBorder==UnpPtr ||
397       WrPtr!=UnpPtr && ((WrPtr-UnpPtr)&MaxWinMask)<((WriteBorder-UnpPtr)&MaxWinMask))
398     WriteBorder=WrPtr;
399 }
400 
401 
ApplyFilter(byte * Data,uint DataSize,UnpackFilter * Flt)402 byte* Unpack::ApplyFilter(byte *Data,uint DataSize,UnpackFilter *Flt)
403 {
404   byte *SrcData=Data;
405   switch(Flt->Type)
406   {
407     case FILTER_E8:
408     case FILTER_E8E9:
409       {
410         uint FileOffset=(uint)WrittenFileSize;
411 
412         const uint FileSize=0x1000000;
413         byte CmpByte2=Flt->Type==FILTER_E8E9 ? 0xe9:0xe8;
414         // DataSize is unsigned, so we use "CurPos+4" and not "DataSize-4"
415         // to avoid overflow for DataSize<4.
416         for (uint CurPos=0;CurPos+4<DataSize;)
417         {
418           byte CurByte=*(Data++);
419           CurPos++;
420           if (CurByte==0xe8 || CurByte==CmpByte2)
421           {
422             uint Offset=(CurPos+FileOffset)%FileSize;
423             uint Addr=RawGet4(Data);
424 
425             // We check 0x80000000 bit instead of '< 0' comparison
426             // not assuming int32 presence or uint size and endianness.
427             if ((Addr & 0x80000000)!=0)              // Addr<0
428             {
429               if (((Addr+Offset) & 0x80000000)==0)   // Addr+Offset>=0
430                 RawPut4(Addr+FileSize,Data);
431             }
432             else
433               if (((Addr-FileSize) & 0x80000000)!=0) // Addr<FileSize
434                 RawPut4(Addr-Offset,Data);
435 
436             Data+=4;
437             CurPos+=4;
438           }
439         }
440       }
441       return SrcData;
442     case FILTER_ARM:
443       // 2019-11-15: we turned off ARM filter by default when compressing,
444       // mostly because it is inefficient for modern 64 bit ARM binaries.
445       // It was turned on by default in 5.0 - 5.80b3 , so we still need it
446       // here for compatibility with some of previously created archives.
447       {
448         uint FileOffset=(uint)WrittenFileSize;
449         // DataSize is unsigned, so we use "CurPos+3" and not "DataSize-3"
450         // to avoid overflow for DataSize<3.
451         for (uint CurPos=0;CurPos+3<DataSize;CurPos+=4)
452         {
453           byte *D=Data+CurPos;
454           if (D[3]==0xeb) // BL command with '1110' (Always) condition.
455           {
456             uint Offset=D[0]+uint(D[1])*0x100+uint(D[2])*0x10000;
457             Offset-=(FileOffset+CurPos)/4;
458             D[0]=(byte)Offset;
459             D[1]=(byte)(Offset>>8);
460             D[2]=(byte)(Offset>>16);
461           }
462         }
463       }
464       return SrcData;
465     case FILTER_DELTA:
466       {
467         // Unlike RAR3, we do not need to reject excessive channel
468         // values here, since RAR5 uses only 5 bits to store channel.
469         uint Channels=Flt->Channels,SrcPos=0;
470 
471         FilterDstMemory.Alloc(DataSize);
472         byte *DstData=&FilterDstMemory[0];
473 
474         // Bytes from same channels are grouped to continual data blocks,
475         // so we need to place them back to their interleaving positions.
476         for (uint CurChannel=0;CurChannel<Channels;CurChannel++)
477         {
478           byte PrevByte=0;
479           for (uint DestPos=CurChannel;DestPos<DataSize;DestPos+=Channels)
480             DstData[DestPos]=(PrevByte-=Data[SrcPos++]);
481         }
482         return DstData;
483       }
484 
485   }
486   return NULL;
487 }
488 
489 
UnpWriteArea(size_t StartPtr,size_t EndPtr)490 void Unpack::UnpWriteArea(size_t StartPtr,size_t EndPtr)
491 {
492   if (EndPtr!=StartPtr)
493     UnpSomeRead=true;
494   if (EndPtr<StartPtr)
495     UnpAllBuf=true;
496 
497   if (Fragmented)
498   {
499     size_t SizeToWrite=(EndPtr-StartPtr) & MaxWinMask;
500     while (SizeToWrite>0)
501     {
502       size_t BlockSize=FragWindow.GetBlockSize(StartPtr,SizeToWrite);
503       UnpWriteData(&FragWindow[StartPtr],BlockSize);
504       SizeToWrite-=BlockSize;
505       StartPtr=(StartPtr+BlockSize) & MaxWinMask;
506     }
507   }
508   else
509     if (EndPtr<StartPtr)
510     {
511       UnpWriteData(Window+StartPtr,MaxWinSize-StartPtr);
512       UnpWriteData(Window,EndPtr);
513     }
514     else
515       UnpWriteData(Window+StartPtr,EndPtr-StartPtr);
516 }
517 
518 
UnpWriteData(byte * Data,size_t Size)519 void Unpack::UnpWriteData(byte *Data,size_t Size)
520 {
521   if (WrittenFileSize>=DestUnpSize)
522     return;
523   size_t WriteSize=Size;
524   int64 LeftToWrite=DestUnpSize-WrittenFileSize;
525   if ((int64)WriteSize>LeftToWrite)
526     WriteSize=(size_t)LeftToWrite;
527   UnpIO->UnpWrite(Data,WriteSize);
528   WrittenFileSize+=Size;
529 }
530 
531 
UnpInitData50(bool Solid)532 void Unpack::UnpInitData50(bool Solid)
533 {
534   if (!Solid)
535     TablesRead5=false;
536 }
537 
538 
ReadBlockHeader(BitInput & Inp,UnpackBlockHeader & Header)539 bool Unpack::ReadBlockHeader(BitInput &Inp,UnpackBlockHeader &Header)
540 {
541   Header.HeaderSize=0;
542 
543   if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-7)
544     if (!UnpReadBuf())
545       return false;
546   Inp.faddbits((8-Inp.InBit)&7);
547 
548   byte BlockFlags=Inp.fgetbits()>>8;
549   Inp.faddbits(8);
550   uint ByteCount=((BlockFlags>>3)&3)+1; // Block size byte count.
551 
552   if (ByteCount==4)
553     return false;
554 
555   Header.HeaderSize=2+ByteCount;
556 
557   Header.BlockBitSize=(BlockFlags&7)+1;
558 
559   byte SavedCheckSum=Inp.fgetbits()>>8;
560   Inp.faddbits(8);
561 
562   int BlockSize=0;
563   for (uint I=0;I<ByteCount;I++)
564   {
565     BlockSize+=(Inp.fgetbits()>>8)<<(I*8);
566     Inp.addbits(8);
567   }
568 
569   Header.BlockSize=BlockSize;
570   byte CheckSum=byte(0x5a^BlockFlags^BlockSize^(BlockSize>>8)^(BlockSize>>16));
571   if (CheckSum!=SavedCheckSum)
572     return false;
573 
574   Header.BlockStart=Inp.InAddr;
575   ReadBorder=Min(ReadBorder,Header.BlockStart+Header.BlockSize-1);
576 
577   Header.LastBlockInFile=(BlockFlags & 0x40)!=0;
578   Header.TablePresent=(BlockFlags & 0x80)!=0;
579   return true;
580 }
581 
582 
ReadTables(BitInput & Inp,UnpackBlockHeader & Header,UnpackBlockTables & Tables)583 bool Unpack::ReadTables(BitInput &Inp,UnpackBlockHeader &Header,UnpackBlockTables &Tables)
584 {
585   if (!Header.TablePresent)
586     return true;
587 
588   if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-25)
589     if (!UnpReadBuf())
590       return false;
591 
592   byte BitLength[BC];
593   for (uint I=0;I<BC;I++)
594   {
595     uint Length=(byte)(Inp.fgetbits() >> 12);
596     Inp.faddbits(4);
597     if (Length==15)
598     {
599       uint ZeroCount=(byte)(Inp.fgetbits() >> 12);
600       Inp.faddbits(4);
601       if (ZeroCount==0)
602         BitLength[I]=15;
603       else
604       {
605         ZeroCount+=2;
606         while (ZeroCount-- > 0 && I<ASIZE(BitLength))
607           BitLength[I++]=0;
608         I--;
609       }
610     }
611     else
612       BitLength[I]=Length;
613   }
614 
615   MakeDecodeTables(BitLength,&Tables.BD,BC);
616 
617   byte Table[HUFF_TABLE_SIZE];
618   const uint TableSize=HUFF_TABLE_SIZE;
619   for (uint I=0;I<TableSize;)
620   {
621     if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-5)
622       if (!UnpReadBuf())
623         return false;
624     uint Number=DecodeNumber(Inp,&Tables.BD);
625     if (Number<16)
626     {
627       Table[I]=Number;
628       I++;
629     }
630     else
631       if (Number<18)
632       {
633         uint N;
634         if (Number==16)
635         {
636           N=(Inp.fgetbits() >> 13)+3;
637           Inp.faddbits(3);
638         }
639         else
640         {
641           N=(Inp.fgetbits() >> 9)+11;
642           Inp.faddbits(7);
643         }
644         if (I==0)
645         {
646           // We cannot have "repeat previous" code at the first position.
647           // Multiple such codes would shift Inp position without changing I,
648           // which can lead to reading beyond of Inp boundary in mutithreading
649           // mode, where Inp.ExternalBuffer disables bounds check and we just
650           // reserve a lot of buffer space to not need such check normally.
651           return false;
652         }
653         else
654           while (N-- > 0 && I<TableSize)
655           {
656             Table[I]=Table[I-1];
657             I++;
658           }
659       }
660       else
661       {
662         uint N;
663         if (Number==18)
664         {
665           N=(Inp.fgetbits() >> 13)+3;
666           Inp.faddbits(3);
667         }
668         else
669         {
670           N=(Inp.fgetbits() >> 9)+11;
671           Inp.faddbits(7);
672         }
673         while (N-- > 0 && I<TableSize)
674           Table[I++]=0;
675       }
676   }
677   TablesRead5=true;
678   if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop)
679     return false;
680   MakeDecodeTables(&Table[0],&Tables.LD,NC);
681   MakeDecodeTables(&Table[NC],&Tables.DD,DC);
682   MakeDecodeTables(&Table[NC+DC],&Tables.LDD,LDC);
683   MakeDecodeTables(&Table[NC+DC+LDC],&Tables.RD,RC);
684   return true;
685 }
686 
687 
InitFilters()688 void Unpack::InitFilters()
689 {
690   Filters.SoftReset();
691 }
692