1
0

StoneCrackerDecompressor.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. /* Copyright (C) Teemu Suutari */
  2. #include "StoneCrackerDecompressor.hpp"
  3. #include "InputStream.hpp"
  4. #include "OutputStream.hpp"
  5. #include "HuffmanDecoder.hpp"
  6. #include "common/Common.hpp"
  7. namespace ancient::internal
  8. {
  9. bool StoneCrackerDecompressor::detectHeaderAndGeneration(uint32_t hdr,uint32_t &generation) noexcept
  10. {
  11. // Stonecracker 2.71 (and others from 2.69 - 2.8 series) do not have any sensible identification value
  12. // first 3 bytes are constants for RLE-encoder (byte values for RLE-encoder, at least they are unique)
  13. // last byte is bit length.
  14. //
  15. // 2.92 and 2.99 do not have either any proper identification word either, however its
  16. // bit lengts for decompressor are stored in the first 4 bytes, which forms identifiable
  17. // value.
  18. //
  19. // Thus for detecting 2.71 and friends, we are creating lots of false positives here.
  20. // At least we can rule those out later when detecting the actual header content
  21. // Final complication is that values for 2.71/2.9X overlap, this we need to handle
  22. // later as well
  23. if (hdr>=0x08090a08U&&hdr<=0x08090a0eU&&hdr!=0x08090a09U)
  24. {
  25. // can be generation 1 as well. needs to be determined later
  26. generation=2;
  27. return true;
  28. }
  29. if ((hdr&0xffU)>=0x08U&&(hdr&0xffU)<=0x0eU)
  30. {
  31. uint8_t byte0=hdr>>24U;
  32. uint8_t byte1=hdr>>16U;
  33. uint8_t byte2=hdr>>8U;
  34. // only limiter I can think of apart from the last byte is that the rle-bytes are unique
  35. if (byte0!=byte1 && byte0!=byte2 && byte1!=byte2)
  36. {
  37. generation=1;
  38. return true;
  39. }
  40. }
  41. // From 3.00 and onwards we can be certain of the format
  42. switch (hdr)
  43. {
  44. case FourCC("S300"):
  45. generation=3;
  46. return true;
  47. case FourCC("S310"):
  48. generation=4;
  49. return true;
  50. case FourCC("S400"):
  51. generation=5;
  52. return true;
  53. case FourCC("S401"):
  54. generation=6;
  55. return true;
  56. case FourCC("S403"):
  57. generation=7;
  58. return true;
  59. case FourCC("S404"):
  60. generation=8;
  61. return true;
  62. default:
  63. return false;
  64. }
  65. }
  66. bool StoneCrackerDecompressor::detectHeader(uint32_t hdr) noexcept
  67. {
  68. uint32_t dummy;
  69. return detectHeaderAndGeneration(hdr,dummy);
  70. }
  71. std::shared_ptr<Decompressor> StoneCrackerDecompressor::create(const Buffer &packedData,bool exactSizeKnown,bool verify)
  72. {
  73. return std::make_shared<StoneCrackerDecompressor>(packedData,exactSizeKnown,verify);
  74. }
  75. void StoneCrackerDecompressor::initialize(const Buffer &packedData,uint32_t hdr)
  76. {
  77. auto readModes=[&](uint32_t value)
  78. {
  79. for (uint32_t i=0;i<4U;i++)
  80. {
  81. _modes[i]=value>>24U;
  82. if (_modes[i]<8U || _modes[i]>14U)
  83. throw InvalidFormatError();
  84. value<<=8U;
  85. }
  86. };
  87. switch (_generation)
  88. {
  89. case 1:
  90. _dataOffset=18U;
  91. _rle[0]=hdr>>24U;
  92. _rle[1]=hdr>>16U;
  93. _rle[2]=hdr>>8U;
  94. _modes[0]=hdr;
  95. if (packedData.size()<_dataOffset) throw InvalidFormatError();
  96. for (uint32_t i=1;i<3U;i++)
  97. {
  98. _modes[i]=packedData.read8(i+15U);
  99. if (_modes[i]<4U || _modes[i]>7U)
  100. throw InvalidFormatError();
  101. }
  102. _rleSize=packedData.readBE32(4U);
  103. _rawSize=packedData.readBE32(8U);
  104. _packedSize=packedData.readBE32(12U);
  105. break;
  106. case 2:
  107. readModes(hdr);
  108. case 4:
  109. case 5:
  110. case 6:
  111. _dataOffset=12U;
  112. if (packedData.size()<_dataOffset) throw InvalidFormatError();
  113. _rawSize=packedData.readBE32(4U);
  114. _packedSize=packedData.readBE32(8U);
  115. break;
  116. case 3:
  117. _dataOffset=16U;
  118. if (packedData.size()<_dataOffset) throw InvalidFormatError();
  119. readModes(packedData.readBE32(4));
  120. _rawSize=packedData.readBE32(8U);
  121. _packedSize=packedData.readBE32(12U);
  122. break;
  123. case 7:
  124. case 8:
  125. _dataOffset=16U;
  126. if (packedData.size()<_dataOffset+2U) throw InvalidFormatError();
  127. _rawSize=packedData.readBE32(8U);
  128. _packedSize=packedData.readBE32(12U)+2U;
  129. break;
  130. default:
  131. throw InvalidFormatError();
  132. break;
  133. }
  134. if (_packedSize>getMaxPackedSize() || _rawSize>getMaxRawSize())
  135. throw InvalidFormatError();
  136. // Final sanity checks on old formats, especially on 2.71 which can still be false positive
  137. // For a sanity check we assume the compressor is actually compressing, which is not a exactly wrong thing to do
  138. // (of course there could be expanding files, but it is doubtful someone would actually used them)
  139. // Also, the compressor seem to crash on large files. Lets cap the filesize to 1M
  140. if (_generation==1 && (_rleSize>_rawSize || _packedSize>_rleSize || _rawSize>1048'576U))
  141. throw InvalidFormatError();
  142. _packedSize+=_dataOffset;
  143. if (_packedSize>packedData.size())
  144. throw InvalidFormatError();
  145. }
  146. StoneCrackerDecompressor::StoneCrackerDecompressor(const Buffer &packedData,bool exactSizeKnown,bool verify) :
  147. _packedData(packedData)
  148. {
  149. uint32_t hdr=packedData.readBE32(0);
  150. if (!detectHeaderAndGeneration(hdr,_generation)) throw InvalidFormatError();
  151. bool initialized=false;
  152. // this is the fallback if we have accidentally identified the wrong version
  153. if (_generation==2)
  154. {
  155. try
  156. {
  157. initialize(packedData,hdr);
  158. initialized=true;
  159. } catch (const Error &) {
  160. _generation=1;
  161. }
  162. }
  163. if (!initialized) initialize(packedData,hdr);
  164. }
  165. StoneCrackerDecompressor::~StoneCrackerDecompressor()
  166. {
  167. // nothing needed
  168. }
  169. const std::string &StoneCrackerDecompressor::getName() const noexcept
  170. {
  171. switch (_generation)
  172. {
  173. case 1:
  174. {
  175. static std::string name="SC: StoneCracker v2.69 - v2.81";
  176. return name;
  177. }
  178. case 2:
  179. {
  180. static std::string name="SC: StoneCracker v2.92, v2.99";
  181. return name;
  182. }
  183. case 3:
  184. {
  185. static std::string name="S300: StoneCracker v3.00";
  186. return name;
  187. }
  188. case 4:
  189. {
  190. static std::string name="S310: StoneCracker v3.10, v3.11b";
  191. return name;
  192. }
  193. case 5:
  194. {
  195. static std::string name="S400: StoneCracker pre v4.00";
  196. return name;
  197. }
  198. case 6:
  199. {
  200. static std::string name="S401: StoneCracker v4.01";
  201. return name;
  202. }
  203. case 7:
  204. {
  205. static std::string name="S403: StoneCracker v4.02a";
  206. return name;
  207. }
  208. case 8:
  209. {
  210. static std::string name="S404: StoneCracker v4.10";
  211. return name;
  212. }
  213. }
  214. static std::string dummy="";
  215. return dummy;
  216. }
  217. size_t StoneCrackerDecompressor::getPackedSize() const noexcept
  218. {
  219. return _packedSize;
  220. }
  221. size_t StoneCrackerDecompressor::getRawSize() const noexcept
  222. {
  223. return _rawSize;
  224. }
  225. // v2.71
  226. void StoneCrackerDecompressor::decompressGen1(Buffer &rawData)
  227. {
  228. BackwardInputStream inputStream(_packedData,_dataOffset,_packedSize);
  229. MSBBitReader<BackwardInputStream> bitReader(inputStream);
  230. MemoryBuffer tmpBuffer(_rleSize);
  231. BackwardOutputStream outputStream(tmpBuffer,0,_rleSize);
  232. auto readBits=[&](uint32_t count)->uint32_t
  233. {
  234. return bitReader.readBitsBE32(count);
  235. };
  236. auto readBit=[&]()->uint32_t
  237. {
  238. return bitReader.readBitsBE32(1);
  239. };
  240. // anchor-bit handling
  241. {
  242. uint32_t value=0;
  243. for (uint32_t i=0;i<4U;i++)
  244. {
  245. value>>=8U;
  246. value|=uint32_t(inputStream.readByte())<<24U;
  247. }
  248. uint32_t tmp=value;
  249. uint32_t count=0;
  250. while (tmp)
  251. {
  252. tmp<<=1;
  253. count++;
  254. }
  255. if (count) count--;
  256. if (count)
  257. bitReader.reset(value>>(32U-count),count);
  258. }
  259. struct SCItem
  260. {
  261. uint32_t distanceBits;
  262. uint32_t countBits;
  263. uint32_t addition;
  264. bool isLiteral;
  265. };
  266. // logic is very hard to un-convolute...
  267. HuffmanDecoder<SCItem> scDecoder
  268. {
  269. HuffmanCode<SCItem>{2,0b000,SCItem{0,3U,0,true}},
  270. HuffmanCode<SCItem>{3,0b010,SCItem{0,_modes[2]+1U,8U,true}},
  271. HuffmanCode<SCItem>{3,0b011,SCItem{_modes[0]+1U,_modes[1]+1U,5U,false}},
  272. HuffmanCode<SCItem>{2,0b010,SCItem{8U,0,2U,false}},
  273. HuffmanCode<SCItem>{3,0b110,SCItem{9U,0,3U,false}},
  274. HuffmanCode<SCItem>{3,0b111,SCItem{10U,0,4U,false}}
  275. };
  276. while (!outputStream.eof())
  277. {
  278. const auto &item=scDecoder.decode(readBit);
  279. if (item.isLiteral)
  280. {
  281. uint32_t count=readBits(item.countBits);
  282. if (!item.addition) count=!count?8U:count; // why?!?
  283. else count+=item.addition;
  284. for (uint32_t i=0;i<count;i++)
  285. outputStream.writeByte(readBits(8));
  286. } else {
  287. uint32_t count=readBits(item.countBits)+item.addition;
  288. uint32_t distance=readBits(item.distanceBits);
  289. outputStream.copy(distance,count);
  290. }
  291. }
  292. ForwardInputStream finalInputStream(tmpBuffer,0,_rleSize);
  293. ForwardOutputStream finalOutputStream(rawData,0,_rawSize);
  294. while (!finalOutputStream.eof())
  295. {
  296. uint8_t cmd=finalInputStream.readByte();
  297. if (cmd==_rle[0])
  298. {
  299. uint32_t count=uint32_t(finalInputStream.readByte())+1;
  300. if (count==1) finalOutputStream.writeByte(cmd);
  301. else {
  302. uint8_t value=finalInputStream.readByte();
  303. for (uint32_t i=0;i<=count;i++) finalOutputStream.writeByte(value);
  304. }
  305. } else if (cmd==_rle[1]) {
  306. uint32_t count=uint32_t(finalInputStream.readByte())+1;
  307. if (count==1) finalOutputStream.writeByte(cmd);
  308. else {
  309. for (uint32_t i=0;i<=count;i++) finalOutputStream.writeByte(_rle[2]);
  310. }
  311. } else finalOutputStream.writeByte(cmd);
  312. }
  313. }
  314. // v2.92, v2.99
  315. // v3.00
  316. void StoneCrackerDecompressor::decompressGen23(Buffer &rawData)
  317. {
  318. BackwardInputStream inputStream(_packedData,_dataOffset,_packedSize);
  319. LSBBitReader<BackwardInputStream> bitReader(inputStream);
  320. BackwardOutputStream outputStream(rawData,0,_rawSize);
  321. // anchor-bit handling
  322. {
  323. uint32_t value=0;
  324. for (uint32_t i=0;i<4U;i++)
  325. {
  326. value>>=8U;
  327. value|=uint32_t(inputStream.readByte())<<24U;
  328. }
  329. if (value) for (uint32_t i=31U;i>0;i--)
  330. {
  331. if (value&(1U<<i))
  332. {
  333. bitReader.reset(value&((1U<<i)-1U),i);
  334. break;
  335. }
  336. }
  337. }
  338. auto readBits=[&](uint32_t count)->uint32_t
  339. {
  340. return bitReader.readBitsBE32(count);
  341. };
  342. auto readBit=[&]()->uint32_t
  343. {
  344. return bitReader.readBitsBE32(1);
  345. };
  346. auto readCount=[&](uint32_t threshold,uint32_t bits)->uint32_t
  347. {
  348. uint32_t ret=0;
  349. uint32_t tmp;
  350. do
  351. {
  352. tmp=rotateBits(readBits(bits),bits);
  353. ret+=tmp;
  354. } while (tmp==threshold);
  355. return ret;
  356. };
  357. bool gen3=_generation>=3;
  358. while (!outputStream.eof())
  359. {
  360. if (readBit())
  361. {
  362. uint32_t count=readCount(7U,3U);
  363. if (gen3) count++;
  364. // for 2.92 zero count could meant count of 65536
  365. // for 2.99 it would be 4G
  366. // nevertheless it is an error
  367. // 3.00 fixes this by +1
  368. if (!count)
  369. throw DecompressionError();
  370. for (uint32_t i=0;i<count;i++)
  371. outputStream.writeByte(readBits(8));
  372. } else {
  373. uint32_t mode=rotateBits(readBits(2U),2U);
  374. uint32_t count;
  375. uint32_t modeBits=_modes[mode]+1U;
  376. if (mode==3)
  377. {
  378. if (readBit()) {
  379. count=readCount(7U,3U)+5U;
  380. if (gen3) modeBits=8U;
  381. } else count=readCount(127U,7U)+(gen3?5U:19U);
  382. } else {
  383. count=mode+2U;
  384. }
  385. uint32_t distance=rotateBits(readBits(modeBits),modeBits)+1U;
  386. outputStream.copy(distance,count);
  387. }
  388. }
  389. }
  390. // v3.10, v3.11b
  391. // pads output file, and this new size is also defined as rawSize in header!
  392. //
  393. // pre v4.00, v4.01
  394. void StoneCrackerDecompressor::decompressGen456(Buffer &rawData)
  395. {
  396. ForwardInputStream inputStream(_packedData,_dataOffset,_packedSize);
  397. MSBBitReader<ForwardInputStream> bitReader(inputStream);
  398. ForwardOutputStream outputStream(rawData,0,_rawSize);
  399. auto readBits=[&](uint32_t count)->uint32_t
  400. {
  401. if (_generation==4) return bitReader.readBitsBE32(count);
  402. else return bitReader.readBitsBE16(count);
  403. };
  404. auto readBit=[&]()->uint32_t
  405. {
  406. return readBits(1);
  407. };
  408. auto readCount=[&](uint32_t threshold,uint32_t bits)->uint32_t
  409. {
  410. uint32_t ret=0;
  411. uint32_t tmp;
  412. do
  413. {
  414. tmp=readBits(bits);
  415. ret+=tmp;
  416. } while (tmp==threshold);
  417. return ret;
  418. };
  419. static const uint8_t modes[4]={10U,11U,12U,8U};
  420. while (!outputStream.eof())
  421. {
  422. if (readBit())
  423. {
  424. uint32_t mode=readBits(2U);
  425. uint32_t distance=readBits(modes[mode]);
  426. // will obviously throw if distance is 0
  427. uint32_t count;
  428. if (mode>=2U)
  429. {
  430. if (_generation==4) count=readCount(15U,4U)+3U;
  431. else count=readCount(7U,3U)+3U;
  432. } else {
  433. count=mode+3U;
  434. }
  435. // yet another bug
  436. if (count>_rawSize-uint32_t(outputStream.getOffset()))
  437. count=_rawSize-uint32_t(outputStream.getOffset());
  438. outputStream.copy(distance,count);
  439. } else {
  440. uint32_t count=readCount(7U,3U);
  441. // A regression in 3.10 that is not fixed until 4.01
  442. if (_generation==6) count++;
  443. if (!count)
  444. throw DecompressionError();
  445. for (uint32_t i=0;i<count;i++)
  446. outputStream.writeByte(readBits(8));
  447. }
  448. }
  449. }
  450. // v4.02a
  451. void StoneCrackerDecompressor::decompressGen7(Buffer &rawData)
  452. {
  453. BackwardInputStream inputStream(_packedData,_dataOffset,_packedSize-2U);
  454. LSBBitReader<BackwardInputStream> bitReader(inputStream);
  455. BackwardOutputStream outputStream(rawData,0,_rawSize);
  456. // incomplete value at start
  457. {
  458. uint16_t bitCount=_packedData.readBE16(_packedSize-2U);
  459. if (bitCount>16U)
  460. throw DecompressionError();
  461. uint16_t value=inputStream.readByte();
  462. value|=uint16_t(inputStream.readByte())<<8U;
  463. bitReader.reset(value,bitCount&0xff);
  464. }
  465. auto readBits=[&](uint32_t count)->uint32_t
  466. {
  467. return bitReader.readBitsBE16(count);
  468. };
  469. auto readBit=[&]()->uint32_t
  470. {
  471. return bitReader.readBitsBE16(1);
  472. };
  473. while (!outputStream.eof())
  474. {
  475. if (readBit())
  476. {
  477. static const uint8_t distanceBits[4]={5U,8U,10U,12U};
  478. static const uint32_t distanceAdditions[4]={1U,0x21,0x121U,0x521U};
  479. uint32_t mode=readBits(2U);
  480. uint32_t distance=readBits(distanceBits[mode])+distanceAdditions[mode];
  481. // christmas tree!
  482. uint32_t count=2U;
  483. if (!readBit())
  484. {
  485. count++;
  486. if (!readBit())
  487. {
  488. count++;
  489. if (!readBit())
  490. {
  491. count++;
  492. uint32_t tmp;
  493. do
  494. {
  495. tmp=readBits(3U);
  496. count+=tmp;
  497. } while (tmp==7U);
  498. }
  499. }
  500. }
  501. outputStream.copy(distance,count);
  502. } else {
  503. outputStream.writeByte(readBits(8));
  504. }
  505. }
  506. }
  507. // v4.10
  508. void StoneCrackerDecompressor::decompressGen8(Buffer &rawData)
  509. {
  510. BackwardInputStream inputStream(_packedData,_dataOffset,_packedSize-2U);
  511. MSBBitReader<BackwardInputStream> bitReader(inputStream);
  512. BackwardOutputStream outputStream(rawData,0,_rawSize);
  513. // incomplete value at start
  514. uint16_t modeBits=0;
  515. {
  516. uint16_t bitCount=_packedData.readBE16(_packedSize-2U)&15U;
  517. uint16_t value=inputStream.readByte();
  518. value|=uint16_t(inputStream.readByte())<<8U;
  519. bitReader.reset(value>>(16U-bitCount),bitCount&0xff);
  520. modeBits=inputStream.readByte();
  521. modeBits|=uint16_t(inputStream.readByte())<<8U;
  522. if (modeBits<10U || modeBits>14U)
  523. throw DecompressionError();
  524. }
  525. auto readBits=[&](uint32_t count)->uint32_t
  526. {
  527. return bitReader.readBitsBE16(count);
  528. };
  529. auto readBit=[&]()->uint32_t
  530. {
  531. return bitReader.readBitsBE16(1);
  532. };
  533. struct CountItem
  534. {
  535. uint32_t bits;
  536. uint32_t addition;
  537. bool isLiteral;
  538. };
  539. struct DistanceItem
  540. {
  541. uint32_t bits;
  542. uint32_t addition;
  543. };
  544. HuffmanDecoder<CountItem> countDecoder
  545. {
  546. HuffmanCode<CountItem>{1,0b00000000,CountItem{0,1U,true}},
  547. HuffmanCode<CountItem>{2,0b00000011,CountItem{1U,2U,false}},
  548. HuffmanCode<CountItem>{3,0b00000101,CountItem{2U,4U,false}},
  549. HuffmanCode<CountItem>{4,0b00001000,CountItem{8U,23U,false}},
  550. HuffmanCode<CountItem>{5,0b00010010,CountItem{3U,8U,false}},
  551. HuffmanCode<CountItem>{6,0b00100110,CountItem{2U,16U,false}},
  552. HuffmanCode<CountItem>{7,0b01001110,CountItem{1U,20U,false}},
  553. HuffmanCode<CountItem>{8,0b10011110,CountItem{0,22U,false}},
  554. HuffmanCode<CountItem>{8,0b10011111,CountItem{5U,14U,true}}
  555. };
  556. HuffmanDecoder<DistanceItem> distanceDecoder
  557. {
  558. HuffmanCode<DistanceItem>{1,0b01,DistanceItem{modeBits,0x221U}},
  559. HuffmanCode<DistanceItem>{2,0b00,DistanceItem{9U,0x21U}},
  560. HuffmanCode<DistanceItem>{2,0b01,DistanceItem{5U,0x1U}}
  561. };
  562. while (!outputStream.eof())
  563. {
  564. const auto &countItem=countDecoder.decode(readBit);
  565. uint32_t count=countItem.addition;
  566. uint32_t tmp;
  567. do
  568. {
  569. tmp=readBits(countItem.bits);
  570. count+=tmp;
  571. } while (tmp==0xffU);
  572. if (countItem.isLiteral)
  573. {
  574. for (uint32_t i=0;i<count;i++)
  575. outputStream.writeByte(readBits(8));
  576. } else {
  577. const auto &distanceItem=distanceDecoder.decode(readBit);
  578. uint32_t distance=readBits(distanceItem.bits)+distanceItem.addition;
  579. outputStream.copy(distance,count);
  580. }
  581. }
  582. }
  583. void StoneCrackerDecompressor::decompressImpl(Buffer &rawData,bool verify)
  584. {
  585. if (rawData.size()<_rawSize) throw DecompressionError();
  586. if (!_rawSize) return;
  587. // The algorithms are all simple LZ compressors. However they will differ from version to version
  588. // on which order they read data, how much and on some other details
  589. // some of them can be nicely combined, others not so.
  590. //
  591. // To the creators credit, you can see generally improving performance as the versions increase
  592. // Although it is still limited by the simple nature of the implementation and does not really
  593. // compare to the more generic data compression algorithms
  594. switch (_generation)
  595. {
  596. case 1:
  597. decompressGen1(rawData);
  598. break;
  599. case 2:
  600. case 3:
  601. decompressGen23(rawData);
  602. break;
  603. case 4:
  604. case 5:
  605. case 6:
  606. decompressGen456(rawData);
  607. break;
  608. case 7:
  609. decompressGen7(rawData);
  610. break;
  611. case 8:
  612. decompressGen8(rawData);
  613. break;
  614. default:
  615. throw DecompressionError();
  616. }
  617. }
  618. }