123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524 |
- /*
- * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
- * Original author: Edmund Wagner
- * Creation date: 21.06.2007
- *
- * the unrar licence applies to all junrar source and binary distributions
- * you are not allowed to use this source to re-create the RAR compression algorithm
- */
- using System;
- using SharpCompress.Compressors.Rar.UnpackV1.Decode;
- namespace SharpCompress.Compressors.Rar.UnpackV1
- {
- internal partial class Unpack
- {
- private readonly MultDecode[] MD = new MultDecode[4];
- private readonly byte[] UnpOldTable20 = new byte[PackDef.MC20 * 4];
- private int UnpAudioBlock, UnpChannels, UnpCurChannel, UnpChannelDelta;
- private readonly AudioVariables[] AudV = new AudioVariables[4];
- private readonly LitDecode LD = new LitDecode();
- private readonly DistDecode DD = new DistDecode();
- private readonly LowDistDecode LDD = new LowDistDecode();
- private readonly RepDecode RD = new RepDecode();
- private readonly BitDecode BD = new BitDecode();
- private static readonly int[] 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
- };
- private static readonly byte[] 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
- };
- private static readonly int[] DDecode =
- {
- 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384,
- 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384,
- 24576, 32768, 49152, 65536, 98304, 131072, 196608, 262144, 327680,
- 393216, 458752, 524288, 589824, 655360, 720896, 786432, 851968,
- 917504, 983040
- };
- private static readonly int[] DBits =
- {
- 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10,
- 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16
- , 16, 16, 16, 16, 16, 16, 16
- };
- private static readonly int[] SDDecode = {0, 4, 8, 16, 32, 64, 128, 192};
- private static readonly int[] SDBits = {2, 2, 3, 4, 5, 6, 6, 6};
- private void unpack20(bool solid)
- {
- int Bits;
- if (suspended)
- {
- unpPtr = wrPtr;
- }
- else
- {
- UnpInitData(solid);
- if (!unpReadBuf())
- {
- return;
- }
- if (!solid)
- {
- if (!ReadTables20())
- {
- return;
- }
- }
- --destUnpSize;
- }
- while (destUnpSize >= 0)
- {
- unpPtr &= PackDef.MAXWINMASK;
- if (inAddr > readTop - 30)
- {
- if (!unpReadBuf())
- {
- break;
- }
- }
- if (((wrPtr - unpPtr) & PackDef.MAXWINMASK) < 270 && wrPtr != unpPtr)
- {
- oldUnpWriteBuf();
- if (suspended)
- {
- return;
- }
- }
- if (UnpAudioBlock != 0)
- {
- int AudioNumber = this.decodeNumber(MD[UnpCurChannel]);
- if (AudioNumber == 256)
- {
- if (!ReadTables20())
- {
- break;
- }
- continue;
- }
- window[unpPtr++] = DecodeAudio(AudioNumber);
- if (++UnpCurChannel == UnpChannels)
- {
- UnpCurChannel = 0;
- }
- --destUnpSize;
- continue;
- }
- int Number = this.decodeNumber(LD);
- if (Number < 256)
- {
- window[unpPtr++] = (byte)Number;
- --destUnpSize;
- continue;
- }
- if (Number > 269)
- {
- int Length = LDecode[Number -= 270] + 3;
- if ((Bits = LBits[Number]) > 0)
- {
- Length += Utility.URShift(GetBits(), (16 - Bits));
- AddBits(Bits);
- }
- int DistNumber = this.decodeNumber(DD);
- int Distance = DDecode[DistNumber] + 1;
- if ((Bits = DBits[DistNumber]) > 0)
- {
- Distance += Utility.URShift(GetBits(), (16 - Bits));
- AddBits(Bits);
- }
- if (Distance >= 0x2000)
- {
- Length++;
- if (Distance >= 0x40000L)
- {
- Length++;
- }
- }
- CopyString20(Length, Distance);
- continue;
- }
- if (Number == 269)
- {
- if (!ReadTables20())
- {
- break;
- }
- continue;
- }
- if (Number == 256)
- {
- CopyString20(lastLength, lastDist);
- continue;
- }
- if (Number < 261)
- {
- int Distance = oldDist[(oldDistPtr - (Number - 256)) & 3];
- int LengthNumber = this.decodeNumber(RD);
- int Length = LDecode[LengthNumber] + 2;
- if ((Bits = LBits[LengthNumber]) > 0)
- {
- Length += Utility.URShift(GetBits(), (16 - Bits));
- AddBits(Bits);
- }
- if (Distance >= 0x101)
- {
- Length++;
- if (Distance >= 0x2000)
- {
- Length++;
- if (Distance >= 0x40000)
- {
- Length++;
- }
- }
- }
- CopyString20(Length, Distance);
- continue;
- }
- if (Number < 270)
- {
- int Distance = SDDecode[Number -= 261] + 1;
- if ((Bits = SDBits[Number]) > 0)
- {
- Distance += Utility.URShift(GetBits(), (16 - Bits));
- AddBits(Bits);
- }
- CopyString20(2, Distance);
- }
- }
- ReadLastTables();
- oldUnpWriteBuf();
- }
- private void CopyString20(int Length, int Distance)
- {
- lastDist = oldDist[oldDistPtr++ & 3] = Distance;
- lastLength = Length;
- destUnpSize -= Length;
- int DestPtr = unpPtr - Distance;
- if (DestPtr < PackDef.MAXWINSIZE - 300 && unpPtr < PackDef.MAXWINSIZE - 300)
- {
- window[unpPtr++] = window[DestPtr++];
- window[unpPtr++] = window[DestPtr++];
- while (Length > 2)
- {
- Length--;
- window[unpPtr++] = window[DestPtr++];
- }
- }
- else
- {
- while ((Length--) != 0)
- {
- window[unpPtr] = window[DestPtr++ & PackDef.MAXWINMASK];
- unpPtr = (unpPtr + 1) & PackDef.MAXWINMASK;
- }
- }
- }
- private bool ReadTables20()
- {
- byte[] BitLength = new byte[PackDef.BC20];
- byte[] Table = new byte[PackDef.MC20 * 4];
- int TableSize, N, I;
- if (inAddr > readTop - 25)
- {
- if (!unpReadBuf())
- {
- return (false);
- }
- }
- int BitField = GetBits();
- UnpAudioBlock = (BitField & 0x8000);
- if (0 == (BitField & 0x4000))
- {
- // memset(UnpOldTable20,0,sizeof(UnpOldTable20));
- Utility.Fill(UnpOldTable20, (byte)0);
- }
- AddBits(2);
- if (UnpAudioBlock != 0)
- {
- UnpChannels = ((Utility.URShift(BitField, 12)) & 3) + 1;
- if (UnpCurChannel >= UnpChannels)
- {
- UnpCurChannel = 0;
- }
- AddBits(2);
- TableSize = PackDef.MC20 * UnpChannels;
- }
- else
- {
- TableSize = PackDef.NC20 + PackDef.DC20 + PackDef.RC20;
- }
- for (I = 0; I < PackDef.BC20; I++)
- {
- BitLength[I] = (byte)(Utility.URShift(GetBits(), 12));
- AddBits(4);
- }
- UnpackUtility.makeDecodeTables(BitLength, 0, BD, PackDef.BC20);
- I = 0;
- while (I < TableSize)
- {
- if (inAddr > readTop - 5)
- {
- if (!unpReadBuf())
- {
- return (false);
- }
- }
- int Number = this.decodeNumber(BD);
- if (Number < 16)
- {
- Table[I] = (byte)((Number + UnpOldTable20[I]) & 0xf);
- I++;
- }
- else if (Number == 16)
- {
- N = (Utility.URShift(GetBits(), 14)) + 3;
- AddBits(2);
- while (N-- > 0 && I < TableSize)
- {
- Table[I] = Table[I - 1];
- I++;
- }
- }
- else
- {
- if (Number == 17)
- {
- N = (Utility.URShift(GetBits(), 13)) + 3;
- AddBits(3);
- }
- else
- {
- N = (Utility.URShift(GetBits(), 9)) + 11;
- AddBits(7);
- }
- while (N-- > 0 && I < TableSize)
- {
- Table[I++] = 0;
- }
- }
- }
- if (inAddr > readTop)
- {
- return (true);
- }
- if (UnpAudioBlock != 0)
- {
- for (I = 0; I < UnpChannels; I++)
- {
- UnpackUtility.makeDecodeTables(Table, I * PackDef.MC20, MD[I], PackDef.MC20);
- }
- }
- else
- {
- UnpackUtility.makeDecodeTables(Table, 0, LD, PackDef.NC20);
- UnpackUtility.makeDecodeTables(Table, PackDef.NC20, DD, PackDef.DC20);
- UnpackUtility.makeDecodeTables(Table, PackDef.NC20 + PackDef.DC20, RD, PackDef.RC20);
- }
- // memcpy(UnpOldTable20,Table,sizeof(UnpOldTable20));
- for (int i = 0; i < UnpOldTable20.Length; i++)
- {
- UnpOldTable20[i] = Table[i];
- }
- return (true);
- }
- private void unpInitData20(bool Solid)
- {
- if (!Solid)
- {
- UnpChannelDelta = UnpCurChannel = 0;
- UnpChannels = 1;
- // memset(AudV,0,sizeof(AudV));
- AudV[0] = new AudioVariables();
- AudV[1] = new AudioVariables();
- AudV[2] = new AudioVariables();
- AudV[3] = new AudioVariables();
- // memset(UnpOldTable20,0,sizeof(UnpOldTable20));
- Utility.Fill(UnpOldTable20, (byte)0);
- }
- }
- private void ReadLastTables()
- {
- if (readTop >= inAddr + 5)
- {
- if (UnpAudioBlock != 0)
- {
- if (this.decodeNumber(MD[UnpCurChannel]) == 256)
- {
- ReadTables20();
- }
- }
- else
- {
- if (this.decodeNumber(LD) == 269)
- {
- ReadTables20();
- }
- }
- }
- }
- private byte DecodeAudio(int Delta)
- {
- AudioVariables v = AudV[UnpCurChannel];
- v.ByteCount = v.ByteCount + 1;
- v.D4 = v.D3;
- v.D3 = v.D2; // ->D3=V->D2;
- v.D2 = v.LastDelta - v.D1; // ->D2=V->LastDelta-V->D1;
- v.D1 = v.LastDelta; // V->D1=V->LastDelta;
- // int PCh=8*V->LastChar+V->K1*V->D1 +V->K2*V->D2 +V->K3*V->D3
- // +V->K4*V->D4+ V->K5*UnpChannelDelta;
- int PCh = 8 * v.LastChar + v.K1 * v.D1;
- PCh += v.K2 * v.D2 + v.K3 * v.D3;
- PCh += v.K4 * v.D4 + v.K5 * UnpChannelDelta;
- PCh = (Utility.URShift(PCh, 3)) & 0xFF;
- int Ch = PCh - Delta;
- int D = ((byte)Delta) << 3;
- v.Dif[0] += Math.Abs(D); // V->Dif[0]+=abs(D);
- v.Dif[1] += Math.Abs(D - v.D1); // V->Dif[1]+=abs(D-V->D1);
- v.Dif[2] += Math.Abs(D + v.D1); // V->Dif[2]+=abs(D+V->D1);
- v.Dif[3] += Math.Abs(D - v.D2); // V->Dif[3]+=abs(D-V->D2);
- v.Dif[4] += Math.Abs(D + v.D2); // V->Dif[4]+=abs(D+V->D2);
- v.Dif[5] += Math.Abs(D - v.D3); // V->Dif[5]+=abs(D-V->D3);
- v.Dif[6] += Math.Abs(D + v.D3); // V->Dif[6]+=abs(D+V->D3);
- v.Dif[7] += Math.Abs(D - v.D4); // V->Dif[7]+=abs(D-V->D4);
- v.Dif[8] += Math.Abs(D + v.D4); // V->Dif[8]+=abs(D+V->D4);
- v.Dif[9] += Math.Abs(D - UnpChannelDelta); // V->Dif[9]+=abs(D-UnpChannelDelta);
- v.Dif[10] += Math.Abs(D + UnpChannelDelta); // V->Dif[10]+=abs(D+UnpChannelDelta);
- v.LastDelta = (byte)(Ch - v.LastChar);
- UnpChannelDelta = v.LastDelta;
- v.LastChar = Ch; // V->LastChar=Ch;
- if ((v.ByteCount & 0x1F) == 0)
- {
- int MinDif = v.Dif[0], NumMinDif = 0;
- v.Dif[0] = 0; // ->Dif[0]=0;
- for (int I = 1; I < v.Dif.Length; I++)
- {
- if (v.Dif[I] < MinDif)
- {
- MinDif = v.Dif[I];
- NumMinDif = I;
- }
- v.Dif[I] = 0;
- }
- switch (NumMinDif)
- {
- case 1:
- if (v.K1 >= -16)
- {
- v.K1 = v.K1 - 1; // V->K1--;
- }
- break;
- case 2:
- if (v.K1 < 16)
- {
- v.K1 = v.K1 + 1; // V->K1++;
- }
- break;
- case 3:
- if (v.K2 >= -16)
- {
- v.K2 = v.K2 - 1; // V->K2--;
- }
- break;
- case 4:
- if (v.K2 < 16)
- {
- v.K2 = v.K2 + 1; // V->K2++;
- }
- break;
- case 5:
- if (v.K3 >= -16)
- {
- v.K3 = v.K3 - 1;
- }
- break;
- case 6:
- if (v.K3 < 16)
- {
- v.K3 = v.K3 + 1;
- }
- break;
- case 7:
- if (v.K4 >= -16)
- {
- v.K4 = v.K4 - 1;
- }
- break;
- case 8:
- if (v.K4 < 16)
- {
- v.K4 = v.K4 + 1;
- }
- break;
- case 9:
- if (v.K5 >= -16)
- {
- v.K5 = v.K5 - 1;
- }
- break;
- case 10:
- if (v.K5 < 16)
- {
- v.K5 = v.K5 + 1;
- }
- break;
- }
- }
- return ((byte)Ch);
- }
- }
- }
|