MMCMPDecompressor.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /* Copyright (C) Teemu Suutari */
  2. #include <cstring>
  3. #include "MMCMPDecompressor.hpp"
  4. #include "InputStream.hpp"
  5. #include "OutputStream.hpp"
  6. #include "common/OverflowCheck.hpp"
  7. #include "common/Common.hpp"
  8. namespace ancient::internal
  9. {
  10. bool MMCMPDecompressor::detectHeader(uint32_t hdr) noexcept
  11. {
  12. return hdr==FourCC("ziRC");
  13. }
  14. std::shared_ptr<Decompressor> MMCMPDecompressor::create(const Buffer &packedData,bool exactSizeKnown,bool verify)
  15. {
  16. return std::make_shared<MMCMPDecompressor>(packedData,exactSizeKnown,verify);
  17. }
  18. MMCMPDecompressor::MMCMPDecompressor(const Buffer &packedData,bool exactSizeKnown,bool verify) :
  19. _packedData(packedData)
  20. {
  21. if (!detectHeader(packedData.readBE32(0)) || packedData.readBE32(4U)!=FourCC("ONia") ||
  22. packedData.readLE16(8U)!=14U || packedData.size()<24U)
  23. throw InvalidFormatError();
  24. _version=packedData.readLE16(10U);
  25. _blocks=packedData.readLE16(12U);
  26. _blocksOffset=packedData.readLE32(18U);
  27. _rawSize=packedData.readLE32(14U);
  28. if (OverflowCheck::sum(_blocksOffset,uint32_t(_blocks)*4U)>packedData.size())
  29. throw InvalidFormatError();
  30. _packedSize=0;
  31. for (uint32_t i=0;i<_blocks;i++)
  32. {
  33. uint32_t blockAddr=packedData.readLE32(OverflowCheck::sum(_blocksOffset,i*4U));
  34. if (OverflowCheck::sum(blockAddr,20U)>=packedData.size())
  35. throw InvalidFormatError();
  36. uint32_t blockSize=packedData.readLE32(blockAddr+4U)+uint32_t(packedData.readLE16(blockAddr+12U))*8U+20U;
  37. _packedSize=std::max(_packedSize,OverflowCheck::sum(blockAddr,blockSize));
  38. }
  39. if (_packedSize>packedData.size())
  40. throw InvalidFormatError();
  41. }
  42. MMCMPDecompressor::~MMCMPDecompressor()
  43. {
  44. // nothing needed
  45. }
  46. const std::string &MMCMPDecompressor::getName() const noexcept
  47. {
  48. static std::string name="MMCMP: Music Module Compressor";
  49. return name;
  50. }
  51. size_t MMCMPDecompressor::getPackedSize() const noexcept
  52. {
  53. return _packedSize;
  54. }
  55. size_t MMCMPDecompressor::getRawSize() const noexcept
  56. {
  57. return _rawSize;
  58. }
  59. void MMCMPDecompressor::decompressImpl(Buffer &rawData,bool verify)
  60. {
  61. if (rawData.size()<_rawSize) throw DecompressionError();
  62. // MMCMP allows gaps in data. Although not used in practice still we memset before decompressing to be sure
  63. std::memset(rawData.data(),0,rawData.size());
  64. uint8_t *rawDataPtr=rawData.data();
  65. for (uint32_t i=0;i<_blocks;i++)
  66. {
  67. uint32_t blockAddr=_packedData.readLE32(_blocksOffset+i*4U);
  68. uint32_t unpackedBlockSize=_packedData.readLE32(blockAddr);
  69. uint32_t packedBlockSize=_packedData.readLE32(blockAddr+4U);
  70. uint32_t fileChecksum=_packedData.readLE32(blockAddr+8U);
  71. uint32_t subBlocks=_packedData.readLE16(blockAddr+12U);
  72. uint16_t flags=_packedData.readLE16(blockAddr+14U);
  73. uint32_t packTableSize=_packedData.readLE16(blockAddr+16U);
  74. if (packTableSize>packedBlockSize)
  75. throw DecompressionError();
  76. uint16_t bitCount=_packedData.readLE16(blockAddr+18U);
  77. ForwardInputStream inputStream(_packedData,OverflowCheck::sum(blockAddr,subBlocks*8U,20U,packTableSize),OverflowCheck::sum(blockAddr,subBlocks*8U,20U,packedBlockSize));
  78. LSBBitReader<ForwardInputStream> bitReader(inputStream);
  79. auto readBits=[&](uint32_t count)->uint32_t
  80. {
  81. return bitReader.readBits8(count);
  82. };
  83. uint32_t currentSubBlock=0;
  84. uint32_t outputOffset=0,outputSize=0;
  85. auto readNextSubBlock=[&]()
  86. {
  87. if (currentSubBlock>=subBlocks)
  88. throw DecompressionError();
  89. outputOffset=_packedData.readLE32(blockAddr+currentSubBlock*8U+20U);
  90. outputSize=_packedData.readLE32(blockAddr+currentSubBlock*8U+24U);
  91. if (OverflowCheck::sum(outputOffset,outputSize)>_rawSize)
  92. throw DecompressionError();
  93. currentSubBlock++;
  94. };
  95. uint32_t checksum=0,checksumPartial=0,checksumRot=0;
  96. auto writeByte=[&](uint8_t value,bool allowOverrun=false)
  97. {
  98. while (!outputSize)
  99. {
  100. if (allowOverrun && currentSubBlock>=subBlocks) return;
  101. readNextSubBlock();
  102. }
  103. outputSize--;
  104. rawDataPtr[outputOffset++]=value;
  105. if (verify)
  106. {
  107. if (_version>=0x1310)
  108. {
  109. checksum^=value;
  110. checksum=(checksum<<1)|(checksum>>31);
  111. } else {
  112. checksumPartial|=((uint32_t)value)<<checksumRot;
  113. checksumRot+=8U;
  114. if (checksumRot==32U)
  115. {
  116. checksum^=checksumPartial;
  117. checksumPartial=0;
  118. checksumRot=0;
  119. }
  120. }
  121. }
  122. };
  123. // flags are
  124. // 0 = compressed
  125. // 1 = delta mode
  126. // 2 = 16 bit mode
  127. // 8 = stereo
  128. // 9 = abs16
  129. // 10 = endian
  130. // flags do not combine nicely
  131. // no compress - no other flags
  132. // compressed 8 bit - only delta (and presumably stereo matters)
  133. // compressed 16 bit - all flags matter
  134. if (!(flags&0x1U))
  135. {
  136. // not compressed
  137. for (uint32_t j=0;j<packedBlockSize;j++)
  138. writeByte(inputStream.readByte());
  139. } else if (!(flags&0x4U)) {
  140. // 8 bit compression
  141. // in case the bit-count is not enough to store a value, symbol at the end
  142. // of the codemap is created and this marks as a new bitCount
  143. static const uint8_t valueThresholds[16]={0x1U, 0x3U, 0x7U, 0xfU,0x1eU,0x3cU,0x78U,0xf8U};
  144. static const uint8_t extraBits[8]={3,3,3,3, 2,1,0,0};
  145. if (bitCount>=8)
  146. throw DecompressionError();
  147. uint8_t oldValue[2]={0,0};
  148. uint32_t chIndex=0;
  149. const uint8_t *tablePtr=&_packedData[blockAddr+subBlocks*8U+20U];
  150. for (uint32_t j=0;j<unpackedBlockSize;)
  151. {
  152. uint8_t value=readBits(bitCount+1);
  153. if (value>=valueThresholds[bitCount])
  154. {
  155. uint32_t newBitCount=readBits(extraBits[bitCount])+((value-valueThresholds[bitCount])<<extraBits[bitCount]);
  156. if (bitCount!=newBitCount)
  157. {
  158. bitCount=newBitCount&0x7U;
  159. continue;
  160. }
  161. value=0xf8U+readBits(3U);
  162. if (value==0xffU && readBits(1U)) break;
  163. }
  164. if (value>=packTableSize)
  165. throw DecompressionError();
  166. value=tablePtr[value];
  167. if (flags&0x2U)
  168. {
  169. // delta
  170. value+=oldValue[chIndex];
  171. oldValue[chIndex]=value;
  172. if (flags&0x100U) chIndex^=1U; // stereo
  173. }
  174. writeByte(value);
  175. j++;
  176. }
  177. } else {
  178. // 16 bit compression
  179. // shameless copy-paste from 8-bit variant, with minor changes
  180. static const uint16_t valueThresholds[16]={
  181. 0x1U, 0x3U, 0x7U, 0xfU, 0x1eU, 0x3cU, 0x78U, 0xf0U,
  182. 0x1f0U, 0x3f0U, 0x7f0U, 0xff0U,0x1ff0U,0x3ff0U,0x7ff0U,0xfff0U
  183. };
  184. static const uint8_t extraBits[16]={4,4,4,4, 3,2,1,0, 0,0,0,0, 0,0,0,0};
  185. if (bitCount>=16)
  186. throw DecompressionError();
  187. int16_t oldValue[2]={0,0};
  188. uint32_t chIndex=0;
  189. for (uint32_t j=0;j<unpackedBlockSize;)
  190. {
  191. int32_t value=readBits(bitCount+1);
  192. if (value>=valueThresholds[bitCount])
  193. {
  194. uint32_t newBitCount=readBits(extraBits[bitCount])+((value-valueThresholds[bitCount])<<extraBits[bitCount]);
  195. if (bitCount!=newBitCount)
  196. {
  197. bitCount=newBitCount&0xfU;
  198. continue;
  199. }
  200. value=0xfff0U+readBits(4U);
  201. if (value==0xffffU && readBits(1U)) break;
  202. }
  203. if (value&1U) value=-value-1;
  204. value>>=1;
  205. if (flags&0x2U)
  206. {
  207. // delta
  208. value+=oldValue[chIndex];
  209. oldValue[chIndex]=value;
  210. if (flags&0x100U) chIndex^=1U; // stereo
  211. } else if (!(flags&0x200U)) value^=0x8000U; // abs16
  212. if (flags&0x400U)
  213. {
  214. // big ending
  215. writeByte(value>>8U);
  216. writeByte(value,true);
  217. } else {
  218. // little endian
  219. writeByte(value);
  220. writeByte(value>>8U,true);
  221. }
  222. j+=2;
  223. }
  224. }
  225. if (verify && checksum!=fileChecksum)
  226. throw VerificationError();
  227. }
  228. }
  229. }