public static void Create(byte[] oldData, byte[] newData, Stream output)
        {
            if (oldData == null)
            {
                throw new ArgumentNullException("oldData");
            }
            if (newData == null)
            {
                throw new ArgumentNullException("newData");
            }
            if (output == null)
            {
                throw new ArgumentNullException("output");
            }
            if (!output.get_CanSeek())
            {
                throw new ArgumentException("Output stream must be seekable.", "output");
            }
            if (!output.get_CanWrite())
            {
                throw new ArgumentException("Output stream must be writable.", "output");
            }
            byte[] array = new byte[32];
            BinaryPatchUtility.WriteInt64(3473478480300364610L, array, 0);
            BinaryPatchUtility.WriteInt64(0L, array, 8);
            BinaryPatchUtility.WriteInt64(0L, array, 16);
            BinaryPatchUtility.WriteInt64((long)newData.Length, array, 24);
            long position = output.get_Position();

            output.Write(array, 0, array.Length);
            int[]             i                 = BinaryPatchUtility.SuffixSort(oldData);
            byte[]            array2            = new byte[newData.Length];
            byte[]            array3            = new byte[newData.Length];
            int               num               = 0;
            int               num2              = 0;
            BZip2OutputStream bZip2OutputStream = new BZip2OutputStream(output);

            bZip2OutputStream.set_IsStreamOwner(false);
            using (BZip2OutputStream bZip2OutputStream2 = bZip2OutputStream)
            {
                int j    = 0;
                int num3 = 0;
                int num4 = 0;
                int num5 = 0;
                int num6 = 0;
                int num7 = 0;
                while (j < newData.Length)
                {
                    int num8 = 0;
                    int k;
                    for (j = (k = j + num4); j < newData.Length; j++)
                    {
                        num4 = BinaryPatchUtility.Search(i, oldData, newData, j, 0, oldData.Length, out num3);
                        while (k < j + num4)
                        {
                            if (k + num7 < oldData.Length && oldData[k + num7] == newData[k])
                            {
                                num8++;
                            }
                            k++;
                        }
                        if ((num4 == num8 && num4 != 0) || num4 > num8 + 8)
                        {
                            break;
                        }
                        if (j + num7 < oldData.Length && oldData[j + num7] == newData[j])
                        {
                            num8--;
                        }
                    }
                    if (num4 != num8 || j == newData.Length)
                    {
                        int num9  = 0;
                        int num10 = 0;
                        int num11 = 0;
                        int num12 = 0;
                        while (num5 + num12 < j && num6 + num12 < oldData.Length)
                        {
                            if (oldData[num6 + num12] == newData[num5 + num12])
                            {
                                num9++;
                            }
                            num12++;
                            if (num9 * 2 - num12 > num10 * 2 - num11)
                            {
                                num10 = num9;
                                num11 = num12;
                            }
                        }
                        int num13 = 0;
                        if (j < newData.Length)
                        {
                            num9 = 0;
                            int num14 = 0;
                            int num15 = 1;
                            while (j >= num5 + num15 && num3 >= num15)
                            {
                                if (oldData[num3 - num15] == newData[j - num15])
                                {
                                    num9++;
                                }
                                if (num9 * 2 - num15 > num14 * 2 - num13)
                                {
                                    num14 = num9;
                                    num13 = num15;
                                }
                                num15++;
                            }
                        }
                        if (num5 + num11 > j - num13)
                        {
                            int num16 = num5 + num11 - (j - num13);
                            num9 = 0;
                            int num17 = 0;
                            int num18 = 0;
                            for (int l = 0; l < num16; l++)
                            {
                                if (newData[num5 + num11 - num16 + l] == oldData[num6 + num11 - num16 + l])
                                {
                                    num9++;
                                }
                                if (newData[j - num13 + l] == oldData[num3 - num13 + l])
                                {
                                    num9--;
                                }
                                if (num9 > num17)
                                {
                                    num17 = num9;
                                    num18 = l + 1;
                                }
                            }
                            num11 += num18 - num16;
                            num13 -= num18;
                        }
                        for (int m = 0; m < num11; m++)
                        {
                            array2[num + m] = newData[num5 + m] - oldData[num6 + m];
                        }
                        for (int n = 0; n < j - num13 - (num5 + num11); n++)
                        {
                            array3[num2 + n] = newData[num5 + num11 + n];
                        }
                        num  += num11;
                        num2 += j - num13 - (num5 + num11);
                        byte[] array4 = new byte[8];
                        BinaryPatchUtility.WriteInt64((long)num11, array4, 0);
                        bZip2OutputStream2.Write(array4, 0, 8);
                        BinaryPatchUtility.WriteInt64((long)(j - num13 - (num5 + num11)), array4, 0);
                        bZip2OutputStream2.Write(array4, 0, 8);
                        BinaryPatchUtility.WriteInt64((long)(num3 - num13 - (num6 + num11)), array4, 0);
                        bZip2OutputStream2.Write(array4, 0, 8);
                        num5 = j - num13;
                        num6 = num3 - num13;
                        num7 = num3 - j;
                    }
                }
            }
            long position2 = output.get_Position();

            BinaryPatchUtility.WriteInt64(position2 - position - 32L, array, 8);
            bZip2OutputStream = new BZip2OutputStream(output);
            bZip2OutputStream.set_IsStreamOwner(false);
            using (BZip2OutputStream bZip2OutputStream3 = bZip2OutputStream)
            {
                bZip2OutputStream3.Write(array2, 0, num);
            }
            long position3 = output.get_Position();

            BinaryPatchUtility.WriteInt64(position3 - position2, array, 16);
            bZip2OutputStream = new BZip2OutputStream(output);
            bZip2OutputStream.set_IsStreamOwner(false);
            using (BZip2OutputStream bZip2OutputStream4 = bZip2OutputStream)
            {
                bZip2OutputStream4.Write(array3, 0, num2);
            }
            long position4 = output.get_Position();

            output.set_Position(position);
            output.Write(array, 0, array.Length);
            output.set_Position(position4);
        }