Unpack.unpack30_cpp.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800
  1. #if !Rar2017_64bit
  2. using nint = System.Int32;
  3. using nuint = System.UInt32;
  4. using size_t = System.UInt32;
  5. #else
  6. using nint = System.Int64;
  7. using nuint = System.UInt64;
  8. using size_t = System.UInt64;
  9. #endif
  10. using int64 = System.Int64;
  11. using System;
  12. using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef;
  13. using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal;
  14. //using static SharpCompress.Compressors.Rar.UnpackV2017.Unpack.Unpack30Local;
  15. /*
  16. namespace SharpCompress.Compressors.Rar.UnpackV2017
  17. {
  18. internal partial class Unpack
  19. {
  20. #if !RarV2017_RAR5ONLY
  21. // We use it instead of direct PPM.DecodeChar call to be sure that
  22. // we reset PPM structures in case of corrupt data. It is important,
  23. // because these structures can be invalid after PPM.DecodeChar returned -1.
  24. int SafePPMDecodeChar()
  25. {
  26. int Ch=PPM.DecodeChar();
  27. if (Ch==-1) // Corrupt PPM data found.
  28. {
  29. PPM.CleanUp(); // Reset possibly corrupt PPM data structures.
  30. UnpBlockType=BLOCK_LZ; // Set faster and more fail proof LZ mode.
  31. }
  32. return(Ch);
  33. }
  34. internal static class Unpack30Local {
  35. public static readonly byte[] 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};
  36. public 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};
  37. public static readonly int[] DDecode = new int[DC];
  38. public static readonly byte[] DBits = new byte[DC];
  39. public static readonly int[] DBitLengthCounts= {4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,14,0,12};
  40. public static readonly byte[] SDDecode={0,4,8,16,32,64,128,192};
  41. public static readonly byte[] SDBits= {2,2,3, 4, 5, 6, 6, 6};
  42. }
  43. void Unpack29(bool Solid)
  44. {
  45. uint Bits;
  46. if (DDecode[1]==0)
  47. {
  48. int Dist=0,BitLength=0,Slot=0;
  49. for (int I=0;I<DBitLengthCounts.Length;I++,BitLength++)
  50. for (int J=0;J<DBitLengthCounts[I];J++,Slot++,Dist+=(1<<BitLength))
  51. {
  52. DDecode[Slot]=Dist;
  53. DBits[Slot]=(byte)BitLength;
  54. }
  55. }
  56. FileExtracted=true;
  57. if (!Suspended)
  58. {
  59. UnpInitData(Solid);
  60. if (!UnpReadBuf30())
  61. return;
  62. if ((!Solid || !TablesRead3) && !ReadTables30())
  63. return;
  64. }
  65. while (true)
  66. {
  67. UnpPtr&=MaxWinMask;
  68. if (Inp.InAddr>ReadBorder)
  69. {
  70. if (!UnpReadBuf30())
  71. break;
  72. }
  73. if (((WrPtr-UnpPtr) & MaxWinMask)<260 && WrPtr!=UnpPtr)
  74. {
  75. UnpWriteBuf30();
  76. if (WrittenFileSize>DestUnpSize)
  77. return;
  78. if (Suspended)
  79. {
  80. FileExtracted=false;
  81. return;
  82. }
  83. }
  84. if (UnpBlockType==BLOCK_PPM)
  85. {
  86. // Here speed is critical, so we do not use SafePPMDecodeChar,
  87. // because sometimes even the inline function can introduce
  88. // some additional penalty.
  89. int Ch=PPM.DecodeChar();
  90. if (Ch==-1) // Corrupt PPM data found.
  91. {
  92. PPM.CleanUp(); // Reset possibly corrupt PPM data structures.
  93. UnpBlockType=BLOCK_LZ; // Set faster and more fail proof LZ mode.
  94. break;
  95. }
  96. if (Ch==PPMEscChar)
  97. {
  98. int NextCh=SafePPMDecodeChar();
  99. if (NextCh==0) // End of PPM encoding.
  100. {
  101. if (!ReadTables30())
  102. break;
  103. continue;
  104. }
  105. if (NextCh==-1) // Corrupt PPM data found.
  106. break;
  107. if (NextCh==2) // End of file in PPM mode.
  108. break;
  109. if (NextCh==3) // Read VM code.
  110. {
  111. if (!ReadVMCodePPM())
  112. break;
  113. continue;
  114. }
  115. if (NextCh==4) // LZ inside of PPM.
  116. {
  117. uint Distance=0,Length;
  118. bool Failed=false;
  119. for (int I=0;I<4 && !Failed;I++)
  120. {
  121. int _Ch=SafePPMDecodeChar();
  122. if (_Ch==-1)
  123. Failed=true;
  124. else
  125. if (I==3)
  126. Length=(byte)_Ch;
  127. else
  128. Distance=(Distance<<8)+(byte)_Ch;
  129. }
  130. if (Failed)
  131. break;
  132. CopyString(Length+32,Distance+2);
  133. continue;
  134. }
  135. if (NextCh==5) // One byte distance match (RLE) inside of PPM.
  136. {
  137. int Length=SafePPMDecodeChar();
  138. if (Length==-1)
  139. break;
  140. CopyString((uint)(Length+4),1);
  141. continue;
  142. }
  143. // If we are here, NextCh must be 1, what means that current byte
  144. // is equal to our 'escape' byte, so we just store it to Window.
  145. }
  146. Window[UnpPtr++]=(byte)Ch;
  147. continue;
  148. }
  149. uint Number=DecodeNumber(Inp,BlockTables.LD);
  150. if (Number<256)
  151. {
  152. Window[UnpPtr++]=(byte)Number;
  153. continue;
  154. }
  155. if (Number>=271)
  156. {
  157. uint Length=(uint)(LDecode[Number-=271]+3);
  158. if ((Bits=LBits[Number])>0)
  159. {
  160. Length+=Inp.getbits()>>(int)(16-Bits);
  161. Inp.addbits(Bits);
  162. }
  163. uint DistNumber=DecodeNumber(Inp,BlockTables.DD);
  164. uint Distance=(uint)(DDecode[DistNumber]+1);
  165. if ((Bits=DBits[DistNumber])>0)
  166. {
  167. if (DistNumber>9)
  168. {
  169. if (Bits>4)
  170. {
  171. Distance+=((Inp.getbits()>>(int)(20-Bits))<<4);
  172. Inp.addbits(Bits-4);
  173. }
  174. if (LowDistRepCount>0)
  175. {
  176. LowDistRepCount--;
  177. Distance+=(uint)PrevLowDist;
  178. }
  179. else
  180. {
  181. uint LowDist=DecodeNumber(Inp,BlockTables.LDD);
  182. if (LowDist==16)
  183. {
  184. LowDistRepCount=(int)(LOW_DIST_REP_COUNT-1);
  185. Distance+=(uint)PrevLowDist;
  186. }
  187. else
  188. {
  189. Distance+=LowDist;
  190. PrevLowDist=(int)LowDist;
  191. }
  192. }
  193. }
  194. else
  195. {
  196. Distance+=Inp.getbits()>>(int)(16-Bits);
  197. Inp.addbits(Bits);
  198. }
  199. }
  200. if (Distance>=0x2000)
  201. {
  202. Length++;
  203. if (Distance>=0x40000)
  204. Length++;
  205. }
  206. InsertOldDist(Distance);
  207. LastLength=Length;
  208. CopyString(Length,Distance);
  209. continue;
  210. }
  211. if (Number==256)
  212. {
  213. if (!ReadEndOfBlock())
  214. break;
  215. continue;
  216. }
  217. if (Number==257)
  218. {
  219. if (!ReadVMCode())
  220. break;
  221. continue;
  222. }
  223. if (Number==258)
  224. {
  225. if (LastLength!=0)
  226. CopyString(LastLength,OldDist[0]);
  227. continue;
  228. }
  229. if (Number<263)
  230. {
  231. uint DistNum=Number-259;
  232. uint Distance=OldDist[DistNum];
  233. for (uint I=DistNum;I>0;I--)
  234. OldDist[I]=OldDist[I-1];
  235. OldDist[0]=Distance;
  236. uint LengthNumber=DecodeNumber(Inp,BlockTables.RD);
  237. int Length=LDecode[LengthNumber]+2;
  238. if ((Bits=LBits[LengthNumber])>0)
  239. {
  240. Length+=(int)(Inp.getbits()>>(int)(16-Bits));
  241. Inp.addbits(Bits);
  242. }
  243. LastLength=(uint)Length;
  244. CopyString((uint)Length,Distance);
  245. continue;
  246. }
  247. if (Number<272)
  248. {
  249. uint Distance=(uint)(SDDecode[Number-=263]+1);
  250. if ((Bits=SDBits[Number])>0)
  251. {
  252. Distance+=Inp.getbits()>>(int)(16-Bits);
  253. Inp.addbits(Bits);
  254. }
  255. InsertOldDist(Distance);
  256. LastLength=2;
  257. CopyString(2,Distance);
  258. continue;
  259. }
  260. }
  261. UnpWriteBuf30();
  262. }
  263. // Return 'false' to quit unpacking the current file or 'true' to continue.
  264. bool ReadEndOfBlock()
  265. {
  266. uint BitField=Inp.getbits();
  267. bool NewTable,NewFile=false;
  268. // "1" - no new file, new table just here.
  269. // "00" - new file, no new table.
  270. // "01" - new file, new table (in beginning of next file).
  271. if ((BitField & 0x8000)!=0)
  272. {
  273. NewTable=true;
  274. Inp.addbits(1);
  275. }
  276. else
  277. {
  278. NewFile=true;
  279. NewTable=(BitField & 0x4000)!=0;
  280. Inp.addbits(2);
  281. }
  282. TablesRead3=!NewTable;
  283. // Quit immediately if "new file" flag is set. If "new table" flag
  284. // is present, we'll read the table in beginning of next file
  285. // based on 'TablesRead3' 'false' value.
  286. if (NewFile)
  287. return false;
  288. return ReadTables30(); // Quit only if we failed to read tables.
  289. }
  290. bool ReadVMCode()
  291. {
  292. // Entire VM code is guaranteed to fully present in block defined
  293. // by current Huffman table. Compressor checks that VM code does not cross
  294. // Huffman block boundaries.
  295. uint FirstByte=Inp.getbits()>>8;
  296. Inp.addbits(8);
  297. uint Length=(FirstByte & 7)+1;
  298. if (Length==7)
  299. {
  300. Length=(Inp.getbits()>>8)+7;
  301. Inp.addbits(8);
  302. }
  303. else
  304. if (Length==8)
  305. {
  306. Length=Inp.getbits();
  307. Inp.addbits(16);
  308. }
  309. if (Length==0)
  310. return false;
  311. Array<byte> VMCode(Length);
  312. for (uint I=0;I<Length;I++)
  313. {
  314. // Try to read the new buffer if only one byte is left.
  315. // But if we read all bytes except the last, one byte is enough.
  316. if (Inp.InAddr>=ReadTop-1 && !UnpReadBuf30() && I<Length-1)
  317. return false;
  318. VMCode[I]=Inp.getbits()>>8;
  319. Inp.addbits(8);
  320. }
  321. return AddVMCode(FirstByte,&VMCode[0],Length);
  322. }
  323. bool ReadVMCodePPM()
  324. {
  325. uint FirstByte=(uint)SafePPMDecodeChar();
  326. if ((int)FirstByte==-1)
  327. return false;
  328. uint Length=(FirstByte & 7)+1;
  329. if (Length==7)
  330. {
  331. int B1=SafePPMDecodeChar();
  332. if (B1==-1)
  333. return false;
  334. Length=B1+7;
  335. }
  336. else
  337. if (Length==8)
  338. {
  339. int B1=SafePPMDecodeChar();
  340. if (B1==-1)
  341. return false;
  342. int B2=SafePPMDecodeChar();
  343. if (B2==-1)
  344. return false;
  345. Length=B1*256+B2;
  346. }
  347. if (Length==0)
  348. return false;
  349. Array<byte> VMCode(Length);
  350. for (uint I=0;I<Length;I++)
  351. {
  352. int Ch=SafePPMDecodeChar();
  353. if (Ch==-1)
  354. return false;
  355. VMCode[I]=Ch;
  356. }
  357. return AddVMCode(FirstByte,&VMCode[0],Length);
  358. }
  359. bool AddVMCode(uint FirstByte,byte[] Code,int CodeSize)
  360. {
  361. VMCodeInp.InitBitInput();
  362. //x memcpy(VMCodeInp.InBuf,Code,Min(BitInput.MAX_SIZE,CodeSize));
  363. Array.Copy(Code, 0, VMCodeInp.InBuf, 0, Math.Min(BitInput.MAX_SIZE,CodeSize));
  364. VM.Init();
  365. uint FiltPos;
  366. if ((FirstByte & 0x80)!=0)
  367. {
  368. FiltPos=RarVM.ReadData(VMCodeInp);
  369. if (FiltPos==0)
  370. InitFilters30(false);
  371. else
  372. FiltPos--;
  373. }
  374. else
  375. FiltPos=(uint)this.LastFilter; // Use the same filter as last time.
  376. if (FiltPos>Filters30.Count || FiltPos>OldFilterLengths.Count)
  377. return false;
  378. LastFilter=(int)FiltPos;
  379. bool NewFilter=(FiltPos==Filters30.Count);
  380. UnpackFilter30 StackFilter=new UnpackFilter30(); // New filter for PrgStack.
  381. UnpackFilter30 Filter;
  382. if (NewFilter) // New filter code, never used before since VM reset.
  383. {
  384. if (FiltPos>MAX3_UNPACK_FILTERS)
  385. {
  386. // Too many different filters, corrupt archive.
  387. //delete StackFilter;
  388. return false;
  389. }
  390. Filters30.Add(1);
  391. Filters30[Filters30.Count-1]=Filter=new UnpackFilter30();
  392. StackFilter.ParentFilter=(uint)(Filters30.Count-1);
  393. // Reserve one item to store the data block length of our new filter
  394. // entry. We'll set it to real block length below, after reading it.
  395. // But we need to initialize it now, because when processing corrupt
  396. // data, we can access this item even before we set it to real value.
  397. OldFilterLengths.Add(0);
  398. }
  399. else // Filter was used in the past.
  400. {
  401. Filter=Filters30[(int)FiltPos];
  402. StackFilter.ParentFilter=FiltPos;
  403. }
  404. int EmptyCount=0;
  405. for (int I=0;I<PrgStack.Count;I++)
  406. {
  407. PrgStack[I-EmptyCount]=PrgStack[I];
  408. if (PrgStack[I]==null)
  409. EmptyCount++;
  410. if (EmptyCount>0)
  411. PrgStack[I]=null;
  412. }
  413. if (EmptyCount==0)
  414. {
  415. if (PrgStack.Count>MAX3_UNPACK_FILTERS)
  416. {
  417. //delete StackFilter;
  418. return false;
  419. }
  420. PrgStack.Add(1);
  421. EmptyCount=1;
  422. }
  423. size_t StackPos=(uint)(this.PrgStack.Count-EmptyCount);
  424. PrgStack[(int)StackPos]=StackFilter;
  425. uint BlockStart=RarVM.ReadData(VMCodeInp);
  426. if ((FirstByte & 0x40)!=0)
  427. BlockStart+=258;
  428. StackFilter.BlockStart=(uint)((BlockStart+UnpPtr)&MaxWinMask);
  429. if ((FirstByte & 0x20)!=0)
  430. {
  431. StackFilter.BlockLength=RarVM.ReadData(VMCodeInp);
  432. // Store the last data block length for current filter.
  433. OldFilterLengths[(int)FiltPos]=(int)StackFilter.BlockLength;
  434. }
  435. else
  436. {
  437. // Set the data block size to same value as the previous block size
  438. // for same filter. It is possible for corrupt data to access a new
  439. // and not filled yet item of OldFilterLengths array here. This is why
  440. // we set new OldFilterLengths items to zero above.
  441. StackFilter.BlockLength=FiltPos<OldFilterLengths.Count ? OldFilterLengths[(int)FiltPos]:0;
  442. }
  443. StackFilter.NextWindow=WrPtr!=UnpPtr && ((WrPtr-UnpPtr)&MaxWinMask)<=BlockStart;
  444. // DebugLog("\nNextWindow: UnpPtr=%08x WrPtr=%08x BlockStart=%08x",UnpPtr,WrPtr,BlockStart);
  445. memset(StackFilter.Prg.InitR,0,sizeof(StackFilter.Prg.InitR));
  446. StackFilter.Prg.InitR[4]=StackFilter.BlockLength;
  447. if ((FirstByte & 0x10)!=0) // Set registers to optional parameters if any.
  448. {
  449. uint InitMask=VMCodeInp.fgetbits()>>9;
  450. VMCodeInp.faddbits(7);
  451. for (int I=0;I<7;I++)
  452. if ((InitMask & (1<<I)) != 0)
  453. StackFilter.Prg.InitR[I]=RarVM.ReadData(VMCodeInp);
  454. }
  455. if (NewFilter)
  456. {
  457. uint VMCodeSize=RarVM.ReadData(VMCodeInp);
  458. if (VMCodeSize>=0x10000 || VMCodeSize==0)
  459. return false;
  460. Array<byte> VMCode(VMCodeSize);
  461. for (uint I=0;I<VMCodeSize;I++)
  462. {
  463. if (VMCodeInp.Overflow(3))
  464. return false;
  465. VMCode[I]=VMCodeInp.fgetbits()>>8;
  466. VMCodeInp.faddbits(8);
  467. }
  468. VM.Prepare(&VMCode[0],VMCodeSize,&Filter->Prg);
  469. }
  470. StackFilter.Prg.Type=Filter.Prg.Type;
  471. return true;
  472. }
  473. bool UnpReadBuf30()
  474. {
  475. int DataSize=ReadTop-Inp.InAddr; // Data left to process.
  476. if (DataSize<0)
  477. return false;
  478. if (Inp.InAddr>BitInput.MAX_SIZE/2)
  479. {
  480. // If we already processed more than half of buffer, let's move
  481. // remaining data into beginning to free more space for new data
  482. // and ensure that calling function does not cross the buffer border
  483. // even if we did not read anything here. Also it ensures that read size
  484. // is not less than CRYPT_BLOCK_SIZE, so we can align it without risk
  485. // to make it zero.
  486. if (DataSize>0)
  487. //x memmove(Inp.InBuf,Inp.InBuf+Inp.InAddr,DataSize);
  488. Array.Copy(Inp.InBuf,Inp.InAddr,Inp.InBuf,0,DataSize);
  489. Inp.InAddr=0;
  490. ReadTop=DataSize;
  491. }
  492. else
  493. DataSize=ReadTop;
  494. int ReadCode=UnpIO_UnpRead(Inp.InBuf,DataSize,BitInput.MAX_SIZE-DataSize);
  495. if (ReadCode>0)
  496. ReadTop+=ReadCode;
  497. ReadBorder=ReadTop-30;
  498. return ReadCode!=-1;
  499. }
  500. void UnpWriteBuf30()
  501. {
  502. uint WrittenBorder=(uint)WrPtr;
  503. uint WriteSize=(uint)((UnpPtr-WrittenBorder)&MaxWinMask);
  504. for (int I=0;I<PrgStack.Count;I++)
  505. {
  506. // Here we apply filters to data which we need to write.
  507. // We always copy data to virtual machine memory before processing.
  508. // We cannot process them just in place in Window buffer, because
  509. // these data can be used for future string matches, so we must
  510. // preserve them in original form.
  511. UnpackFilter30 flt=PrgStack[I];
  512. if (flt==null)
  513. continue;
  514. if (flt.NextWindow)
  515. {
  516. flt.NextWindow=false;
  517. continue;
  518. }
  519. uint BlockStart=flt.BlockStart;
  520. uint BlockLength=flt.BlockLength;
  521. if (((BlockStart-WrittenBorder)&MaxWinMask)<WriteSize)
  522. {
  523. if (WrittenBorder!=BlockStart)
  524. {
  525. UnpWriteArea(WrittenBorder,BlockStart);
  526. WrittenBorder=BlockStart;
  527. WriteSize=(uint)((UnpPtr-WrittenBorder)&MaxWinMask);
  528. }
  529. if (BlockLength<=WriteSize)
  530. {
  531. uint BlockEnd=(BlockStart+BlockLength)&MaxWinMask;
  532. if (BlockStart<BlockEnd || BlockEnd==0)
  533. VM.SetMemory(0,Window+BlockStart,BlockLength);
  534. else
  535. {
  536. uint FirstPartLength=uint(MaxWinSize-BlockStart);
  537. VM.SetMemory(0,Window+BlockStart,FirstPartLength);
  538. VM.SetMemory(FirstPartLength,Window,BlockEnd);
  539. }
  540. VM_PreparedProgram *ParentPrg=&Filters30[flt->ParentFilter]->Prg;
  541. VM_PreparedProgram *Prg=&flt->Prg;
  542. ExecuteCode(Prg);
  543. byte[] FilteredData=Prg.FilteredData;
  544. uint FilteredDataSize=Prg.FilteredDataSize;
  545. delete PrgStack[I];
  546. PrgStack[I]=null;
  547. while (I+1<PrgStack.Count)
  548. {
  549. UnpackFilter30 NextFilter=PrgStack[I+1];
  550. // It is required to check NextWindow here.
  551. if (NextFilter==null || NextFilter.BlockStart!=BlockStart ||
  552. NextFilter.BlockLength!=FilteredDataSize || NextFilter.NextWindow)
  553. break;
  554. // Apply several filters to same data block.
  555. VM.SetMemory(0,FilteredData,FilteredDataSize);
  556. VM_PreparedProgram *ParentPrg=&Filters30[NextFilter.ParentFilter]->Prg;
  557. VM_PreparedProgram *NextPrg=&NextFilter->Prg;
  558. ExecuteCode(NextPrg);
  559. FilteredData=NextPrg.FilteredData;
  560. FilteredDataSize=NextPrg.FilteredDataSize;
  561. I++;
  562. delete PrgStack[I];
  563. PrgStack[I]=null;
  564. }
  565. UnpIO_UnpWrite(FilteredData,0,FilteredDataSize);
  566. UnpSomeRead=true;
  567. WrittenFileSize+=FilteredDataSize;
  568. WrittenBorder=BlockEnd;
  569. WriteSize=(uint)((UnpPtr-WrittenBorder)&MaxWinMask);
  570. }
  571. else
  572. {
  573. // Current filter intersects the window write border, so we adjust
  574. // the window border to process this filter next time, not now.
  575. for (size_t J=I;J<PrgStack.Count;J++)
  576. {
  577. UnpackFilter30 flt=PrgStack[J];
  578. if (flt!=null && flt.NextWindow)
  579. flt.NextWindow=false;
  580. }
  581. WrPtr=WrittenBorder;
  582. return;
  583. }
  584. }
  585. }
  586. UnpWriteArea(WrittenBorder,UnpPtr);
  587. WrPtr=UnpPtr;
  588. }
  589. void ExecuteCode(VM_PreparedProgram *Prg)
  590. {
  591. Prg->InitR[6]=(uint)WrittenFileSize;
  592. VM.Execute(Prg);
  593. }
  594. bool ReadTables30()
  595. {
  596. byte[] BitLength = new byte[BC];
  597. byte[] Table = new byte[HUFF_TABLE_SIZE30];
  598. if (Inp.InAddr>ReadTop-25)
  599. if (!UnpReadBuf30())
  600. return(false);
  601. Inp.faddbits((uint)((8-Inp.InBit)&7));
  602. uint BitField=Inp.fgetbits();
  603. if ((BitField & 0x8000) != 0)
  604. {
  605. UnpBlockType=BLOCK_PPM;
  606. return(PPM.DecodeInit(this,PPMEscChar));
  607. }
  608. UnpBlockType=BLOCK_LZ;
  609. PrevLowDist=0;
  610. LowDistRepCount=0;
  611. if ((BitField & 0x4000) == 0)
  612. Utility.Memset(UnpOldTable,0,UnpOldTable.Length);
  613. Inp.faddbits(2);
  614. for (uint I=0;I<BC;I++)
  615. {
  616. uint Length=(byte)(Inp.fgetbits() >> 12);
  617. Inp.faddbits(4);
  618. if (Length==15)
  619. {
  620. uint ZeroCount=(byte)(Inp.fgetbits() >> 12);
  621. Inp.faddbits(4);
  622. if (ZeroCount==0)
  623. BitLength[I]=15;
  624. else
  625. {
  626. ZeroCount+=2;
  627. while (ZeroCount-- > 0 && I<BitLength.Length)
  628. BitLength[I++]=0;
  629. I--;
  630. }
  631. }
  632. else
  633. BitLength[I]=(byte)Length;
  634. }
  635. MakeDecodeTables(BitLength,0,BlockTables.BD,BC30);
  636. const uint TableSize=HUFF_TABLE_SIZE30;
  637. for (uint I=0;I<TableSize;)
  638. {
  639. if (Inp.InAddr>ReadTop-5)
  640. if (!UnpReadBuf30())
  641. return(false);
  642. uint Number=DecodeNumber(Inp,BlockTables.BD);
  643. if (Number<16)
  644. {
  645. Table[I]=(byte)((Number+this.UnpOldTable[I]) & 0xf);
  646. I++;
  647. }
  648. else
  649. if (Number<18)
  650. {
  651. uint N;
  652. if (Number==16)
  653. {
  654. N=(Inp.fgetbits() >> 13)+3;
  655. Inp.faddbits(3);
  656. }
  657. else
  658. {
  659. N=(Inp.fgetbits() >> 9)+11;
  660. Inp.faddbits(7);
  661. }
  662. if (I==0)
  663. return false; // We cannot have "repeat previous" code at the first position.
  664. else
  665. while (N-- > 0 && I<TableSize)
  666. {
  667. Table[I]=Table[I-1];
  668. I++;
  669. }
  670. }
  671. else
  672. {
  673. uint N;
  674. if (Number==18)
  675. {
  676. N=(Inp.fgetbits() >> 13)+3;
  677. Inp.faddbits(3);
  678. }
  679. else
  680. {
  681. N=(Inp.fgetbits() >> 9)+11;
  682. Inp.faddbits(7);
  683. }
  684. while (N-- > 0 && I<TableSize)
  685. Table[I++]=0;
  686. }
  687. }
  688. TablesRead3=true;
  689. if (Inp.InAddr>ReadTop)
  690. return false;
  691. MakeDecodeTables(Table,0,BlockTables.LD,NC30);
  692. MakeDecodeTables(Table,(int)NC30,BlockTables.DD,DC30);
  693. MakeDecodeTables(Table,(int)(NC30+DC30),BlockTables.LDD,LDC30);
  694. MakeDecodeTables(Table,(int)(NC30+DC30+LDC30),BlockTables.RD,RC30);
  695. //x memcpy(UnpOldTable,Table,sizeof(UnpOldTable));
  696. Array.Copy(Table,0,UnpOldTable,0,UnpOldTable.Length);
  697. return true;
  698. }
  699. #endif
  700. void UnpInitData30(bool Solid)
  701. {
  702. if (!Solid)
  703. {
  704. TablesRead3=false;
  705. Utility.Memset(UnpOldTable, 0, UnpOldTable.Length);
  706. PPMEscChar=2;
  707. UnpBlockType=BLOCK_LZ;
  708. }
  709. InitFilters30(Solid);
  710. }
  711. void InitFilters30(bool Solid)
  712. {
  713. if (!Solid)
  714. {
  715. //OldFilterLengths.SoftReset();
  716. OldFilterLengths.Clear();
  717. LastFilter=0;
  718. //for (size_t I=0;I<Filters30.Count;I++)
  719. // delete Filters30[I];
  720. //Filters30.SoftReset();
  721. Filters30.Clear();
  722. }
  723. //for (size_t I=0;I<PrgStack.Count;I++)
  724. // delete PrgStack[I];
  725. //PrgStack.SoftReset();
  726. PrgStack.Clear();
  727. }
  728. }
  729. }
  730. */