/****** ***** ****** ** ** ** ** ** ** unRAR utility version 1.01 ****** ******* ****** ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ** ** ** ** ** ** FREE portable version ** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~ Unpacking algorithm procedures YOU DO NOT NEED TO CHANGE THERE ANYTHING. */ void MakeTbl(); /* Makes Huffman table */ void AddBit(); /* Shift buffer pointer to NBits */ void CopyString(); /* string copy */ void ShortLZ(); /* unpacks short, near and special LZ codes */ void LongLZ(); /* unpacks long and far LZ codes */ void HuffDecode(); /* Huffman decoding */ int UnpWriteBuf(); /* writes output buffer */ int UnpReadBuf(); /* reads output buffer */ void GetFlagsBuf(); /* gets flag byte */ void UnpInitData(); /* reset initial data */ void InitHuff(); /* initializing Huffman tables */ void CorrHuff(); /* Huffman table correction in case of overflow */ void CreateEncTbl(); /* create decoding tables */ void CreateOneTbl(); /* subfunction of previous */ int unpack(); /* unpacking procedure itself */ #define SUSPEND 1 #define SIZE_PBUF 0x2000 #define FIRST 1 #define NEXT 2 #define UNP_MEMORY 0x10010L+sizeof(struct UnpData)+ \ sizeof(struct DecodeTables)+SIZE_PBUF UWORD hcdsh1[]={ 0x0001,0xa003,0xd004,0xe004,0xf005,0xf806,0xfc07,0xfe08, 0xff08,0xc004,0x8004,0x9005,0x9806,0x9c06,0 }; UWORD hcdsh2[]={ 0x0002,0x4003,0x6003,0xa003,0xd004,0xe004,0xf005,0xf806, 0xfc06,0xc004,0x8004,0x9005,0x9806,0x9c06,0 }; UWORD hcdsh3[]={ 0x0001,0xa004,0xd004,0xe004,0xf005,0xf806,0xfc07,0xfe08, 0xff08,0xc004,0x8004,0x9005,0x9806,0x9c06,0xb004,0 }; UWORD hcdsh4[]={ 0x0002,0x4003,0x6003,0xa004,0xd004,0xe004,0xf005,0xf806, 0xfc06,0xc004,0x8004,0x9005,0x9806,0x9c06,0xb004,0 }; UWORD hcdln0[]={ 0x8001,0x4002,0x2003,0x1004,0x0805,0x0406,0x0207,0x0108, 0x0008,0 }; UWORD hcdln1[258],hcdln2[258]; UWORD hcode0[258],hcode1[258],hcode2[258],hcode3[258],hcode4[258]; struct MakeHuffTabs { UWORD *Table; UBYTE HuffCodeCount[12]; } MakeTab[]={ {hcdln1,{0 ,2 ,1 ,2 ,2 ,4 ,5 ,4 ,4 ,8 ,0 ,224}}, {hcdln2,{0 ,0 ,5 ,2 ,2 ,4 ,5 ,4 ,4 ,8 ,2 ,220}}, {hcode0,{0 ,0 ,0 ,8 ,8 ,8 ,9 ,0 ,0 ,0 ,0 ,224}}, {hcode1,{0 ,0 ,0 ,0 ,4 ,40 ,16 ,16 ,4 ,0 ,47 ,130}}, {hcode2,{0 ,0 ,0 ,0 ,2 ,5 ,46 ,64 ,116 ,24 ,0 ,0 }}, {hcode3,{0 ,0 ,0 ,0 ,0 ,2 ,14 ,202 ,33 ,6 ,0 ,0 }}, {hcode4,{0 ,0 ,0 ,0 ,0 ,0 ,0 ,255 ,2 ,0 ,0 ,0 }}}; SDWORD DestUnpSize=0; UBYTE FlagBuf; UWORD InAdr,OutAdr; unsigned int Suspend=0; unsigned int NumBit; unsigned int LCount; int FlagsCnt; struct UnpData { UWORD ChSet[256]; UBYTE Place[256]; UBYTE NToPl[256]; UBYTE ChSetA[256]; UBYTE PlaceA[256]; UWORD ChSetB[256]; UBYTE PlaceB[256]; UBYTE NToPlB[256]; UWORD ChSetC[256]; UBYTE PlaceC[256]; UBYTE NToPlC[256]; UWORD AvrPlc; UWORD AvrPlcB; UWORD AvrLn1; UWORD AvrLn2; UWORD AvrLn3; UBYTE NumHuf; UBYTE StMode; UWORD Nhfb; UWORD Nlzb; UWORD MaxDist3; UBYTE Buf60; UWORD WrAddr; UWORD SomeRd; UWORD UnpAllBuf; UWORD LastDist; UWORD LastLen; UWORD OldDist[4]; UWORD OldDistNum; } *D; struct DecodeTables { UBYTE ECDSH1[256]; UBYTE ECDSH2[256]; UBYTE ECDSH3[256]; UBYTE ECDSH4[256]; UBYTE ECDLN0[256]; UBYTE ECDLN1[4096]; UBYTE ECDLN2[4096]; UBYTE ECODE0[4096]; UBYTE ECODE1[4096]; UBYTE ECODE2[1024]; UBYTE ECODE3[1024]; UBYTE ECODE4[1024]; UBYTE NCDSH1[16]; UBYTE NCDSH2[16]; UBYTE NCDSH3[16]; UBYTE NCDSH4[16]; UBYTE NCDLN0[256]; UBYTE NCDLN1[256]; UBYTE NCDLN2[256]; UBYTE NCODE0[257]; UBYTE NCODE1[257]; UBYTE NCODE2[257]; UBYTE NCODE3[257]; UBYTE NCODE4[257]; } *T; UBYTE *PackBuf; HPBYTE UnpBuf; int (* UnpReadFn)(); int (* UnpWriteFn)(); #define GetField() ((UWORD)((((UDWORD)PackBuf[InAdr] << 16) | \ ((UWORD)PackBuf[InAdr+1] << 8) | PackBuf[InAdr+2]) \ >> (8-NumBit))) void AddBit(NBits) unsigned int NBits; { InAdr += (NumBit+NBits) >> 3; NumBit = (NumBit+NBits) & 7; } void CopyString(Distance,Length) UWORD Distance; unsigned int Length; { DestUnpSize-=Length; while (Length--) { UnpBuf[OutAdr]=UnpBuf[(UWORD)(OutAdr-Distance)]; OutAdr++; } } int unpack(UnpMem,UnpRead,UnpWrite,Solid) HPBYTE UnpMem; int (* UnpRead)(); int (* UnpWrite)(); int Solid; { UnpReadFn=UnpRead; UnpWriteFn=UnpWrite; UnpBuf=(UBYTE *)UnpMem; PackBuf=(UBYTE *)(UnpMem+0x10000L+sizeof(struct UnpData)+sizeof(struct DecodeTables)); D=(struct UnpData *)(UnpMem+0x10000L); if (Suspend) OutAdr=D->WrAddr; else { UnpInitData(Solid); if (!Solid) { InitHuff(); memset(UnpBuf,0,0x8000); memset(UnpBuf+0x8000,0,0x8000); OutAdr=0; } else OutAdr=D->WrAddr; if (--DestUnpSize < 0) return(0); if (UnpReadBuf(FIRST)==-1) return(-1); GetFlagsBuf(); FlagsCnt=8; } while (DestUnpSize>=0) { if (InAdr >= SIZE_PBUF-12) if (UnpReadBuf(NEXT)==-1) return(-1); if ((UWORD)(D->WrAddr - OutAdr) < 0x110 && D->WrAddr!=OutAdr) { if (UnpWriteBuf()==-1) return(-1); if (Suspend) return(0); } if (D->StMode) { HuffDecode(); continue; } if (--FlagsCnt < 0) { GetFlagsBuf(); FlagsCnt=7; } if (FlagBuf >= 0x80) { FlagBuf<<=1; if (D->Nlzb > D->Nhfb) LongLZ(); else HuffDecode(); } else { FlagBuf<<=1; if (--FlagsCnt < 0) { GetFlagsBuf(); FlagsCnt=7; } if (FlagBuf >= 0x80) { FlagBuf<<=1; if (D->Nlzb > D->Nhfb) HuffDecode(); else LongLZ(); } else { FlagBuf<<=1; ShortLZ(); } } } if (UnpWriteBuf()==-1) return(-1); return(0); } void ShortLZ() { UWORD LengthCode,SaveLength; UBYTE LastDistance; UWORD Distance,DistancePlace,Length; D->NumHuf=0; LengthCode=GetField(); if (LCount==2) { AddBit(1); if (LengthCode >= 0x8000) { CopyString(D->LastDist,D->LastLen); return; } LengthCode <<= 1; LCount=0; } LengthCode >>= 8; if (D->Buf60==0) if (D->AvrLn1<37) { Length=T->ECDSH1[LengthCode]; AddBit(T->NCDSH1[Length]); } else { Length=T->ECDSH2[LengthCode]; AddBit(T->NCDSH2[Length]); } else if (D->AvrLn1<37) { Length=T->ECDSH3[LengthCode]; AddBit(T->NCDSH3[Length]); } else { Length=T->ECDSH4[LengthCode]; AddBit(T->NCDSH4[Length]); } if (Length >= 9) { if (Length == 9) { LCount++; CopyString(D->LastDist,D->LastLen); return; } if (Length == 14) { LCount=0; Length=T->ECDLN2[GetField() >> 4]; AddBit(T->NCDLN2[Length]); Length+=5; Distance=(GetField() >> 1) | 0x8000; AddBit(15); D->LastLen=Length; D->LastDist=Distance; CopyString(Distance,Length); return; } LCount=0; SaveLength=Length; Distance=D->OldDist[(D->OldDistNum-(Length-9)) & 3]; Length=T->ECDLN1[GetField() >> 4]; AddBit(T->NCDLN1[Length]); Length+=2; if (Length==0x101 && SaveLength==10) { D->Buf60 ^= 1; return; } if (Distance > 256) Length++; if (Distance > D->MaxDist3) Length++; D->OldDist[D->OldDistNum++]=Distance; D->OldDistNum = D->OldDistNum & 3; D->LastLen=Length; D->LastDist=Distance; CopyString(Distance,Length); return; } LCount=0; D->AvrLn1 += Length; D->AvrLn1 -= D->AvrLn1 >> 4; DistancePlace=T->ECODE2[GetField() >> 6]; AddBit(T->NCODE2[DistancePlace]); Distance=D->ChSetA[DistancePlace]; if (--DistancePlace != 0xFFFF) { D->PlaceA[Distance]--; LastDistance=D->ChSetA[DistancePlace]; D->PlaceA[LastDistance]++; D->ChSetA[DistancePlace+1]=LastDistance; D->ChSetA[DistancePlace]=(UBYTE)Distance; } Length+=2; D->OldDist[D->OldDistNum++] = ++Distance; D->OldDistNum = D->OldDistNum & 3; D->LastLen=Length; D->LastDist=Distance; CopyString(Distance,Length); return; } void LongLZ() { UWORD LengthCode,Length; UWORD Distance,DistancePlace,NewDistancePlace; UWORD oldav2,oldav3; D->NumHuf=0; D->Nlzb+=16; if (D->Nlzb > 0xff) { D->Nlzb=0x90; D->Nhfb >>= 1; } oldav2=D->AvrLn2; if (D->AvrLn2 >= 122) { Length=T->ECDLN2[GetField() >> 4]; AddBit(T->NCDLN2[Length]); } else if (D->AvrLn2 >= 64) { Length=T->ECDLN1[GetField() >> 4]; AddBit(T->NCDLN1[Length]); } else { LengthCode=GetField(); if (LengthCode < 0x100) { Length=LengthCode; AddBit(16); } else { Length=T->ECDLN0[LengthCode >> 8]; AddBit(T->NCDLN0[Length]); } } D->AvrLn2 += Length; D->AvrLn2 -= D->AvrLn2 >> 5; if (D->AvrPlcB > 0x28ff) { DistancePlace=T->ECODE2[GetField() >> 6]; AddBit(T->NCODE2[DistancePlace]); } else if (D->AvrPlcB > 0x6ff) { DistancePlace=T->ECODE1[GetField() >> 4]; AddBit(T->NCODE1[DistancePlace]); } else { DistancePlace=T->ECODE0[GetField() >> 4]; AddBit(T->NCODE0[DistancePlace]); } D->AvrPlcB += DistancePlace; D->AvrPlcB -= D->AvrPlcB >> 8; while (1) { Distance = D->ChSetB[DistancePlace]; NewDistancePlace = D->NToPlB[Distance++ & 0xff]++; if (!(Distance & 0xff)) { Distance-=0x100; CorrHuff(D->ChSetB,D->NToPlB); } else break; } D->ChSetB[DistancePlace]=D->ChSetB[NewDistancePlace]; D->ChSetB[NewDistancePlace]=Distance; Distance=((UWORD)((Distance & ~0xff) | (GetField() >> 8))) >> 1; AddBit(7); oldav3=D->AvrLn3; if (Length!=1 && Length!=4) if (Length==0 && Distance <= D->MaxDist3) { D->AvrLn3++; D->AvrLn3 -= D->AvrLn3 >> 8; } else if (D->AvrLn3 > 0) D->AvrLn3--; Length+=3; if (Distance >= D->MaxDist3) Length++; if (Distance <= 256) Length+=8; if (oldav3 > 0xb0 || D->AvrPlc >= 0x2a00 && oldav2 < 0x40) D->MaxDist3=0x7f00; else D->MaxDist3=0x2001; D->OldDist[D->OldDistNum++]=Distance; D->OldDistNum = D->OldDistNum & 3; D->LastLen=Length; D->LastDist=Distance; CopyString(Distance,Length); } void HuffDecode() { UWORD CurByte,BytePlace,NewBytePlace; UWORD Length,Distance,Code; Code=GetField(); if (D->AvrPlc > 0x75ff) { BytePlace=T->ECODE4[Code>>6]; if (D->StMode && BytePlace==0 && Code > 0xfff) BytePlace=0x100; AddBit(T->NCODE4[BytePlace]); } else if (D->AvrPlc > 0x5dff) { BytePlace=T->ECODE3[Code>>6]; if (D->StMode && BytePlace==0 && Code > 0xfff) BytePlace=0x100; AddBit(T->NCODE3[BytePlace]); } else if (D->AvrPlc > 0x35ff) { BytePlace=T->ECODE2[Code>>6]; if (D->StMode && BytePlace==0 && Code > 0xfff) BytePlace=0x100; AddBit(T->NCODE2[BytePlace]); } else if (D->AvrPlc > 0x0dff) { BytePlace=T->ECODE1[Code>>4]; if (D->StMode && BytePlace==0 && Code > 0xfff) BytePlace=0x100; AddBit(T->NCODE1[BytePlace]); } else { BytePlace=T->ECODE0[Code>>4]; if (D->StMode && BytePlace==0 && Code > 0xfff) BytePlace=0x100; AddBit(T->NCODE0[BytePlace]); } if (D->StMode) { if (--BytePlace==0xFFFF) { Code=GetField(); AddBit(1); if (Code >= 0x8000) { D->NumHuf=D->StMode=0; return; } else { Length = (Code & 0x4000) ? 4 : 3; Distance= T->ECODE2[(Code >> 4) & 0x3ff]; AddBit(T->NCODE2[Distance]+1); Distance = (Distance << 5) | (GetField() >> 11); AddBit(5); CopyString(Distance,Length); return; } } } else if (D->NumHuf++ >= 16 && FlagsCnt==0) D->StMode=1; D->AvrPlc += BytePlace; D->AvrPlc -= D->AvrPlc >> 8; D->Nhfb+=16; if (D->Nhfb > 0xff) { D->Nhfb=0x90; D->Nlzb >>= 1; } UnpBuf[OutAdr++]=(UBYTE)(D->ChSet[BytePlace]>>8); DestUnpSize--; while (1) { CurByte=D->ChSet[BytePlace]; NewBytePlace=D->NToPl[CurByte++ & 0xff]++; if ((CurByte & 0xff) > 0xa1) CorrHuff(D->ChSet,D->NToPl); else break; } D->ChSet[BytePlace]=D->ChSet[NewBytePlace]; D->ChSet[NewBytePlace]=CurByte; } int UnpWriteBuf() { if (OutAdrWrAddr) { if (UnpWriteFn((UBYTE *)(UnpBuf+D->WrAddr),(UWORD)-D->WrAddr)==-1 || UnpWriteFn((UBYTE *)UnpBuf,(UWORD)OutAdr)==-1) return(-1); } else if (UnpWriteFn((UBYTE *)(UnpBuf+D->WrAddr),(UWORD)(OutAdr-D->WrAddr))==-1) return(-1); D->WrAddr=OutAdr; return(0); } int UnpReadBuf(NumBuf) int NumBuf; { int ReadCode; if (NumBuf==FIRST) ReadCode=UnpReadFn(PackBuf,SIZE_PBUF); else { memcpy(PackBuf,PackBuf+InAdr,(UWORD)(SIZE_PBUF-InAdr)); ReadCode=UnpReadFn(PackBuf+SIZE_PBUF-InAdr,(UWORD)InAdr); } InAdr=0; if (ReadCode==-1) return(-1); return(0); } void GetFlagsBuf() { UWORD Flags,FlagsPlace,NewFlagsPlace; FlagsPlace=T->ECODE2[GetField() >> 6]; AddBit(T->NCODE2[FlagsPlace]); while (1) { Flags=D->ChSetC[FlagsPlace]; FlagBuf=(UBYTE)(Flags >> 8); NewFlagsPlace=D->NToPlC[Flags++ & 0xff]++; if ((Flags & 0xff) == 0) { Flags-=0x100; CorrHuff(D->ChSetC,D->NToPlC); } else break; } D->ChSetC[FlagsPlace]=D->ChSetC[NewFlagsPlace]; D->ChSetC[NewFlagsPlace]=Flags; } void UnpInitData(Solid) int Solid; { if (!Solid) { memset(D,0,sizeof(struct UnpData)); D->AvrPlc=0x3500; D->MaxDist3=0x2001; D->Nhfb=D->Nlzb=0x80; } FlagsCnt=0; FlagBuf=0; InAdr=0; NumBit=0; D->StMode=0; LCount=0; } void InitHuff() { UWORD I; for (I=0;I<256;I++) { D->Place[I]=D->PlaceA[I]=D->PlaceB[I]=(UBYTE)I; D->PlaceC[I]=(UBYTE)(~I+1); D->ChSet[I]=D->ChSetB[I]=I<<8; D->ChSetA[I]=(UBYTE)I; D->ChSetC[I]=(~I+1)<<8; } memset(D->NToPl,0,sizeof(D->NToPl)); memset(D->NToPlB,0,sizeof(D->NToPlB)); memset(D->NToPlC,0,sizeof(D->NToPlC)); CorrHuff(D->ChSetB,D->NToPlB); } void CorrHuff(CharSet,NumToPlace) UWORD *CharSet; UBYTE *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(D->NToPl)); for (I=6;I>=0;I--) NumToPlace[I]=(7-I)*32; } void CreateEncTbl(UnpMem) HPBYTE UnpMem; { T=(struct DecodeTables *)(UnpMem+0x10000L+sizeof(struct UnpData)); CreateOneTbl(hcdsh1,T->ECDSH1,T->NCDSH1,8); CreateOneTbl(hcdsh2,T->ECDSH2,T->NCDSH2,8); CreateOneTbl(hcdsh3,T->ECDSH3,T->NCDSH3,8); CreateOneTbl(hcdsh4,T->ECDSH4,T->NCDSH4,8); CreateOneTbl(hcdln0,T->ECDLN0,T->NCDLN0,8); CreateOneTbl(hcdln1,T->ECDLN1,T->NCDLN1,4); CreateOneTbl(hcdln2,T->ECDLN2,T->NCDLN2,4); CreateOneTbl(hcode0,T->ECODE0,T->NCODE0,4); CreateOneTbl(hcode1,T->ECODE1,T->NCODE1,4); CreateOneTbl(hcode2,T->ECODE2,T->NCODE2,6); CreateOneTbl(hcode3,T->ECODE3,T->NCODE3,6); CreateOneTbl(hcode4,T->ECODE4,T->NCODE4,6); } void CreateOneTbl(hcd,ecd,ncd,ShiftCount) UWORD *hcd; UBYTE *ecd; UBYTE *ncd; UBYTE ShiftCount; { UWORD I,MaxCode,Code; for (I=0; hcd[I]; I++) { ncd[I]=(UBYTE)(hcd[I] & 0xf); Code=hcd[I] >> ShiftCount; MaxCode=1 << (16-ShiftCount-(UBYTE)(hcd[I] & 0xf)); while (MaxCode--) ecd[Code++]=(UBYTE)I; } } void MakeTbl() { UWORD I,J,K,Code; UWORD *OutTab; for (I=0;I