Lz4.cs 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. using System;
  2. namespace Ryujinx.HLE.Loaders.Compression
  3. {
  4. static class Lz4
  5. {
  6. public static byte[] Decompress(byte[] cmp, int decLength)
  7. {
  8. byte[] dec = new byte[decLength];
  9. int cmpPos = 0;
  10. int decPos = 0;
  11. int GetLength(int length)
  12. {
  13. byte sum;
  14. if (length == 0xf)
  15. {
  16. do
  17. {
  18. length += (sum = cmp[cmpPos++]);
  19. }
  20. while (sum == 0xff);
  21. }
  22. return length;
  23. }
  24. do
  25. {
  26. byte token = cmp[cmpPos++];
  27. int encCount = (token >> 0) & 0xf;
  28. int litCount = (token >> 4) & 0xf;
  29. // Copy literal chunk
  30. litCount = GetLength(litCount);
  31. Buffer.BlockCopy(cmp, cmpPos, dec, decPos, litCount);
  32. cmpPos += litCount;
  33. decPos += litCount;
  34. if (cmpPos >= cmp.Length)
  35. {
  36. break;
  37. }
  38. // Copy compressed chunk
  39. int back = cmp[cmpPos++] << 0 |
  40. cmp[cmpPos++] << 8;
  41. encCount = GetLength(encCount) + 4;
  42. int encPos = decPos - back;
  43. if (encCount <= back)
  44. {
  45. Buffer.BlockCopy(dec, encPos, dec, decPos, encCount);
  46. decPos += encCount;
  47. }
  48. else
  49. {
  50. while (encCount-- > 0)
  51. {
  52. dec[decPos++] = dec[encPos++];
  53. }
  54. }
  55. }
  56. while (cmpPos < cmp.Length &&
  57. decPos < dec.Length);
  58. return dec;
  59. }
  60. }
  61. }