예제 #1
0
HRESULT CDecoder::CodeSpec(UInt32 curSize)
{
  if (_remainLen == kLenIdNeedInit)
  {
    _remainLen = 0;
    m_InBitStream.Init();
    if (!_keepHistory || !m_IsUncompressedBlock)
      m_InBitStream.Normalize();
    if (!_keepHistory)
    {
      _skipByte = false;
      m_UnCompressedBlockSize = 0;
      ClearPrevLevels();
      UInt32 i86TranslationSize = 12000000;
      bool translationMode = true;
      if (!_wimMode)
      {
        translationMode = (ReadBits(1) != 0);
        if (translationMode)
        {
          i86TranslationSize = ReadBits(16) << 16;
          i86TranslationSize |= ReadBits(16);
        }
      }
      m_x86ConvertOutStreamSpec->Init(translationMode, i86TranslationSize);
      
      for (unsigned i = 0 ; i < kNumRepDistances; i++)
        m_RepDistances[i] = 0;
    }
  }

  while (_remainLen > 0 && curSize > 0)
  {
    m_OutWindowStream.PutByte(m_OutWindowStream.GetByte(m_RepDistances[0]));
    _remainLen--;
    curSize--;
  }

  while (curSize > 0)
  {
    if (m_UnCompressedBlockSize == 0)
      if (!ReadTables())
        return S_FALSE;
    UInt32 next = (Int32)MyMin(m_UnCompressedBlockSize, curSize);
    curSize -= next;
    m_UnCompressedBlockSize -= next;
    if (m_IsUncompressedBlock)
    {
      while (next > 0)
      {
        m_OutWindowStream.PutByte(m_InBitStream.DirectReadByte());
        next--;
      }
    }
    else while (next > 0)
    {
      UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);
      if (number < 256)
      {
        m_OutWindowStream.PutByte((Byte)number);
        next--;
      }
      else
      {
        UInt32 posLenSlot = number - 256;
        if (posLenSlot >= m_NumPosLenSlots)
          return S_FALSE;
        UInt32 posSlot = posLenSlot / kNumLenSlots;
        UInt32 lenSlot = posLenSlot % kNumLenSlots;
        UInt32 len = kMatchMinLen + lenSlot;
        if (lenSlot == kNumLenSlots - 1)
        {
          UInt32 lenTemp = m_LenDecoder.DecodeSymbol(&m_InBitStream);
          if (lenTemp >= kNumLenSymbols)
            return S_FALSE;
          len += lenTemp;
        }
        
        if (posSlot < kNumRepDistances)
        {
          UInt32 distance = m_RepDistances[posSlot];
          m_RepDistances[posSlot] = m_RepDistances[0];
          m_RepDistances[0] = distance;
        }
        else
        {
          UInt32 distance;
          unsigned numDirectBits;
          if (posSlot < kNumPowerPosSlots)
          {
            numDirectBits = (unsigned)(posSlot >> 1) - 1;
            distance = ((2 | (posSlot & 1)) << numDirectBits);
          }
          else
          {
            numDirectBits = kNumLinearPosSlotBits;
            distance = ((posSlot - 0x22) << kNumLinearPosSlotBits);
          }

          if (m_AlignIsUsed && numDirectBits >= kNumAlignBits)
          {
            distance += (m_InBitStream.ReadBits(numDirectBits - kNumAlignBits) << kNumAlignBits);
            UInt32 alignTemp = m_AlignDecoder.DecodeSymbol(&m_InBitStream);
            if (alignTemp >= kAlignTableSize)
              return S_FALSE;
            distance += alignTemp;
          }
          else
            distance += m_InBitStream.ReadBits(numDirectBits);
          m_RepDistances[2] = m_RepDistances[1];
          m_RepDistances[1] = m_RepDistances[0];
          m_RepDistances[0] = distance - kNumRepDistances;
        }

        UInt32 locLen = len;
        if (locLen > next)
          locLen = next;

        if (!m_OutWindowStream.CopyBlock(m_RepDistances[0], locLen))
          return S_FALSE;

        len -= locLen;
        next -= locLen;
        if (len != 0)
        {
          _remainLen = (int)len;
          return S_OK;
        }
      }
    }
예제 #2
0
HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
    const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
{
  if (!m_InBitStream.Create(1 << 20))
    return E_OUTOFMEMORY;
  if (!m_OutWindowStream.Create(kHistorySize))
    return E_OUTOFMEMORY;
  if (outSize == NULL)
    return E_INVALIDARG;
  UInt64 pos = 0, unPackSize = *outSize;

  m_OutWindowStream.SetStream(outStream);
  m_OutWindowStream.Init(false);
  m_InBitStream.SetStream(inStream);
  m_InBitStream.Init();
  // CCoderReleaser coderReleaser(this);

  if (!ReadTables())
    return S_FALSE;

  while (pos < unPackSize)
  {
    if (progress != NULL && pos % (1 << 16) == 0)
    {
      UInt64 packSize = m_InBitStream.GetProcessedSize();
      RINOK(progress->SetRatioInfo(&packSize, &pos));
    }
    if (m_InBitStream.ReadBits(1) == kMatchId) // match
    {
      UInt32 lowDistBits = m_InBitStream.ReadBits(m_NumDistanceLowDirectBits);
      UInt32 distance = m_DistanceDecoder.DecodeSymbol(&m_InBitStream);
      if (distance >= kDistanceTableSize)
        return S_FALSE;
      distance = (distance << m_NumDistanceLowDirectBits) + lowDistBits;
      UInt32 lengthSymbol = m_LengthDecoder.DecodeSymbol(&m_InBitStream);
      if (lengthSymbol >= kLengthTableSize)
        return S_FALSE;
      UInt32 length = lengthSymbol + m_MinMatchLength;
      if (lengthSymbol == kLengthTableSize - 1) // special symbol = 63
        length += m_InBitStream.ReadBits(kNumAdditionalLengthBits);
      while (distance >= pos && length > 0)
      {
        m_OutWindowStream.PutByte(0);
        pos++;
        length--;
      }
      if (length > 0)
        m_OutWindowStream.CopyBlock(distance, length);
      pos += length;
    }
    else
    {
      Byte b;
      if (m_LiteralsOn)
      {
        UInt32 temp = m_LiteralDecoder.DecodeSymbol(&m_InBitStream);
        if (temp >= kLiteralTableSize)
          return S_FALSE;
        b = (Byte)temp;
      }
      else
        b = (Byte)m_InBitStream.ReadBits(kNumBitsInByte);
      m_OutWindowStream.PutByte(b);
      pos++;
    }
  }
  if (pos > unPackSize)
    return S_FALSE;
  return m_OutWindowStream.Flush();
}
예제 #3
0
파일: unpack50.cpp 프로젝트: kode54/Cog
void Unpack::Unpack5(bool Solid)
{
  FileExtracted=true;

  if (!Suspended)
  {
    UnpInitData(Solid);
    if (!UnpReadBuf())
      return;
    if (!ReadBlockHeader(Inp,BlockHeader) || !ReadTables(Inp,BlockHeader,BlockTables))
      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(Inp,BlockHeader) || !ReadTables(Inp,BlockHeader,BlockTables))
          return;
      }
      if (FileDone || !UnpReadBuf())
        break;
    }

    if (((WriteBorder-UnpPtr) & MaxWinMask)<MAX_LZ_MATCH+3 && WriteBorder!=UnpPtr)
    {
      UnpWriteBuf();
      if (WrittenFileSize>DestUnpSize)
        return;
      if (Suspended)
      {
        FileExtracted=false;
        return;
      }
    }

    uint MainSlot=DecodeNumber(Inp,&BlockTables.LD);
    if (MainSlot<256)
    {
      if (Fragmented)
        FragWindow[UnpPtr++]=(byte)MainSlot;
      else
        Window[UnpPtr++]=(byte)MainSlot;
      continue;
    }
    if (MainSlot>=262)
    {
      uint Length=SlotToLength(Inp,MainSlot-262);

      uint DBits,Distance=1,DistSlot=DecodeNumber(Inp,&BlockTables.DD);
      if (DistSlot<4)
      {
        DBits=0;
        Distance+=DistSlot;
      }
      else
      {
        DBits=DistSlot/2 - 1;
        Distance+=(2 | (DistSlot & 1)) << DBits;
      }

      if (DBits>0)
      {
        if (DBits>=4)
        {
          if (DBits>4)
          {
            Distance+=((Inp.getbits32()>>(36-DBits))<<4);
            Inp.addbits(DBits-4);
          }
          uint LowDist=DecodeNumber(Inp,&BlockTables.LDD);
          Distance+=LowDist;
        }
        else
        {
          Distance+=Inp.getbits32()>>(32-DBits);
          Inp.addbits(DBits);
        }
      }
예제 #4
0
void Unpack::Unpack29(bool Solid)
{
  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};
  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};
  static int DDecode[DC];
  static byte DBits[DC];
  static int DBitLengthCounts[]= {4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,14,0,12};
  static unsigned char SDDecode[]={0,4,8,16,32,64,128,192};
  static unsigned char SDBits[]=  {2,2,3, 4, 5, 6,  6,  6};
  unsigned int Bits;

  if (DDecode[1]==0)
  {
    int Dist=0,BitLength=0,Slot=0;
    for (int I=0;I<sizeof(DBitLengthCounts)/sizeof(DBitLengthCounts[0]);I++,BitLength++)
      for (int J=0;J<DBitLengthCounts[I];J++,Slot++,Dist+=(1<<BitLength))
      {
        DDecode[Slot]=Dist;
        DBits[Slot]=BitLength;
      }
  }

  FileExtracted=true;

  if (!Suspended)
  {
    UnpInitData(Solid);
    if (!UnpReadBuf())
      return;
    if ((!Solid || !TablesRead) && !ReadTables())
      return;
  }

  while (true)
  {
    UnpPtr&=MAXWINMASK;

    if (InAddr>ReadBorder)
    {
      if (!UnpReadBuf())
        break;
    }
    if (((WrPtr-UnpPtr) & MAXWINMASK)<260 && WrPtr!=UnpPtr)
    {
      UnpWriteBuf();
      if (WrittenFileSize>DestUnpSize)
        return;
      if (Suspended)
      {
        FileExtracted=false;
        return;
      }
    }
    if (UnpBlockType==BLOCK_PPM)
    {
      // Here speed is critical, so we do not use SafePPMDecodeChar,
      // because sometimes even the inline function can introduce
      // some additional penalty.
      int Ch=PPM.DecodeChar();
      if (Ch==-1)              // Corrupt PPM data found.
      {
        PPM.CleanUp();         // Reset possibly corrupt PPM data structures.
        UnpBlockType=BLOCK_LZ; // Set faster and more fail proof LZ mode.
        break;
      }
      if (Ch==PPMEscChar)
      {
        int NextCh=SafePPMDecodeChar();
        if (NextCh==0)  // End of PPM encoding.
        {
          if (!ReadTables())
            break;
          continue;
        }
        if (NextCh==-1) // Corrupt PPM data found.
          break;
        if (NextCh==2)  // End of file in PPM mode..
          break;
        if (NextCh==3)  // Read VM code.
        {
          if (!ReadVMCodePPM())
            break;
          continue;
        }
        if (NextCh==4) // LZ inside of PPM.
        {
          unsigned int Distance=0,Length;
          bool Failed=false;
          for (int I=0;I<4 && !Failed;I++)
          {
            int Ch=SafePPMDecodeChar();
            if (Ch==-1)
              Failed=true;
            else
              if (I==3)
                Length=(byte)Ch;
              else
                Distance=(Distance<<8)+(byte)Ch;
          }
          if (Failed)
            break;

          CopyString(Length+32,Distance+2);
          continue;
        }
        if (NextCh==5) // One byte distance match (RLE) inside of PPM.
        {
          int Length=SafePPMDecodeChar();
          if (Length==-1)
            break;
          CopyString(Length+4,1);
          continue;
        }
        // If we are here, NextCh must be 1, what means that current byte
        // is equal to our 'escape' byte, so we just store it to Window.
      }
      Window[UnpPtr++]=Ch;
      continue;
    }

    int Number=DecodeNumber((struct Decode *)&LD);
    if (Number<256)
    {
      Window[UnpPtr++]=(byte)Number;
      continue;
    }
    if (Number>=271)
    {
      int Length=LDecode[Number-=271]+3;
      if ((Bits=LBits[Number])>0)
      {
        Length+=getbits()>>(16-Bits);
        addbits(Bits);
      }

      int DistNumber=DecodeNumber((struct Decode *)&DD);
      unsigned int Distance=DDecode[DistNumber]+1;
      if ((Bits=DBits[DistNumber])>0)
      {
        if (DistNumber>9)
        {
          if (Bits>4)
          {
            Distance+=((getbits()>>(20-Bits))<<4);
            addbits(Bits-4);
          }
          if (LowDistRepCount>0)
          {
            LowDistRepCount--;
            Distance+=PrevLowDist;
          }
          else
          {
            int LowDist=DecodeNumber((struct Decode *)&LDD);
            if (LowDist==16)
            {
              LowDistRepCount=LOW_DIST_REP_COUNT-1;
              Distance+=PrevLowDist;
            }
            else
            {
              Distance+=LowDist;
              PrevLowDist=LowDist;
            }
          }
        }
        else
        {
예제 #5
0
void Unpack::Unpack29(bool Solid)
{
  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};
  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};
  static int DDecode[DC];
  static byte DBits[DC];
  static int DBitLengthCounts[]= {4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,14,0,12};
  static unsigned char SDDecode[]={0,4,8,16,32,64,128,192};
  static unsigned char SDBits[]=  {2,2,3, 4, 5, 6,  6,  6};
  unsigned int Bits;

  if (DDecode[1]==0)
  {
    int Dist=0,BitLength=0,Slot=0;
    for (int I=0;I<sizeof(DBitLengthCounts)/sizeof(DBitLengthCounts[0]);I++,BitLength++)
      for (int J=0;J<DBitLengthCounts[I];J++,Slot++,Dist+=(1<<BitLength))
      {
        DDecode[Slot]=Dist;
        DBits[Slot]=BitLength;
      }
  }

  FileExtracted=true;

  if (!Suspended)
  {
    UnpInitData(Solid);
    if (!UnpReadBuf())
      return;
    if ((!Solid || !TablesRead) && !ReadTables())
      return;
  }

  if (PPMError)
    return;

  while (true)
  {
    UnpPtr&=MAXWINMASK;

    if (InAddr>ReadBorder)
    {
      if (!UnpReadBuf())
        break;
    }
    if (((WrPtr-UnpPtr) & MAXWINMASK)<260 && WrPtr!=UnpPtr)
    {
      UnpWriteBuf();
      if (WrittenFileSize>DestUnpSize)
        return;
      if (Suspended)
      {
        FileExtracted=false;
        return;
      }
    }
    if (UnpBlockType==BLOCK_PPM)
    {
      int Ch=PPM.DecodeChar();
      if (Ch==-1)
      {
        PPMError=true;
        break;
      }
      if (Ch==PPMEscChar)
      {
        int NextCh=PPM.DecodeChar();
        if (NextCh==0)
        {
          if (!ReadTables())
            break;
          continue;
        }
        if (NextCh==2 || NextCh==-1)
          break;
        if (NextCh==3)
        {
          if (!ReadVMCodePPM())
            break;
          continue;
        }
        if (NextCh==4)
        {
          unsigned int Distance=0,Length;
          bool Failed=false;
          for (int I=0;I<4 && !Failed;I++)
          {
            int Ch=PPM.DecodeChar();
            if (Ch==-1)
              Failed=true;
            else
              if (I==3)
                Length=(byte)Ch;
              else
                Distance=(Distance<<8)+(byte)Ch;
          }
          if (Failed)
            break;
          CopyString(Length+32,Distance+2);
          continue;
        }
        if (NextCh==5)
        {
          int Length=PPM.DecodeChar();
          if (Length==-1)
            break;
          CopyString(Length+4,1);
          continue;
        }
      }
      Window[UnpPtr++]=Ch;
      continue;
    }

    int Number=DecodeNumber((struct Decode *)&LD);
    if (Number<256)
    {
      Window[UnpPtr++]=(byte)Number;
      continue;
    }
    if (Number>=271)
    {
      int Length=LDecode[Number-=271]+3;
      if ((Bits=LBits[Number])>0)
      {
        Length+=getbits()>>(16-Bits);
        addbits(Bits);
      }

      int DistNumber=DecodeNumber((struct Decode *)&DD);
      unsigned int Distance=DDecode[DistNumber]+1;
      if ((Bits=DBits[DistNumber])>0)
      {
        if (DistNumber>9)
        {
          if (Bits>4)
          {
            Distance+=((getbits()>>(20-Bits))<<4);
            addbits(Bits-4);
          }
          if (LowDistRepCount>0)
          {
            LowDistRepCount--;
            Distance+=PrevLowDist;
          }
          else
          {
            int LowDist=DecodeNumber((struct Decode *)&LDD);
            if (LowDist==16)
            {
              LowDistRepCount=LOW_DIST_REP_COUNT-1;
              Distance+=PrevLowDist;
            }
            else
            {
              Distance+=LowDist;
              PrevLowDist=LowDist;
            }
          }
        }
        else
        {
예제 #6
0
파일: unpack.cpp 프로젝트: BigEd/snes-sdk
void Unpack::Unpack29(bool Solid)
{
	// tables moved outside function
	
	unsigned int Bits;

	FileExtracted=true;

	if (!Suspended)
	{
		UnpInitData(Solid);
		if (!UnpReadBuf())
			return;
		if ((!Solid || !TablesRead) && !ReadTables())
			return;
	}

	while (true)
	{
		UnpPtr&=MAXWINMASK;

		if (InAddr>ReadBorder)
		{
			if (!UnpReadBuf())
				break;
		}
		if (((WrPtr-UnpPtr) & MAXWINMASK)<260 && WrPtr!=UnpPtr)
		{
			UnpWriteBuf();
			if (WrittenFileSize>DestUnpSize)
				return;
			if (Suspended)
			{
				FileExtracted=false;
				return;
			}
		}
		if (UnpBlockType==BLOCK_PPM)
		{
			int Ch=PPM.DecodeChar();
			if (Ch==-1)
			{
				PPM.CleanUp();

				// turn off PPM compression mode in case of error, so UnRAR will
				// call PPM.DecodeInit in case it needs to turn it on back later.
				UnpBlockType=BLOCK_LZ;
				break;
			}
			if (Ch==PPMEscChar)
			{
				int NextCh=PPM.DecodeChar();
				if (NextCh==0)
				{
					if (!ReadTables())
						break;
					continue;
				}
				if (NextCh==2 || NextCh==-1)
					break;
				if (NextCh==3)
				{
					if (!ReadVMCodePPM())
						break;
					continue;
				}
				if (NextCh==4)
				{
					unsigned int Distance=0,Length;
					Length = 0; // avoids warning
					bool Failed=false;
					for (int I=0;I<4 && !Failed;I++)
					{
						int Ch=PPM.DecodeChar();
						if (Ch==-1)
							Failed=true;
						else
							if (I==3)
								Length=(byte)Ch;
							else
								Distance=(Distance<<8)+(byte)Ch;
					}
					if (Failed)
						break;

#ifdef _MSC_VER
	// avoid a warning about uninitialized 'Length' variable
	#pragma warning( disable : 4701 )
#endif
					CopyString(Length+32,Distance+2);
					continue;
				}
				if (NextCh==5)
				{
					int Length=PPM.DecodeChar();
					if (Length==-1)
						break;
					CopyString(Length+4,1);
					continue;
				}
			}
			Window[UnpPtr++]=Ch;
			continue;
		}

		int Number=DecodeNumber((struct Decode *)&LD);
		if (Number<256)
		{
			Window[UnpPtr++]=(byte)Number;
			continue;
		}
		if (Number>=271)
		{
			int Length=LDecode[Number-=271]+3;
			if ((Bits=LBits[Number])>0)
			{
				Length+=getbits()>>(16-Bits);
				addbits(Bits);
			}

			int DistNumber=DecodeNumber((struct Decode *)&DD);
			unsigned int Distance=DDecode[DistNumber]+1;
			if ((Bits=DBits[DistNumber])>0)
			{
				if (DistNumber>9)
				{
					if (Bits>4)
					{
						Distance+=((getbits()>>(20-Bits))<<4);
						addbits(Bits-4);
					}
					if (LowDistRepCount>0)
					{
						LowDistRepCount--;
						Distance+=PrevLowDist;
					}
					else
					{
						int LowDist=DecodeNumber((struct Decode *)&LDD);
						if (LowDist==16)
						{
							LowDistRepCount=LOW_DIST_REP_COUNT-1;
							Distance+=PrevLowDist;
						}
						else
						{
							Distance+=LowDist;
							PrevLowDist=LowDist;
						}
					}
				}
				else
				{
예제 #7
0
// Decode Huffman block and save decoded data to memory.
void Unpack::UnpackDecode(UnpackThreadData &D)
{
  if (!D.TableRead)
  {
    D.TableRead=true;
    if (!ReadTables(D.Inp,D.BlockHeader,D.BlockTables))
    {
      D.DamagedData=true;
      return;
    }
  }

  if (D.Inp.InAddr>D.BlockHeader.HeaderSize+D.BlockHeader.BlockSize)
  {
    D.DamagedData=true;
    return;
  }
  
  D.DecodedSize=0;
  int BlockBorder=D.BlockHeader.BlockStart+D.BlockHeader.BlockSize-1;

  // Reserve enough space even for filter entry.
  int DataBorder=D.DataSize-16;
  int ReadBorder=Min(BlockBorder,DataBorder);

  while (true)
  {
    if (D.Inp.InAddr>=ReadBorder)
    {
      if (D.Inp.InAddr>BlockBorder || D.Inp.InAddr==BlockBorder && 
          D.Inp.InBit>=D.BlockHeader.BlockBitSize)
        break;

      // If we do not have any more data in file to read, we must process
      // what we have until last byte. Otherwise we can return and append
      // more data to unprocessed few bytes.
      if ((D.Inp.InAddr>=DataBorder) && !D.NoDataLeft || D.Inp.InAddr>=D.DataSize)
      {
        D.Incomplete=true;
        break;
      }
    }
    if (D.DecodedSize>D.DecodedAllocated-8) // Filter can use several slots.
    {
      D.DecodedAllocated=D.DecodedAllocated*2;
      D.Decoded=(UnpackDecodedItem *)realloc(D.Decoded,D.DecodedAllocated*sizeof(UnpackDecodedItem));
      if (D.Decoded==NULL)
        ErrHandler.MemoryError();
    }

    UnpackDecodedItem *CurItem=D.Decoded+D.DecodedSize++;

    uint MainSlot=DecodeNumber(D.Inp,&D.BlockTables.LD);
    if (MainSlot<256)
    {
      if (D.DecodedSize>1)
      {
        UnpackDecodedItem *PrevItem=CurItem-1;
        if (PrevItem->Type==UNPDT_LITERAL && PrevItem->Length<3)
        {
          PrevItem->Length++;
          PrevItem->Literal[PrevItem->Length]=(byte)MainSlot;
          D.DecodedSize--;
          continue;
        }
      }
      CurItem->Type=UNPDT_LITERAL;
      CurItem->Literal[0]=(byte)MainSlot;
      CurItem->Length=0;
      continue;
    }
    if (MainSlot>=262)
    {
      uint Length=SlotToLength(D.Inp,MainSlot-262);

      uint DBits,Distance=1,DistSlot=DecodeNumber(D.Inp,&D.BlockTables.DD);
      if (DistSlot<4)
      {
        DBits=0;
        Distance+=DistSlot;
      }
      else
      {
        DBits=DistSlot/2 - 1;
        Distance+=(2 | (DistSlot & 1)) << DBits;
      }

      if (DBits>0)
      {
        if (DBits>=4)
        {
          if (DBits>4)
          {
            Distance+=((D.Inp.getbits32()>>(36-DBits))<<4);
            D.Inp.addbits(DBits-4);
          }
          uint LowDist=DecodeNumber(D.Inp,&D.BlockTables.LDD);
          Distance+=LowDist;
        }
        else
        {
          Distance+=D.Inp.getbits32()>>(32-DBits);
          D.Inp.addbits(DBits);
        }
      }