SLZ3Decompressor.cpp 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. /* Copyright (C) Teemu Suutari */
  2. #include "SLZ3Decompressor.hpp"
  3. #include "InputStream.hpp"
  4. #include "OutputStream.hpp"
  5. #include "common/Common.hpp"
  6. namespace ancient::internal
  7. {
  8. bool SLZ3Decompressor::detectHeaderXPK(uint32_t hdr) noexcept
  9. {
  10. return hdr==FourCC("SLZ3");
  11. }
  12. std::shared_ptr<XPKDecompressor> SLZ3Decompressor::create(uint32_t hdr,uint32_t recursionLevel,const Buffer &packedData,std::shared_ptr<XPKDecompressor::State> &state,bool verify)
  13. {
  14. return std::make_shared<SLZ3Decompressor>(hdr,recursionLevel,packedData,state,verify);
  15. }
  16. SLZ3Decompressor::SLZ3Decompressor(uint32_t hdr,uint32_t recursionLevel,const Buffer &packedData,std::shared_ptr<XPKDecompressor::State> &state,bool verify) :
  17. XPKDecompressor(recursionLevel),
  18. _packedData(packedData)
  19. {
  20. if (!detectHeaderXPK(hdr)) throw Decompressor::InvalidFormatError();
  21. }
  22. SLZ3Decompressor::~SLZ3Decompressor()
  23. {
  24. // nothing needed
  25. }
  26. const std::string &SLZ3Decompressor::getSubName() const noexcept
  27. {
  28. static std::string name="XPK-SLZ3: SLZ3 CyberYAFA compressor";
  29. return name;
  30. }
  31. void SLZ3Decompressor::decompressImpl(Buffer &rawData,const Buffer &previousData,bool verify)
  32. {
  33. ForwardInputStream inputStream(_packedData,0,_packedData.size());
  34. MSBBitReader<ForwardInputStream> bitReader(inputStream);
  35. auto readBit=[&]()->uint32_t
  36. {
  37. return bitReader.readBits8(1);
  38. };
  39. auto readByte=[&]()->uint8_t
  40. {
  41. return inputStream.readByte();
  42. };
  43. ForwardOutputStream outputStream(rawData,0,rawData.size());
  44. while (!outputStream.eof())
  45. {
  46. if (!readBit())
  47. {
  48. outputStream.writeByte(readByte());
  49. } else {
  50. uint8_t tmp=readByte();
  51. if (!tmp) throw Decompressor::DecompressionError();
  52. uint32_t distance=uint32_t(tmp&0xf0)<<4;
  53. distance|=uint32_t(readByte());
  54. uint32_t count=uint32_t(tmp&0xf)+2;
  55. outputStream.copy(distance,count);
  56. }
  57. }
  58. }
  59. }