Guest User

MPPC Unpacker Perfect World

a guest
Sep 25th, 2013
377
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 8.06 KB | None | 0 0
  1.     public class MppcUnpacker
  2.     {
  3.         private int code1;
  4.         private int code2;
  5.         private int code3;
  6.         private int code4;
  7.  
  8.         private byte packedOffset;
  9.  
  10.         private readonly List<byte> packedBytes;
  11.         private readonly List<byte> unpackedBytes;
  12.         private List<byte> unpackedChunk;
  13.  
  14.         public MppcUnpacker()
  15.         {
  16.             code3 = 0;
  17.             code4 = 0;
  18.  
  19.             packedBytes = new List<byte>();
  20.             unpackedBytes = new List<byte>();
  21.         }
  22.  
  23.         public byte[] Unpack(byte packedByte)
  24.         {
  25.             packedBytes.Add(packedByte);
  26.  
  27.             unpackedChunk = new List<byte>();
  28.  
  29.             if (unpackedBytes.Count >= 10240)
  30.                 unpackedBytes.RemoveRange(0, 2048);
  31.  
  32.             for (; ; )
  33.             {
  34.                 if (code3 == 0)
  35.                 {
  36.                     if (HasBits(4))
  37.                     {
  38.                         if (GetPackedBits(1) == 0)
  39.                         {
  40.                             // 0-xxxxxxx
  41.                             code1 = 1;
  42.                             code3 = 1;
  43.                         }
  44.                         else
  45.                         {
  46.                             if (GetPackedBits(1) == 0)
  47.                             {
  48.                                 // 10-xxxxxxx
  49.                                 code1 = 2;
  50.                                 code3 = 1;
  51.                             }
  52.                             else
  53.                             {
  54.                                 if (GetPackedBits(1) == 0)
  55.                                 {
  56.                                     // 110-xxxxxxxxxxxxx-*
  57.                                     code1 = 3;
  58.                                     code3 = 1;
  59.                                 }
  60.                                 else
  61.                                 {
  62.                                     if (GetPackedBits(1) == 0)
  63.                                     {
  64.                                         // 1110-xxxxxxxx-*
  65.                                         code1 = 4;
  66.                                         code3 = 1;
  67.                                     }
  68.                                     else
  69.                                     {
  70.                                         // 1111-xxxxxx-*
  71.                                         code1 = 5;
  72.                                         code3 = 1;
  73.                                     }
  74.                                 }
  75.                             }
  76.                         }
  77.                     }
  78.                     else
  79.                         break;
  80.                 }
  81.                 else if (code3 == 1)
  82.                 {
  83.                     if (code1 == 1)
  84.                     {
  85.                         if (HasBits(7))
  86.                         {
  87.                             var outB = (byte)GetPackedBits(7);
  88.                             unpackedChunk.Add(outB);
  89.                             unpackedBytes.Add(outB);
  90.                             code3 = 0;
  91.                         }
  92.                         else
  93.                             break;
  94.                     }
  95.                     else if (code1 == 2)
  96.                     {
  97.                         if (HasBits(7))
  98.                         {
  99.                             var outB = (byte)(GetPackedBits(7) | 0x80);
  100.                             unpackedChunk.Add(outB);
  101.                             unpackedBytes.Add(outB);
  102.                             code3 = 0;
  103.                         }
  104.                         else
  105.                             break;
  106.                     }
  107.                     else if (code1 == 3)
  108.                     {
  109.                         if (HasBits(13))
  110.                         {
  111.                             code4 = (int)GetPackedBits(13) + 0x140;
  112.                             code3 = 2;
  113.                         }
  114.                         else
  115.                             break;
  116.                     }
  117.                     else if (code1 == 4)
  118.                     {
  119.                         if (HasBits(8))
  120.                         {
  121.                             code4 = (int)GetPackedBits(8) + 0x40;
  122.                             code3 = 2;
  123.                         }
  124.                         else
  125.                             break;
  126.                     }
  127.                     else if (code1 == 5)
  128.                     {
  129.                         if (HasBits(6))
  130.                         {
  131.                             code4 = (int)GetPackedBits(6);
  132.                             code3 = 2;
  133.                         }
  134.                         else
  135.                             break;
  136.                     }
  137.                 }
  138.                 else if (code3 == 2)
  139.                 {
  140.                     if (code4 == 0)
  141.                     {
  142.                         // Guess !!!
  143.                         if (packedOffset != 0)
  144.                         {
  145.                             packedOffset = 0;
  146.                             packedBytes.RemoveAt(0);
  147.                         }
  148.                         code3 = 0;
  149.                         continue;
  150.                     }
  151.                     code2 = 0;
  152.                     code3 = 3;
  153.                 }
  154.                 else if (code3 == 3)
  155.                 {
  156.                     if (HasBits(1))
  157.                     {
  158.                         if (GetPackedBits(1) == 0)
  159.                         {
  160.                             code3 = 4;
  161.                         }
  162.                         else
  163.                         {
  164.                             code2++;
  165.                         }
  166.                     }
  167.                     else
  168.                         break;
  169.                 }
  170.                 else if (code3 == 4)
  171.                 {
  172.                     int copySize;
  173.  
  174.                     if (code2 == 0)
  175.                     {
  176.                         copySize = 3;
  177.                     }
  178.                     else
  179.                     {
  180.                         var size = code2 + 1;
  181.  
  182.                         if (HasBits(size))
  183.                         {
  184.                             copySize = (int)GetPackedBits(size) + (1 << size);
  185.                         }
  186.                         else
  187.                             break;
  188.                     }
  189.  
  190.                     Copy(code4, copySize, ref unpackedChunk);
  191.                     code3 = 0;
  192.                 }
  193.             }
  194.  
  195.             return unpackedChunk.ToArray();
  196.         }
  197.  
  198.         public byte[] Unpack(byte[] compressedBytes)
  199.         {
  200.             var rtnList = new List<byte>(compressedBytes.Length);
  201.  
  202.             foreach (var b in compressedBytes)
  203.             {
  204.                 rtnList.AddRange(Unpack(b));
  205.             }
  206.  
  207.             return rtnList.ToArray();
  208.         }
  209.  
  210.         private void Copy(int shift, int size, ref List<byte> unpackedChunkData)
  211.         {
  212.             for (var i = 0; i < size; i++)
  213.             {
  214.                 var pIndex = unpackedBytes.Count - shift;
  215.  
  216.                 if (pIndex < 0)
  217.                     return;
  218.  
  219.                 var b = unpackedBytes[pIndex];
  220.                 unpackedBytes.Add(b);
  221.                 unpackedChunkData.Add(b);
  222.             }
  223.         }
  224.  
  225.         private uint GetPackedBits(int bitCount)
  226.         {
  227.             if (bitCount > 16)
  228.                 return 0;
  229.  
  230.             if (!HasBits(bitCount))
  231.                 throw new Exception("Unpack bit stream overflow");
  232.  
  233.             var alBitCount = bitCount + packedOffset;
  234.             var alByteCount = (alBitCount + 7) / 8;
  235.  
  236.             uint v = 0;
  237.  
  238.             for (var i = 0; i < alByteCount; i++)
  239.             {
  240.                 v |= (uint)(packedBytes[i]) << (24 - i * 8);
  241.             }
  242.  
  243.             v <<= packedOffset;
  244.             v >>= 32 - bitCount;
  245.  
  246.             packedOffset += (byte)bitCount;
  247.             var freeBytes = packedOffset / 8;
  248.  
  249.             if (freeBytes != 0)
  250.                 packedBytes.RemoveRange(0, freeBytes);
  251.  
  252.             packedOffset %= 8;
  253.             return v;
  254.         }
  255.  
  256.         private bool HasBits(int count)
  257.         {
  258.             return (packedBytes.Count * 8 - packedOffset) >= count;
  259.         }
  260.     }
Advertisement
Add Comment
Please, Sign In to add comment