SQSHDecompressor.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /* Copyright (C) Teemu Suutari */
  2. #include "SQSHDecompressor.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 SQSHDecompressor::detectHeaderXPK(uint32_t hdr) noexcept
  10. {
  11. return hdr==FourCC("SQSH");
  12. }
  13. std::shared_ptr<XPKDecompressor> SQSHDecompressor::create(uint32_t hdr,uint32_t recursionLevel,const Buffer &packedData,std::shared_ptr<XPKDecompressor::State> &state,bool verify)
  14. {
  15. return std::make_shared<SQSHDecompressor>(hdr,recursionLevel,packedData,state,verify);
  16. }
  17. SQSHDecompressor::SQSHDecompressor(uint32_t hdr,uint32_t recursionLevel,const Buffer &packedData,std::shared_ptr<XPKDecompressor::State> &state,bool verify) :
  18. XPKDecompressor(recursionLevel),
  19. _packedData(packedData)
  20. {
  21. if (!detectHeaderXPK(hdr) || packedData.size()<3) throw Decompressor::InvalidFormatError();
  22. _rawSize=packedData.readBE16(0);
  23. if (!_rawSize) throw Decompressor::InvalidFormatError();
  24. }
  25. SQSHDecompressor::~SQSHDecompressor()
  26. {
  27. // nothing needed
  28. }
  29. const std::string &SQSHDecompressor::getSubName() const noexcept
  30. {
  31. static std::string name="XPK-SQSH: Compressor for sampled sounds";
  32. return name;
  33. }
  34. void SQSHDecompressor::decompressImpl(Buffer &rawData,const Buffer &previousData,bool verify)
  35. {
  36. if (rawData.size()!=_rawSize) throw Decompressor::DecompressionError();
  37. ForwardInputStream inputStream(_packedData,2,_packedData.size());
  38. MSBBitReader<ForwardInputStream> bitReader(inputStream);
  39. auto readBits=[&](uint32_t count)->uint32_t
  40. {
  41. return bitReader.readBits8(count);
  42. };
  43. auto readSignedBits=[&](uint8_t bits)->int32_t
  44. {
  45. int32_t ret=readBits(bits);
  46. if (ret&(1<<(bits-1)))
  47. ret|=~0U<<bits;
  48. return ret;
  49. };
  50. auto readBit=[&]()->uint32_t
  51. {
  52. return bitReader.readBits8(1);
  53. };
  54. auto readByte=[&]()->uint8_t
  55. {
  56. return inputStream.readByte();
  57. };
  58. ForwardOutputStream outputStream(rawData,0,_rawSize);
  59. HuffmanDecoder<uint8_t> modDecoder
  60. {
  61. HuffmanCode<uint8_t>{1,0b0001,0},
  62. HuffmanCode<uint8_t>{2,0b0000,1},
  63. HuffmanCode<uint8_t>{3,0b0010,2},
  64. HuffmanCode<uint8_t>{4,0b0110,3},
  65. HuffmanCode<uint8_t>{4,0b0111,4}
  66. };
  67. HuffmanDecoder<uint8_t> lengthDecoder
  68. {
  69. HuffmanCode<uint8_t>{1,0b0000,0},
  70. HuffmanCode<uint8_t>{2,0b0010,1},
  71. HuffmanCode<uint8_t>{3,0b0110,2},
  72. HuffmanCode<uint8_t>{4,0b1110,3},
  73. HuffmanCode<uint8_t>{4,0b1111,4}
  74. };
  75. HuffmanDecoder<uint8_t> distanceDecoder
  76. {
  77. HuffmanCode<uint8_t>{1,0b01,0},
  78. HuffmanCode<uint8_t>{2,0b00,1},
  79. HuffmanCode<uint8_t>{2,0b01,2}
  80. };
  81. // first byte is special
  82. uint8_t currentSample=readByte();
  83. outputStream.writeByte(currentSample);
  84. uint32_t accum1=0,accum2=0,prevBits=0;
  85. while (!outputStream.eof())
  86. {
  87. uint8_t bits=0;
  88. uint32_t count=0;
  89. bool doRepeat=false;
  90. if (accum1>=8)
  91. {
  92. static const uint8_t bitLengthTable[7][8]={
  93. {2,3,4,5,6,7,8,0},
  94. {3,2,4,5,6,7,8,0},
  95. {4,3,5,2,6,7,8,0},
  96. {5,4,6,2,3,7,8,0},
  97. {6,5,7,2,3,4,8,0},
  98. {7,6,8,2,3,4,5,0},
  99. {8,7,6,2,3,4,5,0}};
  100. auto handleCondCase=[&]()
  101. {
  102. if (bits==8) {
  103. if (accum2<20)
  104. {
  105. count=1;
  106. } else {
  107. count=2;
  108. accum2+=8;
  109. }
  110. } else {
  111. count=5;
  112. accum2+=8;
  113. }
  114. };
  115. auto handleTable=[&](uint32_t newBits)
  116. {
  117. if (prevBits<2 || !newBits) throw Decompressor::DecompressionError();
  118. bits=bitLengthTable[prevBits-2][newBits-1];
  119. if (!bits) throw Decompressor::DecompressionError();
  120. handleCondCase();
  121. };
  122. uint32_t mod=modDecoder.decode(readBit);
  123. switch (mod)
  124. {
  125. case 0:
  126. if (prevBits==8)
  127. {
  128. bits=8;
  129. handleCondCase();
  130. } else {
  131. bits=prevBits;
  132. count=5;
  133. accum2+=8;
  134. }
  135. break;
  136. case 1:
  137. doRepeat=true;
  138. break;
  139. case 2:
  140. handleTable(2);
  141. break;
  142. case 3:
  143. handleTable(3);
  144. break;
  145. case 4:
  146. handleTable(readBits(2)+4);
  147. break;
  148. default:
  149. throw Decompressor::DecompressionError();
  150. }
  151. } else {
  152. if (readBit())
  153. {
  154. doRepeat=true;
  155. } else {
  156. count=1;
  157. bits=8;
  158. }
  159. }
  160. if (doRepeat) {
  161. uint32_t lengthIndex=lengthDecoder.decode(readBit);
  162. static const uint8_t lengthBits[5]={1,1,1,3,5};
  163. static const uint32_t lengthAdditions[5]={2,4,6,8,16};
  164. count=readBits(lengthBits[lengthIndex])+lengthAdditions[lengthIndex];
  165. if (count>=3)
  166. {
  167. if (accum1) accum1--;
  168. if (count>3 && accum1) accum1--;
  169. }
  170. uint32_t distanceIndex=distanceDecoder.decode(readBit);
  171. static const uint8_t distanceBits[3]={12,8,14};
  172. static const uint32_t distanceAdditions[3]={0x101,1,0x1101};
  173. uint32_t distance=readBits(distanceBits[distanceIndex])+distanceAdditions[distanceIndex];
  174. count=std::min(count,uint32_t(_rawSize-outputStream.getOffset()));
  175. currentSample=outputStream.copy(distance,count);
  176. } else {
  177. count=std::min(count,uint32_t(_rawSize-outputStream.getOffset()));
  178. for (uint32_t i=0;i<count;i++)
  179. {
  180. currentSample-=readSignedBits(bits);
  181. outputStream.writeByte(currentSample);
  182. }
  183. if (accum1!=31) accum1++;
  184. prevBits=bits;
  185. }
  186. accum2-=accum2>>3;
  187. }
  188. }
  189. }