511 lines
11 KiB
C++
511 lines
11 KiB
C++
|
#define STARTL1 2
|
||
|
static unsigned int DecL1[]={0x8000,0xa000,0xc000,0xd000,0xe000,0xea00,
|
||
|
0xee00,0xf000,0xf200,0xf200,0xffff};
|
||
|
static unsigned int PosL1[]={0,0,0,2,3,5,7,11,16,20,24,32,32};
|
||
|
|
||
|
#define STARTL2 3
|
||
|
static unsigned int DecL2[]={0xa000,0xc000,0xd000,0xe000,0xea00,0xee00,
|
||
|
0xf000,0xf200,0xf240,0xffff};
|
||
|
static unsigned int PosL2[]={0,0,0,0,5,7,9,13,18,22,26,34,36};
|
||
|
|
||
|
#define STARTHF0 4
|
||
|
static unsigned int DecHf0[]={0x8000,0xc000,0xe000,0xf200,0xf200,0xf200,
|
||
|
0xf200,0xf200,0xffff};
|
||
|
static unsigned int PosHf0[]={0,0,0,0,0,8,16,24,33,33,33,33,33};
|
||
|
|
||
|
|
||
|
#define STARTHF1 5
|
||
|
static unsigned int DecHf1[]={0x2000,0xc000,0xe000,0xf000,0xf200,0xf200,
|
||
|
0xf7e0,0xffff};
|
||
|
static unsigned int PosHf1[]={0,0,0,0,0,0,4,44,60,76,80,80,127};
|
||
|
|
||
|
|
||
|
#define STARTHF2 5
|
||
|
static unsigned int DecHf2[]={0x1000,0x2400,0x8000,0xc000,0xfa00,0xffff,
|
||
|
0xffff,0xffff};
|
||
|
static unsigned int PosHf2[]={0,0,0,0,0,0,2,7,53,117,233,0,0};
|
||
|
|
||
|
|
||
|
#define STARTHF3 6
|
||
|
static unsigned int DecHf3[]={0x800,0x2400,0xee00,0xfe80,0xffff,0xffff,
|
||
|
0xffff};
|
||
|
static unsigned int PosHf3[]={0,0,0,0,0,0,0,2,16,218,251,0,0};
|
||
|
|
||
|
|
||
|
#define STARTHF4 8
|
||
|
static unsigned int DecHf4[]={0xff00,0xffff,0xffff,0xffff,0xffff,0xffff};
|
||
|
static unsigned int PosHf4[]={0,0,0,0,0,0,0,0,0,255,0,0,0};
|
||
|
|
||
|
|
||
|
void Unpack::Unpack15(bool Solid)
|
||
|
{
|
||
|
if (Suspended)
|
||
|
UnpPtr=WrPtr;
|
||
|
else
|
||
|
{
|
||
|
UnpInitData(Solid);
|
||
|
OldUnpInitData(Solid);
|
||
|
UnpReadBuf();
|
||
|
if (!Solid)
|
||
|
{
|
||
|
InitHuff();
|
||
|
UnpPtr=0;
|
||
|
}
|
||
|
else
|
||
|
UnpPtr=WrPtr;
|
||
|
--DestUnpSize;
|
||
|
}
|
||
|
if (DestUnpSize>=0)
|
||
|
{
|
||
|
GetFlagsBuf();
|
||
|
FlagsCnt=8;
|
||
|
}
|
||
|
|
||
|
while (DestUnpSize>=0)
|
||
|
{
|
||
|
UnpPtr&=MAXWINMASK;
|
||
|
|
||
|
if (InAddr>ReadTop-30 && !UnpReadBuf())
|
||
|
break;
|
||
|
if (((WrPtr-UnpPtr) & MAXWINMASK)<270 && WrPtr!=UnpPtr)
|
||
|
{
|
||
|
OldUnpWriteBuf();
|
||
|
if (Suspended)
|
||
|
return;
|
||
|
}
|
||
|
if (StMode)
|
||
|
{
|
||
|
HuffDecode();
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (--FlagsCnt < 0)
|
||
|
{
|
||
|
GetFlagsBuf();
|
||
|
FlagsCnt=7;
|
||
|
}
|
||
|
|
||
|
if (FlagBuf & 0x80)
|
||
|
{
|
||
|
FlagBuf<<=1;
|
||
|
if (Nlzb > Nhfb)
|
||
|
LongLZ();
|
||
|
else
|
||
|
HuffDecode();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
FlagBuf<<=1;
|
||
|
if (--FlagsCnt < 0)
|
||
|
{
|
||
|
GetFlagsBuf();
|
||
|
FlagsCnt=7;
|
||
|
}
|
||
|
if (FlagBuf & 0x80)
|
||
|
{
|
||
|
FlagBuf<<=1;
|
||
|
if (Nlzb > Nhfb)
|
||
|
HuffDecode();
|
||
|
else
|
||
|
LongLZ();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
FlagBuf<<=1;
|
||
|
ShortLZ();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
OldUnpWriteBuf();
|
||
|
}
|
||
|
|
||
|
|
||
|
void Unpack::OldUnpWriteBuf()
|
||
|
{
|
||
|
if (UnpPtr!=WrPtr)
|
||
|
UnpSomeRead=true;
|
||
|
if (UnpPtr<WrPtr)
|
||
|
{
|
||
|
UnpIO->UnpWrite(&Window[WrPtr],-(int)WrPtr & MAXWINMASK);
|
||
|
UnpIO->UnpWrite(Window,UnpPtr);
|
||
|
UnpAllBuf=true;
|
||
|
}
|
||
|
else
|
||
|
UnpIO->UnpWrite(&Window[WrPtr],UnpPtr-WrPtr);
|
||
|
WrPtr=UnpPtr;
|
||
|
}
|
||
|
|
||
|
|
||
|
#define GetShortLen1(pos) ((pos)==1 ? Buf60+3:ShortLen1[pos])
|
||
|
#define GetShortLen2(pos) ((pos)==3 ? Buf60+3:ShortLen2[pos])
|
||
|
|
||
|
void Unpack::ShortLZ()
|
||
|
{
|
||
|
static unsigned int ShortLen1[]={1,3,4,4,5,6,7,8,8,4,4,5,6,6,4,0};
|
||
|
static unsigned int ShortXor1[]={0,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xfe,
|
||
|
0xff,0xc0,0x80,0x90,0x98,0x9c,0xb0};
|
||
|
static unsigned int ShortLen2[]={2,3,3,3,4,4,5,6,6,4,4,5,6,6,4,0};
|
||
|
static unsigned int ShortXor2[]={0,0x40,0x60,0xa0,0xd0,0xe0,0xf0,0xf8,
|
||
|
0xfc,0xc0,0x80,0x90,0x98,0x9c,0xb0};
|
||
|
|
||
|
|
||
|
unsigned int Length,SaveLength;
|
||
|
unsigned int LastDistance;
|
||
|
unsigned int Distance;
|
||
|
int DistancePlace;
|
||
|
NumHuf=0;
|
||
|
|
||
|
unsigned int BitField=fgetbits();
|
||
|
if (LCount==2)
|
||
|
{
|
||
|
faddbits(1);
|
||
|
if (BitField >= 0x8000)
|
||
|
{
|
||
|
OldCopyString((unsigned int)LastDist,LastLength);
|
||
|
return;
|
||
|
}
|
||
|
BitField <<= 1;
|
||
|
LCount=0;
|
||
|
}
|
||
|
|
||
|
BitField>>=8;
|
||
|
|
||
|
// not thread safe, replaced by GetShortLen1 and GetShortLen2 macro
|
||
|
// ShortLen1[1]=ShortLen2[3]=Buf60+3;
|
||
|
|
||
|
if (AvrLn1<37)
|
||
|
{
|
||
|
for (Length=0;;Length++)
|
||
|
if (((BitField^ShortXor1[Length]) & (~(0xff>>GetShortLen1(Length))))==0)
|
||
|
break;
|
||
|
faddbits(GetShortLen1(Length));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (Length=0;;Length++)
|
||
|
if (((BitField^ShortXor2[Length]) & (~(0xff>>GetShortLen2(Length))))==0)
|
||
|
break;
|
||
|
faddbits(GetShortLen2(Length));
|
||
|
}
|
||
|
|
||
|
if (Length >= 9)
|
||
|
{
|
||
|
if (Length == 9)
|
||
|
{
|
||
|
LCount++;
|
||
|
OldCopyString((unsigned int)LastDist,LastLength);
|
||
|
return;
|
||
|
}
|
||
|
if (Length == 14)
|
||
|
{
|
||
|
LCount=0;
|
||
|
Length=DecodeNum(fgetbits(),STARTL2,DecL2,PosL2)+5;
|
||
|
Distance=(fgetbits()>>1) | 0x8000;
|
||
|
faddbits(15);
|
||
|
LastLength=Length;
|
||
|
LastDist=Distance;
|
||
|
OldCopyString(Distance,Length);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
LCount=0;
|
||
|
SaveLength=Length;
|
||
|
Distance=OldDist[(OldDistPtr-(Length-9)) & 3];
|
||
|
Length=DecodeNum(fgetbits(),STARTL1,DecL1,PosL1)+2;
|
||
|
if (Length==0x101 && SaveLength==10)
|
||
|
{
|
||
|
Buf60 ^= 1;
|
||
|
return;
|
||
|
}
|
||
|
if (Distance > 256)
|
||
|
Length++;
|
||
|
if (Distance >= MaxDist3)
|
||
|
Length++;
|
||
|
|
||
|
OldDist[OldDistPtr++]=Distance;
|
||
|
OldDistPtr = OldDistPtr & 3;
|
||
|
LastLength=Length;
|
||
|
LastDist=Distance;
|
||
|
OldCopyString(Distance,Length);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
LCount=0;
|
||
|
AvrLn1 += Length;
|
||
|
AvrLn1 -= AvrLn1 >> 4;
|
||
|
|
||
|
DistancePlace=DecodeNum(fgetbits(),STARTHF2,DecHf2,PosHf2) & 0xff;
|
||
|
Distance=ChSetA[DistancePlace];
|
||
|
if (--DistancePlace != -1)
|
||
|
{
|
||
|
PlaceA[Distance]--;
|
||
|
LastDistance=ChSetA[DistancePlace];
|
||
|
PlaceA[LastDistance]++;
|
||
|
ChSetA[DistancePlace+1]=LastDistance;
|
||
|
ChSetA[DistancePlace]=Distance;
|
||
|
}
|
||
|
Length+=2;
|
||
|
OldDist[OldDistPtr++] = ++Distance;
|
||
|
OldDistPtr = OldDistPtr & 3;
|
||
|
LastLength=Length;
|
||
|
LastDist=Distance;
|
||
|
OldCopyString(Distance,Length);
|
||
|
}
|
||
|
|
||
|
|
||
|
void Unpack::LongLZ()
|
||
|
{
|
||
|
unsigned int Length;
|
||
|
unsigned int Distance;
|
||
|
unsigned int DistancePlace,NewDistancePlace;
|
||
|
unsigned int OldAvr2,OldAvr3;
|
||
|
|
||
|
NumHuf=0;
|
||
|
Nlzb+=16;
|
||
|
if (Nlzb > 0xff)
|
||
|
{
|
||
|
Nlzb=0x90;
|
||
|
Nhfb >>= 1;
|
||
|
}
|
||
|
OldAvr2=AvrLn2;
|
||
|
|
||
|
unsigned int BitField=fgetbits();
|
||
|
if (AvrLn2 >= 122)
|
||
|
Length=DecodeNum(BitField,STARTL2,DecL2,PosL2);
|
||
|
else
|
||
|
if (AvrLn2 >= 64)
|
||
|
Length=DecodeNum(BitField,STARTL1,DecL1,PosL1);
|
||
|
else
|
||
|
if (BitField < 0x100)
|
||
|
{
|
||
|
Length=BitField;
|
||
|
faddbits(16);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (Length=0;((BitField<<Length)&0x8000)==0;Length++)
|
||
|
;
|
||
|
faddbits(Length+1);
|
||
|
}
|
||
|
|
||
|
AvrLn2 += Length;
|
||
|
AvrLn2 -= AvrLn2 >> 5;
|
||
|
|
||
|
BitField=fgetbits();
|
||
|
if (AvrPlcB > 0x28ff)
|
||
|
DistancePlace=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2);
|
||
|
else
|
||
|
if (AvrPlcB > 0x6ff)
|
||
|
DistancePlace=DecodeNum(BitField,STARTHF1,DecHf1,PosHf1);
|
||
|
else
|
||
|
DistancePlace=DecodeNum(BitField,STARTHF0,DecHf0,PosHf0);
|
||
|
|
||
|
AvrPlcB += DistancePlace;
|
||
|
AvrPlcB -= AvrPlcB >> 8;
|
||
|
while (1)
|
||
|
{
|
||
|
Distance = ChSetB[DistancePlace & 0xff];
|
||
|
NewDistancePlace = NToPlB[Distance++ & 0xff]++;
|
||
|
if (!(Distance & 0xff))
|
||
|
CorrHuff(ChSetB,NToPlB);
|
||
|
else
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
ChSetB[DistancePlace]=ChSetB[NewDistancePlace];
|
||
|
ChSetB[NewDistancePlace]=Distance;
|
||
|
|
||
|
Distance=((Distance & 0xff00) | (fgetbits() >> 8)) >> 1;
|
||
|
faddbits(7);
|
||
|
|
||
|
OldAvr3=AvrLn3;
|
||
|
if (Length!=1 && Length!=4)
|
||
|
if (Length==0 && Distance <= MaxDist3)
|
||
|
{
|
||
|
AvrLn3++;
|
||
|
AvrLn3 -= AvrLn3 >> 8;
|
||
|
}
|
||
|
else
|
||
|
if (AvrLn3 > 0)
|
||
|
AvrLn3--;
|
||
|
Length+=3;
|
||
|
if (Distance >= MaxDist3)
|
||
|
Length++;
|
||
|
if (Distance <= 256)
|
||
|
Length+=8;
|
||
|
if (OldAvr3 > 0xb0 || AvrPlc >= 0x2a00 && OldAvr2 < 0x40)
|
||
|
MaxDist3=0x7f00;
|
||
|
else
|
||
|
MaxDist3=0x2001;
|
||
|
OldDist[OldDistPtr++]=Distance;
|
||
|
OldDistPtr = OldDistPtr & 3;
|
||
|
LastLength=Length;
|
||
|
LastDist=Distance;
|
||
|
OldCopyString(Distance,Length);
|
||
|
}
|
||
|
|
||
|
|
||
|
void Unpack::HuffDecode()
|
||
|
{
|
||
|
unsigned int CurByte,NewBytePlace;
|
||
|
unsigned int Length;
|
||
|
unsigned int Distance;
|
||
|
int BytePlace;
|
||
|
|
||
|
unsigned int BitField=fgetbits();
|
||
|
|
||
|
if (AvrPlc > 0x75ff)
|
||
|
BytePlace=DecodeNum(BitField,STARTHF4,DecHf4,PosHf4);
|
||
|
else
|
||
|
if (AvrPlc > 0x5dff)
|
||
|
BytePlace=DecodeNum(BitField,STARTHF3,DecHf3,PosHf3);
|
||
|
else
|
||
|
if (AvrPlc > 0x35ff)
|
||
|
BytePlace=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2);
|
||
|
else
|
||
|
if (AvrPlc > 0x0dff)
|
||
|
BytePlace=DecodeNum(BitField,STARTHF1,DecHf1,PosHf1);
|
||
|
else
|
||
|
BytePlace=DecodeNum(BitField,STARTHF0,DecHf0,PosHf0);
|
||
|
BytePlace&=0xff;
|
||
|
if (StMode)
|
||
|
{
|
||
|
if (BytePlace==0 && BitField > 0xfff)
|
||
|
BytePlace=0x100;
|
||
|
if (--BytePlace==-1)
|
||
|
{
|
||
|
BitField=fgetbits();
|
||
|
faddbits(1);
|
||
|
if (BitField & 0x8000)
|
||
|
{
|
||
|
NumHuf=StMode=0;
|
||
|
return;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Length = (BitField & 0x4000) ? 4 : 3;
|
||
|
faddbits(1);
|
||
|
Distance=DecodeNum(fgetbits(),STARTHF2,DecHf2,PosHf2);
|
||
|
Distance = (Distance << 5) | (fgetbits() >> 11);
|
||
|
faddbits(5);
|
||
|
OldCopyString(Distance,Length);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
if (NumHuf++ >= 16 && FlagsCnt==0)
|
||
|
StMode=1;
|
||
|
AvrPlc += BytePlace;
|
||
|
AvrPlc -= AvrPlc >> 8;
|
||
|
Nhfb+=16;
|
||
|
if (Nhfb > 0xff)
|
||
|
{
|
||
|
Nhfb=0x90;
|
||
|
Nlzb >>= 1;
|
||
|
}
|
||
|
|
||
|
Window[UnpPtr++]=(byte)(ChSet[BytePlace]>>8);
|
||
|
--DestUnpSize;
|
||
|
|
||
|
while (1)
|
||
|
{
|
||
|
CurByte=ChSet[BytePlace];
|
||
|
NewBytePlace=NToPl[CurByte++ & 0xff]++;
|
||
|
if ((CurByte & 0xff) > 0xa1)
|
||
|
CorrHuff(ChSet,NToPl);
|
||
|
else
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
ChSet[BytePlace]=ChSet[NewBytePlace];
|
||
|
ChSet[NewBytePlace]=CurByte;
|
||
|
}
|
||
|
|
||
|
|
||
|
void Unpack::GetFlagsBuf()
|
||
|
{
|
||
|
unsigned int Flags,NewFlagsPlace;
|
||
|
unsigned int FlagsPlace=DecodeNum(fgetbits(),STARTHF2,DecHf2,PosHf2);
|
||
|
|
||
|
while (1)
|
||
|
{
|
||
|
Flags=ChSetC[FlagsPlace];
|
||
|
FlagBuf=Flags>>8;
|
||
|
NewFlagsPlace=NToPlC[Flags++ & 0xff]++;
|
||
|
if ((Flags & 0xff) != 0)
|
||
|
break;
|
||
|
CorrHuff(ChSetC,NToPlC);
|
||
|
}
|
||
|
|
||
|
ChSetC[FlagsPlace]=ChSetC[NewFlagsPlace];
|
||
|
ChSetC[NewFlagsPlace]=Flags;
|
||
|
}
|
||
|
|
||
|
|
||
|
void Unpack::OldUnpInitData(int Solid)
|
||
|
{
|
||
|
if (!Solid)
|
||
|
{
|
||
|
AvrPlcB=AvrLn1=AvrLn2=AvrLn3=NumHuf=Buf60=0;
|
||
|
AvrPlc=0x3500;
|
||
|
MaxDist3=0x2001;
|
||
|
Nhfb=Nlzb=0x80;
|
||
|
}
|
||
|
FlagsCnt=0;
|
||
|
FlagBuf=0;
|
||
|
StMode=0;
|
||
|
LCount=0;
|
||
|
ReadTop=0;
|
||
|
}
|
||
|
|
||
|
|
||
|
void Unpack::InitHuff()
|
||
|
{
|
||
|
for (unsigned int I=0;I<256;I++)
|
||
|
{
|
||
|
Place[I]=PlaceA[I]=PlaceB[I]=I;
|
||
|
PlaceC[I]=(~I+1) & 0xff;
|
||
|
ChSet[I]=ChSetB[I]=I<<8;
|
||
|
ChSetA[I]=I;
|
||
|
ChSetC[I]=((~I+1) & 0xff)<<8;
|
||
|
}
|
||
|
memset(NToPl,0,sizeof(NToPl));
|
||
|
memset(NToPlB,0,sizeof(NToPlB));
|
||
|
memset(NToPlC,0,sizeof(NToPlC));
|
||
|
CorrHuff(ChSetB,NToPlB);
|
||
|
}
|
||
|
|
||
|
|
||
|
void Unpack::CorrHuff(unsigned int *CharSet,unsigned int *NumToPlace)
|
||
|
{
|
||
|
int I,J;
|
||
|
for (I=7;I>=0;I--)
|
||
|
for (J=0;J<32;J++,CharSet++)
|
||
|
*CharSet=(*CharSet & ~0xff) | I;
|
||
|
memset(NumToPlace,0,sizeof(NToPl));
|
||
|
for (I=6;I>=0;I--)
|
||
|
NumToPlace[I]=(7-I)*32;
|
||
|
}
|
||
|
|
||
|
|
||
|
void Unpack::OldCopyString(unsigned int Distance,unsigned int Length)
|
||
|
{
|
||
|
DestUnpSize-=Length;
|
||
|
while (Length--)
|
||
|
{
|
||
|
Window[UnpPtr]=Window[(UnpPtr-Distance) & MAXWINMASK];
|
||
|
UnpPtr=(UnpPtr+1) & MAXWINMASK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
uint Unpack::DecodeNum(uint Num,uint StartPos,uint *DecTab,uint *PosTab)
|
||
|
{
|
||
|
int I;
|
||
|
for (Num&=0xfff0,I=0;DecTab[I]<=Num;I++)
|
||
|
StartPos++;
|
||
|
faddbits(StartPos);
|
||
|
return(((Num-(I ? DecTab[I-1]:0))>>(16-StartPos))+PosTab[StartPos]);
|
||
|
}
|