Unpack20.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. /*
  2. * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
  3. * Original author: Edmund Wagner
  4. * Creation date: 21.06.2007
  5. *
  6. * the unrar licence applies to all junrar source and binary distributions
  7. * you are not allowed to use this source to re-create the RAR compression algorithm
  8. */
  9. using System;
  10. using SharpCompress.Compressors.Rar.UnpackV1.Decode;
  11. namespace SharpCompress.Compressors.Rar.UnpackV1
  12. {
  13. internal partial class Unpack
  14. {
  15. private readonly MultDecode[] MD = new MultDecode[4];
  16. private readonly byte[] UnpOldTable20 = new byte[PackDef.MC20 * 4];
  17. private int UnpAudioBlock, UnpChannels, UnpCurChannel, UnpChannelDelta;
  18. private readonly AudioVariables[] AudV = new AudioVariables[4];
  19. private readonly LitDecode LD = new LitDecode();
  20. private readonly DistDecode DD = new DistDecode();
  21. private readonly LowDistDecode LDD = new LowDistDecode();
  22. private readonly RepDecode RD = new RepDecode();
  23. private readonly BitDecode BD = new BitDecode();
  24. private static readonly int[] LDecode =
  25. {
  26. 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48,
  27. 56, 64, 80, 96, 112, 128, 160, 192, 224
  28. };
  29. private static readonly byte[] LBits =
  30. {
  31. 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
  32. 4, 5, 5, 5, 5
  33. };
  34. private static readonly int[] DDecode =
  35. {
  36. 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384,
  37. 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384,
  38. 24576, 32768, 49152, 65536, 98304, 131072, 196608, 262144, 327680,
  39. 393216, 458752, 524288, 589824, 655360, 720896, 786432, 851968,
  40. 917504, 983040
  41. };
  42. private static readonly int[] DBits =
  43. {
  44. 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10,
  45. 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16
  46. , 16, 16, 16, 16, 16, 16, 16
  47. };
  48. private static readonly int[] SDDecode = {0, 4, 8, 16, 32, 64, 128, 192};
  49. private static readonly int[] SDBits = {2, 2, 3, 4, 5, 6, 6, 6};
  50. private void unpack20(bool solid)
  51. {
  52. int Bits;
  53. if (suspended)
  54. {
  55. unpPtr = wrPtr;
  56. }
  57. else
  58. {
  59. UnpInitData(solid);
  60. if (!unpReadBuf())
  61. {
  62. return;
  63. }
  64. if (!solid)
  65. {
  66. if (!ReadTables20())
  67. {
  68. return;
  69. }
  70. }
  71. --destUnpSize;
  72. }
  73. while (destUnpSize >= 0)
  74. {
  75. unpPtr &= PackDef.MAXWINMASK;
  76. if (inAddr > readTop - 30)
  77. {
  78. if (!unpReadBuf())
  79. {
  80. break;
  81. }
  82. }
  83. if (((wrPtr - unpPtr) & PackDef.MAXWINMASK) < 270 && wrPtr != unpPtr)
  84. {
  85. oldUnpWriteBuf();
  86. if (suspended)
  87. {
  88. return;
  89. }
  90. }
  91. if (UnpAudioBlock != 0)
  92. {
  93. int AudioNumber = this.decodeNumber(MD[UnpCurChannel]);
  94. if (AudioNumber == 256)
  95. {
  96. if (!ReadTables20())
  97. {
  98. break;
  99. }
  100. continue;
  101. }
  102. window[unpPtr++] = DecodeAudio(AudioNumber);
  103. if (++UnpCurChannel == UnpChannels)
  104. {
  105. UnpCurChannel = 0;
  106. }
  107. --destUnpSize;
  108. continue;
  109. }
  110. int Number = this.decodeNumber(LD);
  111. if (Number < 256)
  112. {
  113. window[unpPtr++] = (byte)Number;
  114. --destUnpSize;
  115. continue;
  116. }
  117. if (Number > 269)
  118. {
  119. int Length = LDecode[Number -= 270] + 3;
  120. if ((Bits = LBits[Number]) > 0)
  121. {
  122. Length += Utility.URShift(GetBits(), (16 - Bits));
  123. AddBits(Bits);
  124. }
  125. int DistNumber = this.decodeNumber(DD);
  126. int Distance = DDecode[DistNumber] + 1;
  127. if ((Bits = DBits[DistNumber]) > 0)
  128. {
  129. Distance += Utility.URShift(GetBits(), (16 - Bits));
  130. AddBits(Bits);
  131. }
  132. if (Distance >= 0x2000)
  133. {
  134. Length++;
  135. if (Distance >= 0x40000L)
  136. {
  137. Length++;
  138. }
  139. }
  140. CopyString20(Length, Distance);
  141. continue;
  142. }
  143. if (Number == 269)
  144. {
  145. if (!ReadTables20())
  146. {
  147. break;
  148. }
  149. continue;
  150. }
  151. if (Number == 256)
  152. {
  153. CopyString20(lastLength, lastDist);
  154. continue;
  155. }
  156. if (Number < 261)
  157. {
  158. int Distance = oldDist[(oldDistPtr - (Number - 256)) & 3];
  159. int LengthNumber = this.decodeNumber(RD);
  160. int Length = LDecode[LengthNumber] + 2;
  161. if ((Bits = LBits[LengthNumber]) > 0)
  162. {
  163. Length += Utility.URShift(GetBits(), (16 - Bits));
  164. AddBits(Bits);
  165. }
  166. if (Distance >= 0x101)
  167. {
  168. Length++;
  169. if (Distance >= 0x2000)
  170. {
  171. Length++;
  172. if (Distance >= 0x40000)
  173. {
  174. Length++;
  175. }
  176. }
  177. }
  178. CopyString20(Length, Distance);
  179. continue;
  180. }
  181. if (Number < 270)
  182. {
  183. int Distance = SDDecode[Number -= 261] + 1;
  184. if ((Bits = SDBits[Number]) > 0)
  185. {
  186. Distance += Utility.URShift(GetBits(), (16 - Bits));
  187. AddBits(Bits);
  188. }
  189. CopyString20(2, Distance);
  190. }
  191. }
  192. ReadLastTables();
  193. oldUnpWriteBuf();
  194. }
  195. private void CopyString20(int Length, int Distance)
  196. {
  197. lastDist = oldDist[oldDistPtr++ & 3] = Distance;
  198. lastLength = Length;
  199. destUnpSize -= Length;
  200. int DestPtr = unpPtr - Distance;
  201. if (DestPtr < PackDef.MAXWINSIZE - 300 && unpPtr < PackDef.MAXWINSIZE - 300)
  202. {
  203. window[unpPtr++] = window[DestPtr++];
  204. window[unpPtr++] = window[DestPtr++];
  205. while (Length > 2)
  206. {
  207. Length--;
  208. window[unpPtr++] = window[DestPtr++];
  209. }
  210. }
  211. else
  212. {
  213. while ((Length--) != 0)
  214. {
  215. window[unpPtr] = window[DestPtr++ & PackDef.MAXWINMASK];
  216. unpPtr = (unpPtr + 1) & PackDef.MAXWINMASK;
  217. }
  218. }
  219. }
  220. private bool ReadTables20()
  221. {
  222. byte[] BitLength = new byte[PackDef.BC20];
  223. byte[] Table = new byte[PackDef.MC20 * 4];
  224. int TableSize, N, I;
  225. if (inAddr > readTop - 25)
  226. {
  227. if (!unpReadBuf())
  228. {
  229. return (false);
  230. }
  231. }
  232. int BitField = GetBits();
  233. UnpAudioBlock = (BitField & 0x8000);
  234. if (0 == (BitField & 0x4000))
  235. {
  236. // memset(UnpOldTable20,0,sizeof(UnpOldTable20));
  237. Utility.Fill(UnpOldTable20, (byte)0);
  238. }
  239. AddBits(2);
  240. if (UnpAudioBlock != 0)
  241. {
  242. UnpChannels = ((Utility.URShift(BitField, 12)) & 3) + 1;
  243. if (UnpCurChannel >= UnpChannels)
  244. {
  245. UnpCurChannel = 0;
  246. }
  247. AddBits(2);
  248. TableSize = PackDef.MC20 * UnpChannels;
  249. }
  250. else
  251. {
  252. TableSize = PackDef.NC20 + PackDef.DC20 + PackDef.RC20;
  253. }
  254. for (I = 0; I < PackDef.BC20; I++)
  255. {
  256. BitLength[I] = (byte)(Utility.URShift(GetBits(), 12));
  257. AddBits(4);
  258. }
  259. UnpackUtility.makeDecodeTables(BitLength, 0, BD, PackDef.BC20);
  260. I = 0;
  261. while (I < TableSize)
  262. {
  263. if (inAddr > readTop - 5)
  264. {
  265. if (!unpReadBuf())
  266. {
  267. return (false);
  268. }
  269. }
  270. int Number = this.decodeNumber(BD);
  271. if (Number < 16)
  272. {
  273. Table[I] = (byte)((Number + UnpOldTable20[I]) & 0xf);
  274. I++;
  275. }
  276. else if (Number == 16)
  277. {
  278. N = (Utility.URShift(GetBits(), 14)) + 3;
  279. AddBits(2);
  280. while (N-- > 0 && I < TableSize)
  281. {
  282. Table[I] = Table[I - 1];
  283. I++;
  284. }
  285. }
  286. else
  287. {
  288. if (Number == 17)
  289. {
  290. N = (Utility.URShift(GetBits(), 13)) + 3;
  291. AddBits(3);
  292. }
  293. else
  294. {
  295. N = (Utility.URShift(GetBits(), 9)) + 11;
  296. AddBits(7);
  297. }
  298. while (N-- > 0 && I < TableSize)
  299. {
  300. Table[I++] = 0;
  301. }
  302. }
  303. }
  304. if (inAddr > readTop)
  305. {
  306. return (true);
  307. }
  308. if (UnpAudioBlock != 0)
  309. {
  310. for (I = 0; I < UnpChannels; I++)
  311. {
  312. UnpackUtility.makeDecodeTables(Table, I * PackDef.MC20, MD[I], PackDef.MC20);
  313. }
  314. }
  315. else
  316. {
  317. UnpackUtility.makeDecodeTables(Table, 0, LD, PackDef.NC20);
  318. UnpackUtility.makeDecodeTables(Table, PackDef.NC20, DD, PackDef.DC20);
  319. UnpackUtility.makeDecodeTables(Table, PackDef.NC20 + PackDef.DC20, RD, PackDef.RC20);
  320. }
  321. // memcpy(UnpOldTable20,Table,sizeof(UnpOldTable20));
  322. for (int i = 0; i < UnpOldTable20.Length; i++)
  323. {
  324. UnpOldTable20[i] = Table[i];
  325. }
  326. return (true);
  327. }
  328. private void unpInitData20(bool Solid)
  329. {
  330. if (!Solid)
  331. {
  332. UnpChannelDelta = UnpCurChannel = 0;
  333. UnpChannels = 1;
  334. // memset(AudV,0,sizeof(AudV));
  335. AudV[0] = new AudioVariables();
  336. AudV[1] = new AudioVariables();
  337. AudV[2] = new AudioVariables();
  338. AudV[3] = new AudioVariables();
  339. // memset(UnpOldTable20,0,sizeof(UnpOldTable20));
  340. Utility.Fill(UnpOldTable20, (byte)0);
  341. }
  342. }
  343. private void ReadLastTables()
  344. {
  345. if (readTop >= inAddr + 5)
  346. {
  347. if (UnpAudioBlock != 0)
  348. {
  349. if (this.decodeNumber(MD[UnpCurChannel]) == 256)
  350. {
  351. ReadTables20();
  352. }
  353. }
  354. else
  355. {
  356. if (this.decodeNumber(LD) == 269)
  357. {
  358. ReadTables20();
  359. }
  360. }
  361. }
  362. }
  363. private byte DecodeAudio(int Delta)
  364. {
  365. AudioVariables v = AudV[UnpCurChannel];
  366. v.ByteCount = v.ByteCount + 1;
  367. v.D4 = v.D3;
  368. v.D3 = v.D2; // ->D3=V->D2;
  369. v.D2 = v.LastDelta - v.D1; // ->D2=V->LastDelta-V->D1;
  370. v.D1 = v.LastDelta; // V->D1=V->LastDelta;
  371. // int PCh=8*V->LastChar+V->K1*V->D1 +V->K2*V->D2 +V->K3*V->D3
  372. // +V->K4*V->D4+ V->K5*UnpChannelDelta;
  373. int PCh = 8 * v.LastChar + v.K1 * v.D1;
  374. PCh += v.K2 * v.D2 + v.K3 * v.D3;
  375. PCh += v.K4 * v.D4 + v.K5 * UnpChannelDelta;
  376. PCh = (Utility.URShift(PCh, 3)) & 0xFF;
  377. int Ch = PCh - Delta;
  378. int D = ((byte)Delta) << 3;
  379. v.Dif[0] += Math.Abs(D); // V->Dif[0]+=abs(D);
  380. v.Dif[1] += Math.Abs(D - v.D1); // V->Dif[1]+=abs(D-V->D1);
  381. v.Dif[2] += Math.Abs(D + v.D1); // V->Dif[2]+=abs(D+V->D1);
  382. v.Dif[3] += Math.Abs(D - v.D2); // V->Dif[3]+=abs(D-V->D2);
  383. v.Dif[4] += Math.Abs(D + v.D2); // V->Dif[4]+=abs(D+V->D2);
  384. v.Dif[5] += Math.Abs(D - v.D3); // V->Dif[5]+=abs(D-V->D3);
  385. v.Dif[6] += Math.Abs(D + v.D3); // V->Dif[6]+=abs(D+V->D3);
  386. v.Dif[7] += Math.Abs(D - v.D4); // V->Dif[7]+=abs(D-V->D4);
  387. v.Dif[8] += Math.Abs(D + v.D4); // V->Dif[8]+=abs(D+V->D4);
  388. v.Dif[9] += Math.Abs(D - UnpChannelDelta); // V->Dif[9]+=abs(D-UnpChannelDelta);
  389. v.Dif[10] += Math.Abs(D + UnpChannelDelta); // V->Dif[10]+=abs(D+UnpChannelDelta);
  390. v.LastDelta = (byte)(Ch - v.LastChar);
  391. UnpChannelDelta = v.LastDelta;
  392. v.LastChar = Ch; // V->LastChar=Ch;
  393. if ((v.ByteCount & 0x1F) == 0)
  394. {
  395. int MinDif = v.Dif[0], NumMinDif = 0;
  396. v.Dif[0] = 0; // ->Dif[0]=0;
  397. for (int I = 1; I < v.Dif.Length; I++)
  398. {
  399. if (v.Dif[I] < MinDif)
  400. {
  401. MinDif = v.Dif[I];
  402. NumMinDif = I;
  403. }
  404. v.Dif[I] = 0;
  405. }
  406. switch (NumMinDif)
  407. {
  408. case 1:
  409. if (v.K1 >= -16)
  410. {
  411. v.K1 = v.K1 - 1; // V->K1--;
  412. }
  413. break;
  414. case 2:
  415. if (v.K1 < 16)
  416. {
  417. v.K1 = v.K1 + 1; // V->K1++;
  418. }
  419. break;
  420. case 3:
  421. if (v.K2 >= -16)
  422. {
  423. v.K2 = v.K2 - 1; // V->K2--;
  424. }
  425. break;
  426. case 4:
  427. if (v.K2 < 16)
  428. {
  429. v.K2 = v.K2 + 1; // V->K2++;
  430. }
  431. break;
  432. case 5:
  433. if (v.K3 >= -16)
  434. {
  435. v.K3 = v.K3 - 1;
  436. }
  437. break;
  438. case 6:
  439. if (v.K3 < 16)
  440. {
  441. v.K3 = v.K3 + 1;
  442. }
  443. break;
  444. case 7:
  445. if (v.K4 >= -16)
  446. {
  447. v.K4 = v.K4 - 1;
  448. }
  449. break;
  450. case 8:
  451. if (v.K4 < 16)
  452. {
  453. v.K4 = v.K4 + 1;
  454. }
  455. break;
  456. case 9:
  457. if (v.K5 >= -16)
  458. {
  459. v.K5 = v.K5 - 1;
  460. }
  461. break;
  462. case 10:
  463. if (v.K5 < 16)
  464. {
  465. v.K5 = v.K5 + 1;
  466. }
  467. break;
  468. }
  469. }
  470. return ((byte)Ch);
  471. }
  472. }
  473. }