• Welcome to Valhalla Legends Archive.
 

C# .NET Compression/Decompression Code (Can Someone Help ?)

Started by Fr3DBr, August 28, 2006, 09:50 PM

Previous topic - Next topic

Fr3DBr

Cool heres my code snipet for now ;), i want some help XD

Actually it doesnt works.... but i want to make it work, so lets go :D


    public class D2GSCompression
    {
        #region [TABLES]

        //----------------------------------------------------------------------
        // Packet Decompression Tables
        //----------------------------------------------------------------------

        int[] CharIndex = {
           0x0247, 0x0236, 0x0225, 0x0214, 0x0203, 0x01F2, 0x01E1, 0x01D0,
           0x01BF, 0x01AE, 0x019D, 0x018C, 0x017B, 0x016A, 0x0161, 0x0158,
           0x014F, 0x0146, 0x013D, 0x0134, 0x012B, 0x0122, 0x0119, 0x0110,
           0x0107, 0x00FE, 0x00F5, 0x00EC, 0x00E3, 0x00DA, 0x00D1, 0x00C8,
           0x00BF, 0x00B6, 0x00AD, 0x00A8, 0x00A3, 0x009E, 0x0099, 0x0094,
           0x008F, 0x008A, 0x0085, 0x0080, 0x007B, 0x0076, 0x0071, 0x006C,
           0x0069, 0x0066, 0x0063, 0x0060, 0x005D, 0x005A, 0x0057, 0x0054,
           0x0051, 0x004E, 0x004B, 0x0048, 0x0045, 0x0042, 0x003F, 0x003F,
           0x003C, 0x003C, 0x0039, 0x0039, 0x0036, 0x0036, 0x0033, 0x0033,
           0x0030, 0x0030, 0x002D, 0x002D, 0x002A, 0x002A, 0x0027, 0x0027,
           0x0024, 0x0024, 0x0021, 0x0021, 0x001E, 0x001E, 0x001B, 0x001B,
           0x0018, 0x0018, 0x0015, 0x0015, 0x0012, 0x0012, 0x0012, 0x0012,
           0x000F, 0x000F, 0x000F, 0x000F, 0x000C, 0x000C, 0x000C, 0x000C,
           0x0009, 0x0009, 0x0009, 0x0009, 0x0006, 0x0006, 0x0006, 0x0006,
           0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
           0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
        };


        byte[] CharTable = {
           0x00,0x00,0x01,0x00,0x01,0x04,0x00,0xFF,0x06,0x00,0x14,0x06,
           0x00,0x13,0x06,0x00,0x05,0x06,0x00,0x02,0x06,0x00,0x80,0x07,
           0x00,0x6D,0x07,0x00,0x69,0x07,0x00,0x68,0x07,0x00,0x67,0x07,
           0x00,0x1E,0x07,0x00,0x15,0x07,0x00,0x12,0x07,0x00,0x0D,0x07,
           0x00,0x0A,0x07,0x00,0x08,0x07,0x00,0x07,0x07,0x00,0x06,0x07,
           0x00,0x04,0x07,0x00,0x03,0x07,0x00,0x6C,0x08,0x00,0x51,0x08,
           0x00,0x20,0x08,0x00,0x1F,0x08,0x00,0x1D,0x08,0x00,0x18,0x08,
           0x00,0x17,0x08,0x00,0x16,0x08,0x00,0x11,0x08,0x00,0x10,0x08,
           0x00,0x0F,0x08,0x00,0x0C,0x08,0x00,0x0B,0x08,0x00,0x09,0x08,
           0x01,0x96,0x09,0x97,0x09,0x01,0x90,0x09,0x95,0x09,0x01,0x64,
           0x09,0x6B,0x09,0x01,0x62,0x09,0x63,0x09,0x01,0x56,0x09,0x58,
           0x09,0x01,0x52,0x09,0x55,0x09,0x01,0x4D,0x09,0x50,0x09,0x01,
           0x45,0x09,0x4C,0x09,0x01,0x40,0x09,0x43,0x09,0x01,0x31,0x09,
           0x3B,0x09,0x01,0x28,0x09,0x30,0x09,0x01,0x1A,0x09,0x25,0x09,
           0x01,0x0E,0x09,0x19,0x09,0x02,0xE2,0x0A,0xE8,0x0A,0xF0,0x0A,
           0xF8,0x0A,0x02,0xC0,0x0A,0xC2,0x0A,0xCE,0x0A,0xE0,0x0A,0x02,
           0xA0,0x0A,0xA2,0x0A,0xB0,0x0A,0xB8,0x0A,0x02,0x8A,0x0A,0x8F,
           0x0A,0x93,0x0A,0x98,0x0A,0x02,0x81,0x0A,0x82,0x0A,0x83,0x0A,
           0x89,0x0A,0x02,0x7C,0x0A,0x7D,0x0A,0x7E,0x0A,0x7F,0x0A,0x02,
           0x77,0x0A,0x78,0x0A,0x79,0x0A,0x7A,0x0A,0x02,0x73,0x0A,0x74,
           0x0A,0x75,0x0A,0x76,0x0A,0x02,0x6E,0x0A,0x6F,0x0A,0x70,0x0A,
           0x72,0x0A,0x02,0x61,0x0A,0x65,0x0A,0x66,0x0A,0x6A,0x0A,0x02,
           0x5D,0x0A,0x5E,0x0A,0x5F,0x0A,0x60,0x0A,0x02,0x57,0x0A,0x59,
           0x0A,0x5A,0x0A,0x5B,0x0A,0x02,0x4A,0x0A,0x4B,0x0A,0x4E,0x0A,
           0x53,0x0A,0x02,0x46,0x0A,0x47,0x0A,0x48,0x0A,0x49,0x0A,0x02,
           0x3F,0x0A,0x41,0x0A,0x42,0x0A,0x44,0x0A,0x02,0x3A,0x0A,0x3C,
           0x0A,0x3D,0x0A,0x3E,0x0A,0x02,0x36,0x0A,0x37,0x0A,0x38,0x0A,
           0x39,0x0A,0x02,0x32,0x0A,0x33,0x0A,0x34,0x0A,0x35,0x0A,0x02,
           0x2B,0x0A,0x2C,0x0A,0x2D,0x0A,0x2E,0x0A,0x02,0x26,0x0A,0x27,
           0x0A,0x29,0x0A,0x2A,0x0A,0x02,0x21,0x0A,0x22,0x0A,0x23,0x0A,
           0x24,0x0A,0x03,0xFB,0x0B,0xFC,0x0B,0xFD,0x0B,0xFE,0x0B,0x1B,
           0x0A,0x1B,0x0A,0x1C,0x0A,0x1C,0x0A,0x03,0xF2,0x0B,0xF3,0x0B,
           0xF4,0x0B,0xF5,0x0B,0xF6,0x0B,0xF7,0x0B,0xF9,0x0B,0xFA,0x0B,
           0x03,0xE9,0x0B,0xEA,0x0B,0xEB,0x0B,0xEC,0x0B,0xED,0x0B,0xEE,
           0x0B,0xEF,0x0B,0xF1,0x0B,0x03,0xDE,0x0B,0xDF,0x0B,0xE1,0x0B,
           0xE3,0x0B,0xE4,0x0B,0xE5,0x0B,0xE6,0x0B,0xE7,0x0B,0x03,0xD6,
           0x0B,0xD7,0x0B,0xD8,0x0B,0xD9,0x0B,0xDA,0x0B,0xDB,0x0B,0xDC,
           0x0B,0xDD,0x0B,0x03,0xCD,0x0B,0xCF,0x0B,0xD0,0x0B,0xD1,0x0B,
           0xD2,0x0B,0xD3,0x0B,0xD4,0x0B,0xD5,0x0B,0x03,0xC5,0x0B,0xC6,
           0x0B,0xC7,0x0B,0xC8,0x0B,0xC9,0x0B,0xCA,0x0B,0xCB,0x0B,0xCC,
           0x0B,0x03,0xBB,0x0B,0xBC,0x0B,0xBD,0x0B,0xBE,0x0B,0xBF,0x0B,
           0xC1,0x0B,0xC3,0x0B,0xC4,0x0B,0x03,0xB2,0x0B,0xB3,0x0B,0xB4,
           0x0B,0xB5,0x0B,0xB6,0x0B,0xB7,0x0B,0xB9,0x0B,0xBA,0x0B,0x03,
           0xA9,0x0B,0xAA,0x0B,0xAB,0x0B,0xAC,0x0B,0xAD,0x0B,0xAE,0x0B,
           0xAF,0x0B,0xB1,0x0B,0x03,0x9F,0x0B,0xA1,0x0B,0xA3,0x0B,0xA4,
           0x0B,0xA5,0x0B,0xA6,0x0B,0xA7,0x0B,0xA8,0x0B,0x03,0x92,0x0B,
           0x94,0x0B,0x99,0x0B,0x9A,0x0B,0x9B,0x0B,0x9C,0x0B,0x9D,0x0B,
           0x9E,0x0B,0x03,0x86,0x0B,0x87,0x0B,0x88,0x0B,0x8B,0x0B,0x8C,
           0x0B,0x8D,0x0B,0x8E,0x0B,0x91,0x0B,0x03,0x2F,0x0B,0x4F,0x0B,
           0x54,0x0B,0x5C,0x0B,0x71,0x0B,0x7B,0x0B,0x84,0x0B,0x85,0x0B
        };

        int[] BitMasks = {
           0x0000,0x0001,0x0003,0x0007,0x000F,0x001F,0x003F,0x007F,
           0x00FF,0x01FF,0x03FF,0x07FF,0x0FFF,0x1FFF,0x3FFF,0x7FFF
        };

        #endregion

        #region [PACKET SIZE]
        //----------------------------------------------------------------------
        // GamePacketSize
        //   Calculates the size of a compressed game packet.
        //   
        // data: [in] pointer to received packet
        // size: [out] pointer to size
        // returns: the offset to the data.
        //----------------------------------------------------------------------

        byte GamePacketSize(byte[] data, int size, int offset)
        {
           int a;

           if (data[0] < 0xF0)
           {
               size = data[0] - 1;
               offset = 1;
               return data[1];
           }

           a = (data[0] & 0xF) << 8;
           size = a + data[1] - 2;
           offset = 2;
           return data[2];
        }
        #endregion

        public bool Compress(Byte[] input, Byte[] output)
        {
            return true;
        }

        public bool Decompress(Byte[] input, int ilen, Byte[] output, int olen, int osize)
        {
            //----------------------------------------------------------------------
            // GamePacketDecode
            //   Decompress a d2gs packet into data.
            //   Note: packets come in clumps. A single compressed packet may have
            //   several game packets, and its up to you to figure it out.
            //
            // indata: [in] compressed packet (without size byte)
            // insize: [in] length of indata
            // outdata: [out] output buffer
            // outmax: [in] size of output buffer
            // outsize: [out] location to store size of decoded data
            // returns: 1 on successf decode, 0 if not enough room
            //----------------------------------------------------------------------

            int a, b, c, d, z, x, index, cnt;
            int size = ilen;

            cnt = 0x20;

            z = 0;
            x = 0;
            b = 0;

            while (true)
            {

                if (cnt >= 0x8)
                {
                    while (size > 0 && cnt >= 8)
                    {
                        cnt -= 0x8;
                        size--;
                        a = input[z++] << cnt;
                        b |= a;
                    }
                }

                index = CharIndex[b >> 0x18];
                a = CharTable[index];
                d = (b >> (0x18 - a)) & BitMasks[a];
                c = CharTable[index + 2 * d + 2];

                cnt += (byte)c;
                if (cnt > 0x20)
                {
                    olen = osize - olen;
                    return true;
                }

                if (olen-- == 0)
                    return false;

                a = CharTable[index + 2 * d + 1];
                output[x++] = (byte)a;

                b <<= (c & 0xFF);

                return false;
            }
        }
    }

MyndFyre

I'm not sure I believe this is your code, for a couple reasons.


        public bool Compress(Byte[] input, Byte[] output)
        {
            return true;
        }

Gee, it doesn't work.  Big surprise there.


        //----------------------------------------------------------------------
        // GamePacketSize
        //   Calculates the size of a compressed game packet.
        //   
        // data: [in] pointer to received packet
        // size: [out] pointer to size
        // returns: the offset to the data.
        //----------------------------------------------------------------------

        byte GamePacketSize(byte[] data, int size, int offset)
        {
           int a;

           if (data[0] < 0xF0)
           {
               size = data[0] - 1;
               offset = 1;
               return data[1];
           }

           a = (data[0] & 0xF) << 8;
           size = a + data[1] - 2;
           offset = 2;
           return data[2];
        }
        #endregion

You said that the "size" parameter is an out/return value, but you haven't decorated it as such.

It's unclear what the "offset" parameter does.  In fact, it's unused.

The return value returns the third byte in the array, not an offset.  If you wanted to return an offset, you'd just put "return 2;" as the end line.

You also didn't decorate your Decompress method appropriately (for by-reference parameters).

Do you even know C#?
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

Fr3DBr

er i know c# the thing is im porting it from C++ and the pointers and unsafe stuff is making me get in panic... compress function isnt even DONE yet... no code for it right now.... just a return because the function returns a bool lol.... right now i want to make the decompression to work, but i need to fix the code... so i wanted some help because i got like stuck due to the pointers and references it used in the c++ code.

Fr3DBr

I already have my proxy done and working pretty well on C#



But since the packets are Compressed now i need to work on the decompressor....

Fr3DBr

Quote from: Fr3DBr on August 29, 2006, 04:54 PM
er i know c# the thing is im porting it from C++ (the code wasnt really mine, only the proxy im doing from scratch is hehehe.) and the pointers and unsafe stuff is making me get in panic... compress function isnt even DONE yet... no code for it right now.... just a return because the function returns a bool lol.... right now i want to make the decompression to work, but i need to fix the code... so i wanted some help because i got like stuck due to the pointers and references it used in the c++ code.

Fr3DBr

        public bool Decompress(Byte[] inputdata, int inputsize, Byte[] outputdata, int maxoutputsize, ref int outputsize)
        {
            try
            {
                int a, b, c, d, x, z;
                int maxcnt, index, cnt;
                int size;

                b = 0;
                x = 0;
                z = 0;

                size = inputsize;
                maxcnt = maxoutputsize;
                cnt = 0x20;

                while (true)
                {

                    if (cnt >= 0x8)
                    {
                        while (size > 0 && cnt >= 8)
                        {
                            cnt -= 0x8;
                            size--;
                            a = inputdata[x++] << cnt;
                            b |= a;
                        }
                    }

                    index = CharIndex[b >> 0x18];
                    a = CharTable[index];
                    d = (b >> (0x18 - a)) & BitMasks[a];
                    c = CharTable[index + 2 * d + 2];

                    cnt += c;

                    if (cnt > 0x20)
                    {
                        outputsize = maxoutputsize - maxcnt;
                        return true;
                    }

                    if (maxcnt-- == 0)
                        return false;

                    a = CharTable[index + 2 * d + 1];
                    outputdata[z++] = (Byte)a;

                    b <<= (c & 0xFF);
                }
            }
            catch (Exception ex)
            {
                GlobalVars.d.WriteLog2("Error : " + ex + Environment.NewLine);
                return false;
            }
        }
    }


My new attempt, still not working so good hehe...

Fr3DBr

Finished and Working, everyone that needs a C# Decompression Code Can now use this one ;)
The Credits Arent Just Mine Since i Just Ported it from a C Code... But we have something ;)


    public class D2GSCompression
    {
        #region [TABLES]

        //----------------------------------------------------------------------
        // Packet Decompression Tables
        //----------------------------------------------------------------------

        uint[] CharIndex = {
           0x0247, 0x0236, 0x0225, 0x0214, 0x0203, 0x01F2, 0x01E1, 0x01D0,
           0x01BF, 0x01AE, 0x019D, 0x018C, 0x017B, 0x016A, 0x0161, 0x0158,
           0x014F, 0x0146, 0x013D, 0x0134, 0x012B, 0x0122, 0x0119, 0x0110,
           0x0107, 0x00FE, 0x00F5, 0x00EC, 0x00E3, 0x00DA, 0x00D1, 0x00C8,
           0x00BF, 0x00B6, 0x00AD, 0x00A8, 0x00A3, 0x009E, 0x0099, 0x0094,
           0x008F, 0x008A, 0x0085, 0x0080, 0x007B, 0x0076, 0x0071, 0x006C,
           0x0069, 0x0066, 0x0063, 0x0060, 0x005D, 0x005A, 0x0057, 0x0054,
           0x0051, 0x004E, 0x004B, 0x0048, 0x0045, 0x0042, 0x003F, 0x003F,
           0x003C, 0x003C, 0x0039, 0x0039, 0x0036, 0x0036, 0x0033, 0x0033,
           0x0030, 0x0030, 0x002D, 0x002D, 0x002A, 0x002A, 0x0027, 0x0027,
           0x0024, 0x0024, 0x0021, 0x0021, 0x001E, 0x001E, 0x001B, 0x001B,
           0x0018, 0x0018, 0x0015, 0x0015, 0x0012, 0x0012, 0x0012, 0x0012,
           0x000F, 0x000F, 0x000F, 0x000F, 0x000C, 0x000C, 0x000C, 0x000C,
           0x0009, 0x0009, 0x0009, 0x0009, 0x0006, 0x0006, 0x0006, 0x0006,
           0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
           0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
           0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
        };


        Byte[] CharTable = {
           0x00,0x00,0x01,0x00,0x01,0x04,0x00,0xFF,0x06,0x00,0x14,0x06,
           0x00,0x13,0x06,0x00,0x05,0x06,0x00,0x02,0x06,0x00,0x80,0x07,
           0x00,0x6D,0x07,0x00,0x69,0x07,0x00,0x68,0x07,0x00,0x67,0x07,
           0x00,0x1E,0x07,0x00,0x15,0x07,0x00,0x12,0x07,0x00,0x0D,0x07,
           0x00,0x0A,0x07,0x00,0x08,0x07,0x00,0x07,0x07,0x00,0x06,0x07,
           0x00,0x04,0x07,0x00,0x03,0x07,0x00,0x6C,0x08,0x00,0x51,0x08,
           0x00,0x20,0x08,0x00,0x1F,0x08,0x00,0x1D,0x08,0x00,0x18,0x08,
           0x00,0x17,0x08,0x00,0x16,0x08,0x00,0x11,0x08,0x00,0x10,0x08,
           0x00,0x0F,0x08,0x00,0x0C,0x08,0x00,0x0B,0x08,0x00,0x09,0x08,
           0x01,0x96,0x09,0x97,0x09,0x01,0x90,0x09,0x95,0x09,0x01,0x64,
           0x09,0x6B,0x09,0x01,0x62,0x09,0x63,0x09,0x01,0x56,0x09,0x58,
           0x09,0x01,0x52,0x09,0x55,0x09,0x01,0x4D,0x09,0x50,0x09,0x01,
           0x45,0x09,0x4C,0x09,0x01,0x40,0x09,0x43,0x09,0x01,0x31,0x09,
           0x3B,0x09,0x01,0x28,0x09,0x30,0x09,0x01,0x1A,0x09,0x25,0x09,
           0x01,0x0E,0x09,0x19,0x09,0x02,0xE2,0x0A,0xE8,0x0A,0xF0,0x0A,
           0xF8,0x0A,0x02,0xC0,0x0A,0xC2,0x0A,0xCE,0x0A,0xE0,0x0A,0x02,
           0xA0,0x0A,0xA2,0x0A,0xB0,0x0A,0xB8,0x0A,0x02,0x8A,0x0A,0x8F,
           0x0A,0x93,0x0A,0x98,0x0A,0x02,0x81,0x0A,0x82,0x0A,0x83,0x0A,
           0x89,0x0A,0x02,0x7C,0x0A,0x7D,0x0A,0x7E,0x0A,0x7F,0x0A,0x02,
           0x77,0x0A,0x78,0x0A,0x79,0x0A,0x7A,0x0A,0x02,0x73,0x0A,0x74,
           0x0A,0x75,0x0A,0x76,0x0A,0x02,0x6E,0x0A,0x6F,0x0A,0x70,0x0A,
           0x72,0x0A,0x02,0x61,0x0A,0x65,0x0A,0x66,0x0A,0x6A,0x0A,0x02,
           0x5D,0x0A,0x5E,0x0A,0x5F,0x0A,0x60,0x0A,0x02,0x57,0x0A,0x59,
           0x0A,0x5A,0x0A,0x5B,0x0A,0x02,0x4A,0x0A,0x4B,0x0A,0x4E,0x0A,
           0x53,0x0A,0x02,0x46,0x0A,0x47,0x0A,0x48,0x0A,0x49,0x0A,0x02,
           0x3F,0x0A,0x41,0x0A,0x42,0x0A,0x44,0x0A,0x02,0x3A,0x0A,0x3C,
           0x0A,0x3D,0x0A,0x3E,0x0A,0x02,0x36,0x0A,0x37,0x0A,0x38,0x0A,
           0x39,0x0A,0x02,0x32,0x0A,0x33,0x0A,0x34,0x0A,0x35,0x0A,0x02,
           0x2B,0x0A,0x2C,0x0A,0x2D,0x0A,0x2E,0x0A,0x02,0x26,0x0A,0x27,
           0x0A,0x29,0x0A,0x2A,0x0A,0x02,0x21,0x0A,0x22,0x0A,0x23,0x0A,
           0x24,0x0A,0x03,0xFB,0x0B,0xFC,0x0B,0xFD,0x0B,0xFE,0x0B,0x1B,
           0x0A,0x1B,0x0A,0x1C,0x0A,0x1C,0x0A,0x03,0xF2,0x0B,0xF3,0x0B,
           0xF4,0x0B,0xF5,0x0B,0xF6,0x0B,0xF7,0x0B,0xF9,0x0B,0xFA,0x0B,
           0x03,0xE9,0x0B,0xEA,0x0B,0xEB,0x0B,0xEC,0x0B,0xED,0x0B,0xEE,
           0x0B,0xEF,0x0B,0xF1,0x0B,0x03,0xDE,0x0B,0xDF,0x0B,0xE1,0x0B,
           0xE3,0x0B,0xE4,0x0B,0xE5,0x0B,0xE6,0x0B,0xE7,0x0B,0x03,0xD6,
           0x0B,0xD7,0x0B,0xD8,0x0B,0xD9,0x0B,0xDA,0x0B,0xDB,0x0B,0xDC,
           0x0B,0xDD,0x0B,0x03,0xCD,0x0B,0xCF,0x0B,0xD0,0x0B,0xD1,0x0B,
           0xD2,0x0B,0xD3,0x0B,0xD4,0x0B,0xD5,0x0B,0x03,0xC5,0x0B,0xC6,
           0x0B,0xC7,0x0B,0xC8,0x0B,0xC9,0x0B,0xCA,0x0B,0xCB,0x0B,0xCC,
           0x0B,0x03,0xBB,0x0B,0xBC,0x0B,0xBD,0x0B,0xBE,0x0B,0xBF,0x0B,
           0xC1,0x0B,0xC3,0x0B,0xC4,0x0B,0x03,0xB2,0x0B,0xB3,0x0B,0xB4,
           0x0B,0xB5,0x0B,0xB6,0x0B,0xB7,0x0B,0xB9,0x0B,0xBA,0x0B,0x03,
           0xA9,0x0B,0xAA,0x0B,0xAB,0x0B,0xAC,0x0B,0xAD,0x0B,0xAE,0x0B,
           0xAF,0x0B,0xB1,0x0B,0x03,0x9F,0x0B,0xA1,0x0B,0xA3,0x0B,0xA4,
           0x0B,0xA5,0x0B,0xA6,0x0B,0xA7,0x0B,0xA8,0x0B,0x03,0x92,0x0B,
           0x94,0x0B,0x99,0x0B,0x9A,0x0B,0x9B,0x0B,0x9C,0x0B,0x9D,0x0B,
           0x9E,0x0B,0x03,0x86,0x0B,0x87,0x0B,0x88,0x0B,0x8B,0x0B,0x8C,
           0x0B,0x8D,0x0B,0x8E,0x0B,0x91,0x0B,0x03,0x2F,0x0B,0x4F,0x0B,
           0x54,0x0B,0x5C,0x0B,0x71,0x0B,0x7B,0x0B,0x84,0x0B,0x85,0x0B
        };

        uint[] BitMasks = {
           0x0000,0x0001,0x0003,0x0007,0x000F,0x001F,0x003F,0x007F,
           0x00FF,0x01FF,0x03FF,0x07FF,0x0FFF,0x1FFF,0x3FFF,0x7FFF
        };

        #endregion

        public bool Decompress(Byte[] inputdata, int inputsize, ref Byte[] outputdata, int maxoutputsize, ref int outputsize)
        {
            try
            {
                uint a, b, c, d, x, z;
                uint maxcnt, index, cnt, size;

                b = 0;
                x = 0;
                z = 0;

                size = (uint)inputsize;
                maxcnt = (uint)maxoutputsize;
                cnt = 0x20;

                while (true)
                {

                    if (cnt >= 0x8)
                    {
                        while (size > 0 && cnt >= 8)
                        {
                            cnt -= 0x8;
                            size--;
                            a = ((uint)inputdata[x++] << (int)cnt);
                            b |= a;
                        }
                    }

                    index = CharIndex[b >> 0x18];
                    a = CharTable[index];
                    d = ((uint)(b >> ((int)(0x18 - a)))) & BitMasks[a];
                    c = CharTable[index + 2 * d + 2];

                    cnt += c;

                    if (cnt > 0x20)
                    {
                        outputsize = ((int)(maxoutputsize - maxcnt));
                        return true;
                    }

                    if (maxcnt-- == 0)
                        return false;

                    outputdata[z++] = CharTable[index + 2 * d + 1];

                    b <<= ((int)(c & 0xFF));
                }
            }
            catch (Exception ex)
            {
                GlobalVars.d.WriteLog2("Error : " + ex + Environment.NewLine);
                return false;
            }
        }
    }