123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841 |
- #if true
- using System;
- using System.Collections.Generic;
- using SharpCompress.Compressors.Rar.UnpackV1.Decode;
- using SharpCompress.Compressors.Rar.VM;
- using size_t=System.UInt32;
- using UnpackBlockHeader = SharpCompress.Compressors.Rar.UnpackV1;
- namespace SharpCompress.Compressors.Rar.UnpackV1
- {
- internal partial class Unpack
- {
- // Maximum allowed number of compressed bits processed in quick mode.
- private const int MAX_QUICK_DECODE_BITS = 10;
- // Maximum number of filters per entire data block. Must be at least
- // twice more than MAX_PACK_FILTERS to store filters from two data blocks.
- private const int MAX_UNPACK_FILTERS = 8192;
- // Maximum number of filters per entire data block for RAR3 unpack.
- // Must be at least twice more than v3_MAX_PACK_FILTERS to store filters
- // from two data blocks.
- private const int MAX3_UNPACK_FILTERS = 8192;
- // Limit maximum number of channels in RAR3 delta filter to some reasonable
- // value to prevent too slow processing of corrupt archives with invalid
- // channels number. Must be equal or larger than v3_MAX_FILTER_CHANNELS.
- // No need to provide it for RAR5, which uses only 5 bits to store channels.
- private const int MAX3_UNPACK_CHANNELS = 1024;
- // Maximum size of single filter block. We restrict it to limit memory
- // allocation. Must be equal or larger than MAX_ANALYZE_SIZE.
- private const int MAX_FILTER_BLOCK_SIZE = 0x400000;
- // Write data in 4 MB or smaller blocks. Must not exceed PACK_MAX_WRITE,
- // so we keep number of buffered filter in unpacker reasonable.
- private const int UNPACK_MAX_WRITE = 0x400000;
- // Decode compressed bit fields to alphabet numbers.
- // struct DecodeTable
- // {
- // // Real size of DecodeNum table.
- // public uint MaxNum;
- //
- // // Left aligned start and upper limit codes defining code space
- // // ranges for bit lengths. DecodeLen[BitLength-1] defines the start of
- // // range for bit length and DecodeLen[BitLength] defines next code
- // // after the end of range or in other words the upper limit code
- // // for specified bit length.
- // //uint DecodeLen[16];
- // public uint [] DecodeLen = new uint[16];
- //
- // // Every item of this array contains the sum of all preceding items.
- // // So it contains the start position in code list for every bit length.
- // public uint DecodePos[16];
- //
- // // Number of compressed bits processed in quick mode.
- // // Must not exceed MAX_QUICK_DECODE_BITS.
- // public uint QuickBits;
- //
- // // Translates compressed bits (up to QuickBits length)
- // // to bit length in quick mode.
- // public byte QuickLen[1<<MAX_QUICK_DECODE_BITS];
- //
- // // Translates compressed bits (up to QuickBits length)
- // // to position in alphabet in quick mode.
- // // 'ushort' saves some memory and even provides a little speed gain
- // // comparting to 'uint' here.
- // public ushort QuickNum[1<<MAX_QUICK_DECODE_BITS];
- //
- // // Translate the position in code list to position in alphabet.
- // // We do not allocate it dynamically to avoid performance overhead
- // // introduced by pointer, so we use the largest possible table size
- // // as array dimension. Real size of this array is defined in MaxNum.
- // // We use this array if compressed bit field is too lengthy
- // // for QuickLen based translation.
- // // 'ushort' saves some memory and even provides a little speed gain
- // // comparting to 'uint' here.
- // public ushort DecodeNum[LARGEST_TABLE_SIZE];
- // }
- // struct UnpackBlockHeader
- // {
- // public int BlockSize;
- // public int BlockBitSize;
- // public int BlockStart;
- // public int HeaderSize;
- // public bool LastBlockInFile;
- // public bool TablePresent;
- // }
- // struct UnpackBlockTables
- // {
- // public DecodeTable LD; // Decode literals.
- // public DecodeTable DD; // Decode distances.
- // public DecodeTable LDD; // Decode lower bits of distances.
- // public DecodeTable RD; // Decode repeating distances.
- // public DecodeTable BD; // Decode bit lengths in Huffman table.
- // }
-
- // private UnpackBlockHeader BlockHeader;
- private bool TablesRead5;
- private int WriteBorder;
- // TODO: see logic in unpack.cpp Unpack::Init()
- private const int MaxWinSize = PackDef.MAXWINSIZE;
- private const int MaxWinMask = PackDef.MAXWINMASK;
- // TODO: rename var
- private int UnpPtr { get { return unpPtr; } set { unpPtr = value; } }
- private int ReadBorder { get { return readBorder; } set { readBorder = value; } }
- private long DestUnpSize { get { return destUnpSize; } set { destUnpSize = value; } }
- private long WrittenFileSize { get { return writtenFileSize; } set { writtenFileSize = value; } }
- private byte[] Window{ get { return window; } }
- private uint LastLength { get { return (uint)lastLength; } set { lastLength = (int)value; } }
- private uint OldDistN(int i) { return (uint)oldDist[i]; }
- private void SetOldDistN(int i, uint value) { oldDist[i] = (int)value; }
- private int WrPtr { get { return wrPtr; } set { wrPtr = value; } }
- private Unpack BlockHeader { get { return this; } }
- private Unpack Header { get { return this; } }
- private int ReadTop { get { return readTop; } set { readTop = value; } }
- private List<UnpackFilter> Filters { get { return filters; } }
- // TODO: make sure these aren't already somewhere else
- public int BlockSize;
- public int BlockBitSize;
- public int BlockStart;
- public int HeaderSize;
- public bool LastBlockInFile;
- public bool TablePresent;
- public void Unpack5(bool Solid) {
- FileExtracted=true;
- if (!Suspended)
- {
- UnpInitData(Solid);
- if (!UnpReadBuf())
- return;
- // Check TablesRead5 to be sure that we read tables at least once
- // regardless of current block header TablePresent flag.
- // So we can safefly use these tables below.
- if (!ReadBlockHeader() ||
- !ReadTables() || !TablesRead5)
- return;
- }
- while (true)
- {
- UnpPtr &= MaxWinMask;
- if (Inp.InAddr>=ReadBorder)
- {
- bool FileDone=false;
- // We use 'while', because for empty block containing only Huffman table,
- // we'll be on the block border once again just after reading the table.
- while (Inp.InAddr>BlockHeader.BlockStart+BlockHeader.BlockSize-1 ||
- Inp.InAddr==BlockHeader.BlockStart+BlockHeader.BlockSize-1 &&
- Inp.InBit>=BlockHeader.BlockBitSize)
- {
- if (BlockHeader.LastBlockInFile)
- {
- FileDone=true;
- break;
- }
- if (!ReadBlockHeader() || !ReadTables())
- return;
- }
- if (FileDone || !UnpReadBuf())
- break;
- }
- if (((WriteBorder-UnpPtr) & MaxWinMask)<PackDef.MAX_LZ_MATCH+3 && WriteBorder!=UnpPtr)
- {
- UnpWriteBuf();
- if (WrittenFileSize>DestUnpSize)
- return;
- if (Suspended)
- {
- FileExtracted=false;
- return;
- }
- }
- //uint MainSlot=DecodeNumber(Inp,LD);
- uint MainSlot= this.DecodeNumber(LD);
- if (MainSlot<256)
- {
- // if (Fragmented)
- // FragWindow[UnpPtr++]=(byte)MainSlot;
- // else
- Window[UnpPtr++]=(byte)MainSlot;
- continue;
- }
- if (MainSlot>=262)
- {
- uint Length=SlotToLength(MainSlot-262);
- //uint DBits,Distance=1,DistSlot=DecodeNumber(Inp,&BlockTables.DD);
- int DBits;
- uint Distance=1,DistSlot=this.DecodeNumber(DD);
- if (DistSlot<4)
- {
- DBits=0;
- Distance+=DistSlot;
- }
- else
- {
- //DBits=DistSlot/2 - 1;
- DBits=(int)(DistSlot/2 - 1);
- Distance+=(2 | (DistSlot & 1)) << DBits;
- }
- if (DBits>0)
- {
- if (DBits>=4)
- {
- if (DBits>4)
- {
- Distance+=((Inp.getbits()>>(36-DBits))<<4);
- Inp.AddBits(DBits-4);
- }
- //uint LowDist=DecodeNumber(Inp,&BlockTables.LDD);
- uint LowDist=this.DecodeNumber(LDD);
- Distance+=LowDist;
- }
- else
- {
- Distance+=Inp.getbits()>>(32-DBits);
- Inp.AddBits(DBits);
- }
- }
- if (Distance>0x100)
- {
- Length++;
- if (Distance>0x2000)
- {
- Length++;
- if (Distance>0x40000)
- Length++;
- }
- }
- InsertOldDist(Distance);
- LastLength=Length;
- // if (Fragmented)
- // FragWindow.CopyString(Length,Distance,UnpPtr,MaxWinMask);
- // else
- CopyString(Length,Distance);
- continue;
- }
- if (MainSlot==256)
- {
- UnpackFilter Filter = new UnpackFilter();
- if (!ReadFilter(Filter) || !AddFilter(Filter))
- break;
- continue;
- }
- if (MainSlot==257)
- {
- if (LastLength!=0)
- // if (Fragmented)
- // FragWindow.CopyString(LastLength,OldDist[0],UnpPtr,MaxWinMask);
- // else
- //CopyString(LastLength,OldDist[0]);
- CopyString(LastLength,OldDistN(0));
- continue;
- }
- if (MainSlot<262)
- {
- //uint DistNum=MainSlot-258;
- int DistNum=(int)(MainSlot-258);
- //uint Distance=OldDist[DistNum];
- uint Distance=OldDistN(DistNum);
- //for (uint I=DistNum;I>0;I--)
- for (int I=DistNum;I>0;I--)
- //OldDistN[I]=OldDistN(I-1);
- SetOldDistN(I, OldDistN(I-1));
- //OldDistN[0]=Distance;
- SetOldDistN(0, Distance);
- uint LengthSlot=this.DecodeNumber(RD);
- uint Length=SlotToLength(LengthSlot);
- LastLength=Length;
- // if (Fragmented)
- // FragWindow.CopyString(Length,Distance,UnpPtr,MaxWinMask);
- // else
- CopyString(Length,Distance);
- continue;
- }
- }
- UnpWriteBuf();
- }
- private uint ReadFilterData()
- {
- uint ByteCount=(Inp.fgetbits()>>14)+1;
- Inp.AddBits(2);
- uint Data=0;
- //for (uint I=0;I<ByteCount;I++)
- for (int I=0;I<ByteCount;I++)
- {
- Data+=(Inp.fgetbits()>>8)<<(I*8);
- Inp.AddBits(8);
- }
- return Data;
- }
- private bool ReadFilter(UnpackFilter Filter)
- {
- if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-16)
- if (!UnpReadBuf())
- return false;
- Filter.uBlockStart=ReadFilterData();
- Filter.uBlockLength=ReadFilterData();
- if (Filter.BlockLength>MAX_FILTER_BLOCK_SIZE)
- Filter.BlockLength=0;
- //Filter.Type=Inp.fgetbits()>>13;
- Filter.Type=(byte)(Inp.fgetbits()>>13);
- Inp.faddbits(3);
- if (Filter.Type==(byte)FilterType.FILTER_DELTA)
- {
- //Filter.Channels=(Inp.fgetbits()>>11)+1;
- Filter.Channels=(byte)((Inp.fgetbits()>>11)+1);
- Inp.faddbits(5);
- }
- return true;
- }
- private bool AddFilter(UnpackFilter Filter)
- {
- if (Filters.Count>=MAX_UNPACK_FILTERS)
- {
- UnpWriteBuf(); // Write data, apply and flush filters.
- if (Filters.Count>=MAX_UNPACK_FILTERS)
- InitFilters(); // Still too many filters, prevent excessive memory use.
- }
- // If distance to filter start is that large that due to circular dictionary
- // mode now it points to old not written yet data, then we set 'NextWindow'
- // flag and process this filter only after processing that older data.
- Filter.NextWindow=WrPtr!=UnpPtr && ((WrPtr-UnpPtr)&MaxWinMask)<=Filter.BlockStart;
- Filter.uBlockStart=(uint)((Filter.BlockStart+UnpPtr)&MaxWinMask);
- Filters.Add(Filter);
- return true;
- }
- private bool UnpReadBuf()
- {
- int DataSize=ReadTop-Inp.InAddr; // Data left to process.
- if (DataSize<0)
- return false;
- BlockHeader.BlockSize-=Inp.InAddr-BlockHeader.BlockStart;
- if (Inp.InAddr>MAX_SIZE/2)
- {
- // If we already processed more than half of buffer, let's move
- // remaining data into beginning to free more space for new data
- // and ensure that calling function does not cross the buffer border
- // even if we did not read anything here. Also it ensures that read size
- // is not less than CRYPT_BLOCK_SIZE, so we can align it without risk
- // to make it zero.
- if (DataSize>0)
- //memmove(Inp.InBuf,Inp.InBuf+Inp.InAddr,DataSize);
- Array.Copy(InBuf, inAddr, InBuf, 0, DataSize);
- // TODO: perf
- //Buffer.BlockCopy(InBuf, inAddr, InBuf, 0, DataSize);
- Inp.InAddr=0;
- ReadTop=DataSize;
- }
- else
- DataSize=ReadTop;
- int ReadCode=0;
- if (MAX_SIZE!=DataSize)
- //ReadCode=UnpIO->UnpRead(Inp.InBuf+DataSize,BitInput.MAX_SIZE-DataSize);
- ReadCode = readStream.Read(InBuf, DataSize, MAX_SIZE-DataSize);
- if (ReadCode>0) // Can be also -1.
- ReadTop+=ReadCode;
- ReadBorder=ReadTop-30;
- BlockHeader.BlockStart=Inp.InAddr;
- if (BlockHeader.BlockSize!=-1) // '-1' means not defined yet.
- {
- // We may need to quit from main extraction loop and read new block header
- // and trees earlier than data in input buffer ends.
- ReadBorder=Math.Min(ReadBorder,BlockHeader.BlockStart+BlockHeader.BlockSize-1);
- }
- return ReadCode!=-1;
- }
- //?
- // void UnpWriteBuf()
- // {
- // size_t WrittenBorder=WrPtr;
- // size_t FullWriteSize=(UnpPtr-WrittenBorder)&MaxWinMask;
- // size_t WriteSizeLeft=FullWriteSize;
- // bool NotAllFiltersProcessed=false;
- // for (size_t I=0;I<Filters.Size();I++)
- // {
- // // Here we apply filters to data which we need to write.
- // // We always copy data to another memory block before processing.
- // // We cannot process them just in place in Window buffer, because
- // // these data can be used for future string matches, so we must
- // // preserve them in original form.
- //
- // UnpackFilter *flt=&Filters[I];
- // if (flt->Type==FilterType.FILTER_NONE)
- // continue;
- // if (flt->NextWindow)
- // {
- // // Here we skip filters which have block start in current data range
- // // due to address wrap around in circular dictionary, but actually
- // // belong to next dictionary block. If such filter start position
- // // is included to current write range, then we reset 'NextWindow' flag.
- // // In fact we can reset it even without such check, because current
- // // implementation seems to guarantee 'NextWindow' flag reset after
- // // buffer writing for all existing filters. But let's keep this check
- // // just in case. Compressor guarantees that distance between
- // // filter block start and filter storing position cannot exceed
- // // the dictionary size. So if we covered the filter block start with
- // // our write here, we can safely assume that filter is applicable
- // // to next block on no further wrap arounds is possible.
- // if (((flt->BlockStart-WrPtr)&MaxWinMask)<=FullWriteSize)
- // flt->NextWindow=false;
- // continue;
- // }
- // uint BlockStart=flt->BlockStart;
- // uint BlockLength=flt->BlockLength;
- // if (((BlockStart-WrittenBorder)&MaxWinMask)<WriteSizeLeft)
- // {
- // if (WrittenBorder!=BlockStart)
- // {
- // UnpWriteArea(WrittenBorder,BlockStart);
- // WrittenBorder=BlockStart;
- // WriteSizeLeft=(UnpPtr-WrittenBorder)&MaxWinMask;
- // }
- // if (BlockLength<=WriteSizeLeft)
- // {
- // if (BlockLength>0) // We set it to 0 also for invalid filters.
- // {
- // uint BlockEnd=(BlockStart+BlockLength)&MaxWinMask;
- //
- // FilterSrcMemory.Alloc(BlockLength);
- // byte *Mem=&FilterSrcMemory[0];
- // if (BlockStart<BlockEnd || BlockEnd==0)
- // {
- // if (Fragmented)
- // FragWindow.CopyData(Mem,BlockStart,BlockLength);
- // else
- // memcpy(Mem,Window+BlockStart,BlockLength);
- // }
- // else
- // {
- // size_t FirstPartLength=size_t(MaxWinSize-BlockStart);
- // if (Fragmented)
- // {
- // FragWindow.CopyData(Mem,BlockStart,FirstPartLength);
- // FragWindow.CopyData(Mem+FirstPartLength,0,BlockEnd);
- // }
- // else
- // {
- // memcpy(Mem,Window+BlockStart,FirstPartLength);
- // memcpy(Mem+FirstPartLength,Window,BlockEnd);
- // }
- // }
- //
- // byte *OutMem=ApplyFilter(Mem,BlockLength,flt);
- //
- // Filters[I].Type=FilterType.FILTER_NONE;
- //
- // if (OutMem!=NULL)
- // UnpIO->UnpWrite(OutMem,BlockLength);
- //
- // UnpSomeRead=true;
- // WrittenFileSize+=BlockLength;
- // WrittenBorder=BlockEnd;
- // WriteSizeLeft=(UnpPtr-WrittenBorder)&MaxWinMask;
- // }
- // }
- // else
- // {
- // // Current filter intersects the window write border, so we adjust
- // // the window border to process this filter next time, not now.
- // WrPtr=WrittenBorder;
- //
- // // Since Filter start position can only increase, we quit processing
- // // all following filters for this data block and reset 'NextWindow'
- // // flag for them.
- // for (size_t J=I;J<Filters.Size();J++)
- // {
- // UnpackFilter *flt=&Filters[J];
- // if (flt->Type!=FilterType.FILTER_NONE)
- // flt->NextWindow=false;
- // }
- //
- // // Do not write data left after current filter now.
- // NotAllFiltersProcessed=true;
- // break;
- // }
- // }
- // }
- //
- // // Remove processed filters from queue.
- // size_t EmptyCount=0;
- // for (size_t I=0;I<Filters.Size();I++)
- // {
- // if (EmptyCount>0)
- // Filters[I-EmptyCount]=Filters[I];
- // if (Filters[I].Type==FilterType.FILTER_NONE)
- // EmptyCount++;
- // }
- // if (EmptyCount>0)
- // Filters.Alloc(Filters.Size()-EmptyCount);
- //
- // if (!NotAllFiltersProcessed) // Only if all filters are processed.
- // {
- // // Write data left after last filter.
- // UnpWriteArea(WrittenBorder,UnpPtr);
- // WrPtr=UnpPtr;
- // }
- //
- // // We prefer to write data in blocks not exceeding UNPACK_MAX_WRITE
- // // instead of potentially huge MaxWinSize blocks. It also allows us
- // // to keep the size of Filters array reasonable.
- // WriteBorder=(UnpPtr+Min(MaxWinSize,UNPACK_MAX_WRITE))&MaxWinMask;
- //
- // // Choose the nearest among WriteBorder and WrPtr actual written border.
- // // If border is equal to UnpPtr, it means that we have MaxWinSize data ahead.
- // if (WriteBorder==UnpPtr ||
- // WrPtr!=UnpPtr && ((WrPtr-UnpPtr)&MaxWinMask)<((WriteBorder-UnpPtr)&MaxWinMask))
- // WriteBorder=WrPtr;
- // }
- // unused
- //x byte* ApplyFilter(byte *Data,uint DataSize,UnpackFilter *Flt)
- // byte[] ApplyFilter(byte []Data, uint DataSize, UnpackFilter Flt)
- // {
- // //x byte *SrcData=Data;
- // byte []SrcData=Data;
- // switch(Flt.Type)
- // {
- // case (byte)FilterType.FILTER_E8:
- // case (byte)FilterType.FILTER_E8E9:
- // {
- // uint FileOffset=(uint)WrittenFileSize;
- //
- // const uint FileSize=0x1000000;
- // byte CmpByte2=Flt.Type==(byte)FilterType.FILTER_E8E9 ? (byte)0xe9 : (byte)0xe8;
- // // DataSize is unsigned, so we use "CurPos+4" and not "DataSize-4"
- // // to avoid overflow for DataSize<4.
- // for (uint CurPos=0;CurPos+4<DataSize;)
- // {
- // byte CurByte=*(Data++);
- // CurPos++;
- // if (CurByte==0xe8 || CurByte==CmpByte2)
- // {
- // uint Offset=(CurPos+FileOffset)%FileSize;
- // uint Addr=RawGet4(Data);
- //
- // // We check 0x80000000 bit instead of '< 0' comparison
- // // not assuming int32 presence or uint size and endianness.
- // if ((Addr & 0x80000000)!=0) // Addr<0
- // {
- // if (((Addr+Offset) & 0x80000000)==0) // Addr+Offset>=0
- // RawPut4(Addr+FileSize,Data);
- // }
- // else
- // if (((Addr-FileSize) & 0x80000000)!=0) // Addr<FileSize
- // RawPut4(Addr-Offset,Data);
- //
- // Data+=4;
- // CurPos+=4;
- // }
- // }
- // }
- // return SrcData;
- // case (byte)FilterType.FILTER_ARM:
- // {
- // uint FileOffset=(uint)WrittenFileSize;
- // // DataSize is unsigned, so we use "CurPos+3" and not "DataSize-3"
- // // to avoid overflow for DataSize<3.
- // for (uint CurPos=0;CurPos+3<DataSize;CurPos+=4)
- // {
- // byte *D=Data+CurPos;
- // if (D[3]==0xeb) // BL command with '1110' (Always) condition.
- // {
- // uint Offset=D[0]+uint(D[1])*0x100+uint(D[2])*0x10000;
- // Offset-=(FileOffset+CurPos)/4;
- // D[0]=(byte)Offset;
- // D[1]=(byte)(Offset>>8);
- // D[2]=(byte)(Offset>>16);
- // }
- // }
- // }
- // return SrcData;
- // case (byte)FilterType.FILTER_DELTA:
- // {
- // // Unlike RAR3, we do not need to reject excessive channel
- // // values here, since RAR5 uses only 5 bits to store channel.
- // uint Channels=Flt->Channels,SrcPos=0;
- //
- // FilterDstMemory.Alloc(DataSize);
- // byte *DstData=&FilterDstMemory[0];
- //
- // // Bytes from same channels are grouped to continual data blocks,
- // // so we need to place them back to their interleaving positions.
- // for (uint CurChannel=0;CurChannel<Channels;CurChannel++)
- // {
- // byte PrevByte=0;
- // for (uint DestPos=CurChannel;DestPos<DataSize;DestPos+=Channels)
- // DstData[DestPos]=(PrevByte-=Data[SrcPos++]);
- // }
- // return DstData;
- // }
- //
- // }
- // return null;
- // }
- // unused
- // void UnpWriteArea(size_t StartPtr,size_t EndPtr)
- // {
- // if (EndPtr!=StartPtr)
- // UnpSomeRead=true;
- // if (EndPtr<StartPtr)
- // UnpAllBuf=true;
- //
- //// if (Fragmented)
- //// {
- //// size_t SizeToWrite=(EndPtr-StartPtr) & MaxWinMask;
- //// while (SizeToWrite>0)
- //// {
- //// size_t BlockSize=FragWindow.GetBlockSize(StartPtr,SizeToWrite);
- //// UnpWriteData(&FragWindow[StartPtr],BlockSize);
- //// SizeToWrite-=BlockSize;
- //// StartPtr=(StartPtr+BlockSize) & MaxWinMask;
- //// }
- //// }
- //// else
- // if (EndPtr<StartPtr)
- // {
- // UnpWriteData(Window+StartPtr,MaxWinSize-StartPtr);
- // UnpWriteData(Window,EndPtr);
- // }
- // else
- // UnpWriteData(Window+StartPtr,EndPtr-StartPtr);
- // }
- // unused
- // void UnpWriteData(byte *Data,size_t Size)
- // {
- // if (WrittenFileSize>=DestUnpSize)
- // return;
- // size_t WriteSize=Size;
- // long LeftToWrite=DestUnpSize-WrittenFileSize;
- // if ((long)WriteSize>LeftToWrite)
- // WriteSize=(size_t)LeftToWrite;
- // UnpIO->UnpWrite(Data,WriteSize);
- // WrittenFileSize+=Size;
- // }
- private void UnpInitData50(bool Solid)
- {
- if (!Solid)
- TablesRead5=false;
- }
- private bool ReadBlockHeader()
- {
- Header.HeaderSize=0;
- if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-7)
- if (!UnpReadBuf())
- return false;
- //Inp.faddbits((8-Inp.InBit)&7);
- Inp.faddbits((uint)((8-Inp.InBit)&7));
-
- byte BlockFlags=(byte)(Inp.fgetbits()>>8);
- Inp.faddbits(8);
- //uint ByteCount=((BlockFlags>>3)&3)+1; // Block size byte count.
- uint ByteCount=(uint)(((BlockFlags>>3)&3)+1); // Block size byte count.
-
- if (ByteCount==4)
- return false;
- //Header.HeaderSize=2+ByteCount;
- Header.HeaderSize=(int)(2+ByteCount);
- Header.BlockBitSize=(BlockFlags&7)+1;
- byte SavedCheckSum=(byte)(Inp.fgetbits()>>8);
- Inp.faddbits(8);
- int BlockSize=0;
- //for (uint I=0;I<ByteCount;I++)
- for (int I=0;I<ByteCount;I++)
- {
- //BlockSize+=(Inp.fgetbits()>>8)<<(I*8);
- BlockSize+=(int)(Inp.fgetbits()>>8)<<(I*8);
- Inp.AddBits(8);
- }
- Header.BlockSize=BlockSize;
- byte CheckSum=(byte)(0x5a^BlockFlags^BlockSize^(BlockSize>>8)^(BlockSize>>16));
- if (CheckSum!=SavedCheckSum)
- return false;
- Header.BlockStart=Inp.InAddr;
- ReadBorder=Math.Min(ReadBorder,Header.BlockStart+Header.BlockSize-1);
- Header.LastBlockInFile=(BlockFlags & 0x40)!=0;
- Header.TablePresent=(BlockFlags & 0x80)!=0;
- return true;
- }
- //?
- // bool ReadTables(BitInput Inp, ref UnpackBlockHeader Header, ref UnpackBlockTables Tables)
- // {
- // if (!Header.TablePresent)
- // return true;
- //
- // if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-25)
- // if (!UnpReadBuf())
- // return false;
- //
- // byte BitLength[BC];
- // for (uint I=0;I<BC;I++)
- // {
- // uint Length=(byte)(Inp.fgetbits() >> 12);
- // Inp.faddbits(4);
- // if (Length==15)
- // {
- // uint ZeroCount=(byte)(Inp.fgetbits() >> 12);
- // Inp.faddbits(4);
- // if (ZeroCount==0)
- // BitLength[I]=15;
- // else
- // {
- // ZeroCount+=2;
- // while (ZeroCount-- > 0 && I<ASIZE(BitLength))
- // BitLength[I++]=0;
- // I--;
- // }
- // }
- // else
- // BitLength[I]=Length;
- // }
- //
- // MakeDecodeTables(BitLength,&Tables.BD,BC);
- //
- // byte Table[HUFF_TABLE_SIZE];
- // const uint TableSize=HUFF_TABLE_SIZE;
- // for (uint I=0;I<TableSize;)
- // {
- // if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-5)
- // if (!UnpReadBuf())
- // return false;
- // uint Number=DecodeNumber(Inp,&Tables.BD);
- // if (Number<16)
- // {
- // Table[I]=Number;
- // I++;
- // }
- // else
- // if (Number<18)
- // {
- // uint N;
- // if (Number==16)
- // {
- // N=(Inp.fgetbits() >> 13)+3;
- // Inp.faddbits(3);
- // }
- // else
- // {
- // N=(Inp.fgetbits() >> 9)+11;
- // Inp.faddbits(7);
- // }
- // if (I==0)
- // {
- // // We cannot have "repeat previous" code at the first position.
- // // Multiple such codes would shift Inp position without changing I,
- // // which can lead to reading beyond of Inp boundary in mutithreading
- // // mode, where Inp.ExternalBuffer disables bounds check and we just
- // // reserve a lot of buffer space to not need such check normally.
- // return false;
- // }
- // else
- // while (N-- > 0 && I<TableSize)
- // {
- // Table[I]=Table[I-1];
- // I++;
- // }
- // }
- // else
- // {
- // uint N;
- // if (Number==18)
- // {
- // N=(Inp.fgetbits() >> 13)+3;
- // Inp.faddbits(3);
- // }
- // else
- // {
- // N=(Inp.fgetbits() >> 9)+11;
- // Inp.faddbits(7);
- // }
- // while (N-- > 0 && I<TableSize)
- // Table[I++]=0;
- // }
- // }
- // TablesRead5=true;
- // if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop)
- // return false;
- // MakeDecodeTables(&Table[0],&Tables.LD,NC);
- // MakeDecodeTables(&Table[NC],&Tables.DD,DC);
- // MakeDecodeTables(&Table[NC+DC],&Tables.LDD,LDC);
- // MakeDecodeTables(&Table[NC+DC+LDC],&Tables.RD,RC);
- // return true;
- // }
- //?
- // void InitFilters()
- // {
- // Filters.SoftReset();
- // }
- }
- }
- #endif
|