Example #1
0
        private PatchHeader DecodePatchHeader(BitPack bitpack)
        {
            PatchHeader header = new PatchHeader();

            // Quantized word bits
            header.QuantWBits = bitpack.UnpackBits(8);
            if (header.QuantWBits == END_OF_PATCHES)
            {
                return(header);
            }

            // DC offset
            header.DCOffset = bitpack.UnpackFloat();

            // Range
            header.Range = bitpack.UnpackBits(16);

            // Patch IDs (10 bits)
            header.PatchIDs = bitpack.UnpackBits(10);

            // Word bits
            header.WordBits = (uint)((header.QuantWBits & 0x0f) + 2);

            return(header);
        }
Example #2
0
        /// <summary>
        /// Add a patch of terrain to a BitPacker
        /// </summary>
        /// <param name="output">BitPacker to write the patch to</param>
        /// <param name="heightmap">Heightmap of the simulator, must be a 256 *
        /// 256 float array</param>
        /// <param name="x">X offset of the patch to create, valid values are
        /// from 0 to 15</param>
        /// <param name="y">Y offset of the patch to create, valid values are
        /// from 0 to 15</param>
        public void CreatePatch(BitPack output, float[] heightmap, int x, int y)
        {
            if (heightmap.Length != 256 * 256)
            {
                Logger.Log("Invalid heightmap value of " + heightmap.Length + " passed to CreatePatch()",
                           Helpers.LogLevel.Error, Client);
                return;
            }

            if (x < 0 || x > 15 || y < 0 || y > 15)
            {
                Logger.Log("Invalid x or y patch offset passed to CreatePatch(), x=" + x + ", y=" + y,
                           Helpers.LogLevel.Error, Client);
                return;
            }

            PatchHeader header = PrescanPatch(heightmap, x, y);

            header.QuantWBits = 136;
            header.PatchIDs   = (y & 0x1F);
            header.PatchIDs  += (x << 5);

            // TODO: What is prequant?
            int[] patch = CompressPatch(heightmap, x, y, header, 10);
            int   wbits = EncodePatchHeader(output, header, patch);

            // TODO: What is postquant?
            EncodePatch(output, patch, 0, wbits);
        }
Example #3
0
        private PatchHeader PrescanPatch(float[] heightmap, int patchX, int patchY)
        {
            PatchHeader header = new PatchHeader();
            float       zmax   = -99999999.0f;
            float       zmin   = 99999999.0f;

            for (int j = patchY * 16; j < (patchY + 1) * 16; j++)
            {
                for (int i = patchX * 16; i < (patchX + 1) * 16; i++)
                {
                    if (heightmap[j * 256 + i] > zmax)
                    {
                        zmax = heightmap[j * 256 + i];
                    }
                    if (heightmap[j * 256 + i] < zmin)
                    {
                        zmin = heightmap[j * 256 + i];
                    }
                }
            }

            header.DCOffset = zmin;
            header.Range    = (int)((zmax - zmin) + 1.0f);

            return(header);
        }
Example #4
0
        private static PatchHeader PrescanPatch(LayerPatch patch)
        {
            var   header = new PatchHeader();
            float zmax   = -99999999.0f;
            float zmin   = 99999999.0f;

            for (int y = 0; y < LAYER_PATCH_NUM_XY_ENTRIES; y++)
            {
                for (int x = 0; x < LAYER_PATCH_NUM_XY_ENTRIES; x++)
                {
                    float val = patch[x, y];
                    if (val > zmax)
                    {
                        zmax = val;
                    }
                    if (val < zmin)
                    {
                        zmin = val;
                    }
                }
            }

            header.DCOffset = zmin;
            header.Range    = (int)((zmax - zmin) + 1.0f);

            return(header);
        }
Example #5
0
    /// <summary>
    /// Decompresses all the patches in the given BitPack and assigns heights and normals to the surface.
    /// </summary>
    /// <param name="bitPack"></param>
    /// <param name="groupHeader"></param>
    /// <param name="isLargePatch"></param>
    public void DecompressPatches(BitPack bitPack, GroupHeader groupHeader, bool isLargePatch)
    {
        int j;
        int i;

        int[] patchData = new int[Patch.LARGE_PATCH_SIZE * Patch.LARGE_PATCH_SIZE]; // Large enough for a maximum sized patch

        Patch.InitPatchDecompressor(groupHeader.PatchSize);
        groupHeader.Stride = (UInt16)GridsPerEdge;
        Patch.SetGroupHeader(groupHeader);

        while (true)
        {
            PatchHeader patchHeader = new PatchHeader(bitPack);
            //Logger.LogDebug("Surface.DecompressPatches", $"{patchHeader} w={patchHeader.PatchIds >> 5} h={patchHeader.PatchIds & 0x1f} (PatchesPerEdge={PatchesPerEdge})");

            if (patchHeader.IsEnd)
            {
                break;
            }

            i = patchHeader.PatchIds >> 5;
            j = patchHeader.PatchIds & 0x1f;

            if ((i >= PatchesPerEdge) || (j >= PatchesPerEdge))
            {
                //Logger.LogWarning("Surface.DecompressPatches", $"Received invalid terrain packet - patch header patch ID incorrect! {i}x{j} DcOffset={patchHeader.DcOffset} Range={patchHeader.Range} QuantWBits={patchHeader.QuantWBits} PatchIds={patchHeader.PatchIds}");
                return;
            }

            SurfacePatch surfacePatch = PatchList[j * PatchesPerEdge + i];
            Patch.Decode(bitPack, groupHeader.PatchSize, (patchHeader.QuantWBits & 0xf) + 2, patchData);

            Patch.DeCompress(SurfaceZ, surfacePatch.DataZStart, patchData, patchHeader);

            // Update edges for neighbours.  Need to guarantee that this gets done before we generate vertical stats.
            surfacePatch.UpdateNorthEdge();
            surfacePatch.UpdateEastEdge();
            if (surfacePatch.GetNeighbourPatch(DirectionIndex.West) != null)
            {
                surfacePatch.GetNeighbourPatch(DirectionIndex.West).UpdateEastEdge();
            }
            if (surfacePatch.GetNeighbourPatch(DirectionIndex.SouthWest) != null)
            {
                surfacePatch.GetNeighbourPatch(DirectionIndex.SouthWest).UpdateEastEdge();
                surfacePatch.GetNeighbourPatch(DirectionIndex.SouthWest).UpdateNorthEdge();
            }
            if (surfacePatch.GetNeighbourPatch(DirectionIndex.South) != null)
            {
                surfacePatch.GetNeighbourPatch(DirectionIndex.South).UpdateNorthEdge();
            }

            //// Dirty patch statistics, and flag that the patch has data.
            surfacePatch.DirtyZ();
            surfacePatch.HasReceivedData = true;
            //break; //TODO: Only do the first patch for testing
        }
    }
Example #6
0
        private void DecompressLand(Simulator simulator, BitPack bitpack, GroupHeader group)
        {
            int x;
            int y;

            int[] patches = new int[32 * 32];
            int   count   = 0;

            while (true)
            {
                PatchHeader header = DecodePatchHeader(bitpack);

                if (header.QuantWBits == END_OF_PATCHES)
                {
                    break;
                }

                x = header.PatchIDs >> 5;
                y = header.PatchIDs & 0x1F;

                if (x >= PATCHES_PER_EDGE || y >= PATCHES_PER_EDGE)
                {
                    Logger.Log("Invalid LayerData land packet, x = " + x + ", y = " + y + ", dc_offset = " +
                               header.DCOffset + ", range = " + header.Range + ", quant_wbits = " + header.QuantWBits +
                               ", patchids = " + header.PatchIDs + ", count = " + count, Helpers.LogLevel.Warning, Client);
                    return;
                }

                // Decode this patch
                DecodePatch(patches, bitpack, header, group.PatchSize);

                // Decompress this patch
                float[] heightmap = DecompressPatch(patches, header, group);

                count++;

                if (OnLandPatch != null)
                {
                    try { OnLandPatch(simulator, x, y, group.PatchSize, heightmap); }
                    catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); }
                }

                if (Client.Settings.STORE_LAND_PATCHES)
                {
                    lock (SimPatches)
                    {
                        if (!SimPatches.ContainsKey(simulator.Handle))
                        {
                            SimPatches.Add(simulator.Handle, new Patch[16 * 16]);
                        }

                        SimPatches[simulator.Handle][y * 16 + x]           = new Patch();
                        SimPatches[simulator.Handle][y * 16 + x].Heightmap = heightmap;
                    }
                }
            }
        }
Example #7
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="output"></param>
        /// <param name="header"></param>
        /// <param name="patch"></param>
        /// <returns>wbits</returns>
        private int EncodePatchHeader(BitPack output, PatchHeader header, int[] patch)
        {
            int  temp;
            int  wbits    = (header.QuantWBits & 0x0f) + 2;
            uint maxWbits = (uint)wbits + 5;
            uint minWbits = ((uint)wbits >> 1);

            wbits = (int)minWbits;

            for (int i = 0; i < patch.Length; i++)
            {
                temp = patch[i];

                if (temp != 0)
                {
                    // Get the absolute value
                    if (temp < 0)
                    {
                        temp *= -1;
                    }

                    for (int j = (int)maxWbits; j > (int)minWbits; j--)
                    {
                        if ((temp & (1 << j)) != 0)
                        {
                            if (j > wbits)
                            {
                                wbits = j;
                            }
                            break;
                        }
                    }
                }
            }

            wbits += 1;

            header.QuantWBits &= 0xf0;

            if (wbits > 17 || wbits < 2)
            {
                Logger.Log("Bits needed per word in EncodePatchHeader() are outside the allowed range",
                           Helpers.LogLevel.Error, Client);
            }

            header.QuantWBits |= (wbits - 2);

            output.PackBits(header.QuantWBits, 8);
            output.PackFloat(header.DCOffset);
            output.PackBits(header.Range, 16);
            output.PackBits(header.PatchIDs, 10);

            return(wbits);
        }
Example #8
0
    public static void DeCompress(float[] dest, uint destOffset, int[] src, PatchHeader patchHeader)
    {
        {
            int i;
            int j;

            float[] block       = new float[LARGE_PATCH_SIZE * LARGE_PATCH_SIZE];
            int     tblockIndex = 0;

            int tpatchIndex;

            GroupHeader groupHeader = GroupHeader;
            int         size        = groupHeader.PatchSize;
            float       range       = patchHeader.Range;
            int         prequant    = (patchHeader.QuantWBits >> 4) + 2;
            int         quantize    = 1 << prequant;
            float       hmin        = patchHeader.DcOffset;
            int         stride      = groupHeader.Stride;

            float ooq               = 1f / (float)quantize;
            int   dqIndex           = 0;
            int   decopyMatrixIndex = 0;

            float mult   = ooq * range;
            float addval = mult * (float)(1 << (prequant - 1)) + hmin;

            for (i = 0; i < size * size; i++)
            {
                block[tblockIndex++] = src[DeCopyMatrix[decopyMatrixIndex++]] * PatchDequantizeTable[dqIndex++];
            }

            if (size == 16)
            {
                idct_patch(block);
            }
            else
            {
                idct_patch_large(block);
            }

            for (j = 0; j < size; j++)
            {
                tpatchIndex = j * stride;
                tblockIndex = j * size;
                for (i = 0; i < size; i++)
                {
                    dest[destOffset + tpatchIndex++] = block[tblockIndex++] * mult + addval;
                }
            }
        }
    }
Example #9
0
        private byte[] ApplyCopyPatch(ref PatchInfoHeader patchInfoHeader, ref PatchHeader patchHeader, uint patchLength, byte[] originalData)
        {
            if (patchLength != patchHeader.PatchedFileSize)
            {
                throw new InvalidDataException("CopyPatchInvalidSize");
            }

            var patchedData = patchLength == originalData.Length ? originalData : new byte[patchLength];

            if (Read(patchedData, 0, patchedData.Length) != patchedData.Length)
            {
                throw new EndOfStreamException();
            }

            return(patchedData);
        }
Example #10
0
        private void DecodePatch(int[] patches, BitPack bitpack, PatchHeader header, int size)
        {
            int temp;

            for (int n = 0; n < size * size; n++)
            {
                // ?
                temp = bitpack.UnpackBits(1);
                if (temp != 0)
                {
                    // Value or EOB
                    temp = bitpack.UnpackBits(1);
                    if (temp != 0)
                    {
                        // Value
                        temp = bitpack.UnpackBits(1);
                        if (temp != 0)
                        {
                            // Negative
                            temp       = bitpack.UnpackBits((int)header.WordBits);
                            patches[n] = temp * -1;
                        }
                        else
                        {
                            // Positive
                            temp       = bitpack.UnpackBits((int)header.WordBits);
                            patches[n] = temp;
                        }
                    }
                    else
                    {
                        // Set the rest to zero
                        // TODO: This might not be necessary
                        for (int o = n; o < size * size; o++)
                        {
                            patches[o] = 0;
                        }
                        break;
                    }
                }
                else
                {
                    patches[n] = 0;
                }
            }
        }
Example #11
0
        private float[] DecompressPatch(int[] patches, PatchHeader header, GroupHeader group)
        {
            float[] block    = new float[group.PatchSize * group.PatchSize];
            float[] output   = new float[group.PatchSize * group.PatchSize];
            int     prequant = (header.QuantWBits >> 4) + 2;
            int     quantize = 1 << prequant;
            float   ooq      = 1.0f / (float)quantize;
            float   mult     = ooq * (float)header.Range;
            float   addval   = mult * (float)(1 << (prequant - 1)) + header.DCOffset;

            if (group.PatchSize == 16)
            {
                for (int n = 0; n < 16 * 16; n++)
                {
                    block[n] = patches[CopyMatrix16[n]] * DequantizeTable16[n];
                }

                float[] ftemp = new float[16 * 16];

                for (int o = 0; o < 16; o++)
                {
                    IDCTColumn16(block, ftemp, o);
                }
                for (int o = 0; o < 16; o++)
                {
                    IDCTLine16(ftemp, block, o);
                }
            }
            else
            {
                for (int n = 0; n < 32 * 32; n++)
                {
                    block[n] = patches[CopyMatrix32[n]] * DequantizeTable32[n];
                }

                Logger.Log("Implement IDCTPatchLarge", Helpers.LogLevel.Error, Client);
            }

            for (int j = 0; j < block.Length; j++)
            {
                output[j] = block[j] * mult + addval;
            }

            return(output);
        }
Example #12
0
        private int[] CompressPatch(float[] heightmap, int patchX, int patchY, PatchHeader header, int prequant)
        {
            float[] block    = new float[16 * 16];
            int     wordsize = prequant;
            float   oozrange = 1.0f / (float)header.Range;
            float   range    = (float)(1 << prequant);
            float   premult  = oozrange * range;
            float   sub      = (float)(1 << (prequant - 1)) + header.DCOffset * premult;

            header.QuantWBits  = wordsize - 2;
            header.QuantWBits |= (prequant - 2) << 4;

            int k = 0;

            for (int j = patchY * 16; j < (patchY + 1) * 16; j++)
            {
                for (int i = patchX * 16; i < (patchX + 1) * 16; i++)
                {
                    block[k++] = heightmap[j * 256 + i] * premult - sub;
                }
            }

            float[] ftemp = new float[16 * 16];
            int[]   itemp = new int[16 * 16];

            for (int o = 0; o < 16; o++)
            {
                DCTLine16(block, ftemp, o);
            }
            for (int o = 0; o < 16; o++)
            {
                DCTColumn16(ftemp, itemp, o);
            }

            return(itemp);
        }
Example #13
0
        private static int[] CompressPatch(LayerPatch patchData, PatchHeader header, int prequant)
        {
            var   block    = new float[LAYER_PATCH_NUM_XY_ENTRIES * LAYER_PATCH_NUM_XY_ENTRIES];
            int   wordsize = prequant;
            float oozrange = 1.0f / (float)header.Range;
            var   range    = (float)(1 << prequant);
            float premult  = oozrange * range;
            float sub      = (1 << (prequant - 1)) + header.DCOffset * premult;

            header.QuantWBits  = wordsize - 2;
            header.QuantWBits |= (prequant - 2) << 4;

            int k = 0;

            for (int y = 0; y < LAYER_PATCH_NUM_XY_ENTRIES; y++)
            {
                for (int x = 0; x < LAYER_PATCH_NUM_XY_ENTRIES; x++)
                {
                    block[k++] = patchData[x, y] * premult - sub;
                }
            }

            var ftemp = new float[LAYER_PATCH_NUM_XY_ENTRIES * LAYER_PATCH_NUM_XY_ENTRIES];
            var itemp = new int[LAYER_PATCH_NUM_XY_ENTRIES * LAYER_PATCH_NUM_XY_ENTRIES];

            for (int o = 0; o < LAYER_PATCH_NUM_XY_ENTRIES; o++)
            {
                DCTLine16(block, ftemp, o);
            }
            for (int o = 0; o < LAYER_PATCH_NUM_XY_ENTRIES; o++)
            {
                DCTColumn16(ftemp, itemp, o);
            }

            return(itemp);
        }
 private void DecodePatch(int[] patches, BitPack bitpack, PatchHeader header, int size)
 {
     int temp;
     for (int n = 0; n < size * size; n++)
     {
         // ?
         temp = bitpack.UnpackBits(1);
         if (temp != 0)
         {
             // Value or EOB
             temp = bitpack.UnpackBits(1);
             if (temp != 0)
             {
                 // Value
                 temp = bitpack.UnpackBits(1);
                 if (temp != 0)
                 {
                     // Negative
                     temp = bitpack.UnpackBits((int)header.WordBits);
                     patches[n] = temp * -1;
                 }
                 else
                 {
                     // Positive
                     temp = bitpack.UnpackBits((int)header.WordBits);
                     patches[n] = temp;
                 }
             }
             else
             {
                 // Set the rest to zero
                 // TODO: This might not be necessary
                 for (int o = n; o < size * size; o++)
                 {
                     patches[o] = 0;
                 }
                 break;
             }
         }
         else
         {
             patches[n] = 0;
         }
     }
 }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="output"></param>
        /// <param name="header"></param>
        /// <param name="patch"></param>
        /// <returns>wbits</returns>
        private int EncodePatchHeader(BitPack output, PatchHeader header, int[] patch)
        {
            int temp;
            int wbits = (header.QuantWBits & 0x0f) + 2;
            uint maxWbits = (uint)wbits + 5;
            uint minWbits = ((uint)wbits >> 1);

            wbits = (int)minWbits;

            for (int i = 0; i < patch.Length; i++)
            {
                temp = patch[i];

                if (temp != 0)
                {
                    // Get the absolute value
                    if (temp < 0) temp *= -1;

                    for (int j = (int)maxWbits; j > (int)minWbits; j--)
                    {
                        if ((temp & (1 << j)) != 0)
                        {
                            if (j > wbits) wbits = j;
                            break;
                        }
                    }
                }
            }

            wbits += 1;

            header.QuantWBits &= 0xf0;

            if (wbits > 17 || wbits < 2)
            {
                Logger.Log("Bits needed per word in EncodePatchHeader() are outside the allowed range", 
                    Helpers.LogLevel.Error, Client);
            }

            header.QuantWBits |= (wbits - 2);

            output.PackBits(header.QuantWBits, 8);
            output.PackFloat(header.DCOffset);
            output.PackBits(header.Range, 16);
            output.PackBits(header.PatchIDs, 10);

            return wbits;
        }
        private PatchHeader DecodePatchHeader(BitPack bitpack)
        {
            PatchHeader header = new PatchHeader();

            // Quantized word bits
            header.QuantWBits = bitpack.UnpackBits(8);
            if (header.QuantWBits == END_OF_PATCHES)
                return header;

            // DC offset
            header.DCOffset = bitpack.UnpackFloat();

            // Range
            header.Range = bitpack.UnpackBits(16);

            // Patch IDs (10 bits)
            header.PatchIDs = bitpack.UnpackBits(10);

            // Word bits
            header.WordBits = (uint)((header.QuantWBits & 0x0f) + 2);

            return header;
        }
        private PatchHeader PrescanPatch(float[] heightmap, int patchX, int patchY)
        {
            PatchHeader header = new PatchHeader();
            float zmax = -99999999.0f;
            float zmin = 99999999.0f;

            for (int j = patchY * 16; j < (patchY + 1) * 16; j++)
            {
                for (int i = patchX * 16; i < (patchX + 1) * 16; i++)
                {
                    if (heightmap[j * 256 + i] > zmax) zmax = heightmap[j * 256 + i];
                    if (heightmap[j * 256 + i] < zmin) zmin = heightmap[j * 256 + i];
                }
            }

            header.DCOffset = zmin;
            header.Range = (int)((zmax - zmin) + 1.0f);

            return header;
        }
Example #18
0
        private unsafe byte[] ApplyBsd0Patch(ref PatchInfoHeader patchInfoHeader, ref PatchHeader patchHeader, uint patchLength, byte[] originalData)
        {
            byte[] patchData;

            if (patchLength < patchHeader.PatchLength)
            {
                patchData = UnpackRle();
            }
            else
            {
                patchData = new byte[patchLength];
                if (Read(patchData, 0, checked ((int)patchLength)) != patchLength)
                {
                    throw new EndOfStreamException();
                }
            }

            fixed(byte *patchDataPointer = patchData)
            {
                var bsdiffHeader = (PatchBsdiff40Header *)patchDataPointer;

                if (!BitConverter.IsLittleEndian)
                {
                    CommonMethods.SwapBytes((ulong *)patchDataPointer, sizeof(PatchBsdiff40Header) >> 3);
                }

                if (bsdiffHeader->Signature != 0x3034464649445342 /* 'BSDIFF40' */)
                {
                    throw new InvalidDataException(ErrorMessages.GetString("Bsd0PatchHeaderInvalidSignature"));
                }

                var controlBlock    = (uint *)(patchDataPointer + sizeof(PatchBsdiff40Header));
                var differenceBlock = (byte *)controlBlock + bsdiffHeader->ControlBlockLength;
                var extraBlock      = differenceBlock + bsdiffHeader->DifferenceBlockLength;

                if (!BitConverter.IsLittleEndian)
                {
                    CommonMethods.SwapBytes(controlBlock, bsdiffHeader->ControlBlockLength >> 2);
                }

                var patchBuffer = new byte[bsdiffHeader->PatchedFileSize];

                fixed(byte *originalDataPointer = originalData)
                fixed(byte *patchBufferPointer = patchBuffer)
                {
                    var sourcePointer      = originalDataPointer;
                    var destinationPointer = patchBufferPointer;
                    int sourceCount        = originalData.Length;
                    int destinationCount   = patchBuffer.Length;

                    while (destinationCount != 0)
                    {
                        uint differenceLength = *controlBlock++;
                        uint extraLength      = *controlBlock++;
                        uint sourceOffset     = *controlBlock++;

                        if (differenceLength > destinationCount)
                        {
                            throw new InvalidDataException(ErrorMessages.GetString("Bsd0PatchInvalidData"));
                        }
                        destinationCount = (int)(destinationCount - differenceLength);

                        // Apply the difference patch (Patched Data = Original data + Difference data)
                        for (; differenceLength-- != 0; destinationPointer++, sourcePointer++)
                        {
                            *destinationPointer = *differenceBlock++;
                            if (sourceCount > 0)
                            {
                                *destinationPointer += *sourcePointer;
                            }
                        }

                        if (extraLength > destinationCount)
                        {
                            throw new InvalidDataException(ErrorMessages.GetString("Bsd0PatchInvalidData"));
                        }
                        destinationCount = (int)(destinationCount - extraLength);

                        // Apply the extra data patch (New data)
                        for (; extraLength-- != 0;)
                        {
                            *destinationPointer++ = *extraBlock++;
                        }

                        sourcePointer += (sourceOffset & 0x80000000) != 0 ? unchecked ((int)(0x80000000 - sourceOffset)) : (int)sourceOffset;
                    }
                }

                return(patchBuffer);
            }
        }
Example #19
0
        private unsafe byte[] ApplyBsd0Patch(ref PatchInfoHeader patchInfoHeader, ref PatchHeader patchHeader, uint patchLength, byte[] originalData)
        {
            byte[] patchData;

            if (patchLength < patchHeader.PatchLength)
            {
                patchData = UnpackRle(patchLength);
            }
            else
            {
                patchData = new byte[patchLength];
                if (Read(patchData, 0, checked ((int)patchLength)) != patchLength)
                {
                    throw new EndOfStreamException();
                }
            }

            fixed(byte *patchDataPointer = patchData)
            {
                var bsdiffHeader = (PatchBsdiff40Header *)patchDataPointer;

                if (!BitConverter.IsLittleEndian)
                {
                    CommonMethods.SwapBytes((ulong *)patchDataPointer, sizeof(PatchBsdiff40Header) / sizeof(ulong));
                }

                if (bsdiffHeader->Signature != 0x3034464649445342 /* 'BSDIFF40' */)
                {
                    throw new InvalidDataException(ErrorMessages.GetString("Bsd0PatchHeaderInvalidSignature"));
                }

                var controlBlock    = (uint *)(patchDataPointer + sizeof(PatchBsdiff40Header));
                var differenceBlock = (byte *)controlBlock + bsdiffHeader->ControlBlockLength;
                var extraBlock      = differenceBlock + bsdiffHeader->DifferenceBlockLength;

                if (!BitConverter.IsLittleEndian)
                {
                    CommonMethods.SwapBytes(controlBlock, bsdiffHeader->ControlBlockLength / sizeof(uint));
                }

                var patchedBuffer = new byte[bsdiffHeader->PatchedFileSize];

                uint o = 0;
                uint n = 0;

                try
                {
                    while (n < patchedBuffer.Length)
                    {
                        uint differenceLength = *controlBlock++;
                        uint extraLength      = *controlBlock++;
                        uint sourceOffset     = *controlBlock++;

                        // Apply the difference patch (Patched Data = Original data + Difference data)
                        for (uint i = 0; i < differenceLength; i++, n++, o++)
                        {
                            patchedBuffer[n] = differenceBlock[i];
                            if (o < originalData.Length)
                            {
                                patchedBuffer[n] += originalData[o];
                            }
                        }
                        differenceBlock += differenceLength;

                        // Apply the extra data patch (New data)
                        for (int e = 0; e < extraLength; e++)
                        {
                            patchedBuffer[n++] = extraBlock[e];
                        }
                        extraBlock += extraLength;

                        unchecked
                        {
                            o += (sourceOffset & 0x80000000) != 0 ? (0x80000000 - sourceOffset) : sourceOffset;
                        }
                    }
                }
                catch (IndexOutOfRangeException ex)
                {
                    throw new InvalidDataException(ErrorMessages.GetString("Bsd0PatchInvalidData"), ex);
                }

                return(patchedBuffer);
            }
        }
Example #20
0
        private static int EncodePatchHeader(BitPacker output, PatchHeader header, int[] patch, bool extended)
        {
            int  temp;
            int  wbits    = (header.QuantWBits & 0x0f) + 2;
            uint maxWbits = (uint)wbits + 5;
            uint minWbits = (uint)wbits >> 1;

            wbits = (int)minWbits;

            for (int i = 0; i < patch.Length; i++)
            {
                temp = patch[i];

                if (temp != 0)
                {
                    // Get the absolute value
                    if (temp < 0)
                    {
                        temp *= -1;
                    }

                    for (int j = (int)maxWbits; j > (int)minWbits; j--)
                    {
                        if ((temp & (1 << j)) != 0)
                        {
                            if (j > wbits)
                            {
                                wbits = j;
                            }
                            break;
                        }
                    }
                }
            }

            wbits++;

            if (wbits > 17)
            {
                wbits = 17;
            }
            else if (wbits < 2)
            {
                wbits = 2;
            }

            header.QuantWBits &= 0xf0;

            header.QuantWBits |= wbits - 2;

            output.PackBits(header.QuantWBits, 8);
            output.FloatValue = header.DCOffset;

            output.PackBits(header.Range, 16);
            if (extended)
            {
                output.PackBits(header.PatchIDs, 32);
            }
            else
            {
                output.PackBits(header.PatchIDs, 10);
            }

            /* Bit Length of Header in VarRegion format: 56 bits => 7 Bytes */

            return(wbits);
        }
        private float[] DecompressPatch(int[] patches, PatchHeader header, GroupHeader group)
        {
            float[] block = new float[group.PatchSize * group.PatchSize];
            float[] output = new float[group.PatchSize * group.PatchSize];
            int prequant = (header.QuantWBits >> 4) + 2;
            int quantize = 1 << prequant;
            float ooq = 1.0f / (float)quantize;
            float mult = ooq * (float)header.Range;
            float addval = mult * (float)(1 << (prequant - 1)) + header.DCOffset;

            if (group.PatchSize == 16)
            {
                for (int n = 0; n < 16 * 16; n++)
                {
                    block[n] = patches[CopyMatrix16[n]] * DequantizeTable16[n];
                }

                float[] ftemp = new float[16 * 16];

                for (int o = 0; o < 16; o++)
                    IDCTColumn16(block, ftemp, o);
                for (int o = 0; o < 16; o++)
                    IDCTLine16(ftemp, block, o);
            }
            else
            {
                for (int n = 0; n < 32 * 32; n++)
                {
                    block[n] = patches[CopyMatrix32[n]] * DequantizeTable32[n];
                }

                Logger.Log("Implement IDCTPatchLarge", Helpers.LogLevel.Error, Client);
            }

            for (int j = 0; j < block.Length; j++)
            {
                output[j] = block[j] * mult + addval;
            }

            return output;
        }
Example #22
0
        private byte[] ApplyCopyPatch(ref PatchInfoHeader patchInfoHeader, ref PatchHeader patchHeader, uint patchLength, byte[] originalData)
        {
            if (patchLength != patchHeader.PatchedFileSize) throw new InvalidDataException("CopyPatchInvalidSize");

            var patchedData = patchLength == originalData.Length ? originalData : new byte[patchLength];

            if (Read(patchedData, 0, patchedData.Length) != patchedData.Length) throw new EndOfStreamException();

            return patchedData;
        }
        private int[] CompressPatch(float[] heightmap, int patchX, int patchY, PatchHeader header, int prequant)
        {
            float[] block = new float[16 * 16];
            int wordsize = prequant;
            float oozrange = 1.0f / (float)header.Range;
            float range = (float)(1 << prequant);
            float premult = oozrange * range;
            float sub = (float)(1 << (prequant - 1)) + header.DCOffset * premult;

            header.QuantWBits = wordsize - 2;
            header.QuantWBits |= (prequant - 2) << 4;

            int k = 0;
            for (int j = patchY * 16; j < (patchY + 1) * 16; j++)
            {
                for (int i = patchX * 16; i < (patchX + 1) * 16; i++)
                {
                    block[k++] = heightmap[j * 256 + i] * premult - sub;
                }
            }

            float[] ftemp = new float[16 * 16];
            int[] itemp = new int[16 * 16];

            for (int o = 0; o < 16; o++)
                DCTLine16(block, ftemp, o);
            for (int o = 0; o < 16; o++)
                DCTColumn16(ftemp, itemp, o);

            return itemp;
        }
Example #24
0
        private unsafe byte[] ApplyBsd0Patch(ref PatchInfoHeader patchInfoHeader, ref PatchHeader patchHeader, uint patchLength, byte[] originalData)
        {
            byte[] patchData;

            if (patchLength < patchHeader.PatchLength) patchData = UnpackRle(patchLength);
            else
            {
                patchData = new byte[patchLength];
                if (Read(patchData, 0, checked((int)patchLength)) != patchLength) throw new EndOfStreamException();
            }

            fixed (byte* patchDataPointer = patchData)
            {
                var bsdiffHeader = (PatchBsdiff40Header*)patchDataPointer;

                if (!BitConverter.IsLittleEndian) CommonMethods.SwapBytes((ulong*)patchDataPointer, sizeof(PatchBsdiff40Header)/sizeof(ulong));

                if (bsdiffHeader->Signature != 0x3034464649445342 /* 'BSDIFF40' */) throw new InvalidDataException(ErrorMessages.GetString("Bsd0PatchHeaderInvalidSignature"));

                var controlBlock = (uint*)(patchDataPointer + sizeof(PatchBsdiff40Header));
                var differenceBlock = (byte*)controlBlock + bsdiffHeader->ControlBlockLength;
                var extraBlock = differenceBlock + bsdiffHeader->DifferenceBlockLength;

                if (!BitConverter.IsLittleEndian) CommonMethods.SwapBytes(controlBlock, bsdiffHeader->ControlBlockLength/sizeof(uint));

                var patchedBuffer = new byte[bsdiffHeader->PatchedFileSize];

                uint o = 0;
                uint n = 0;
                try
                {
                    while (n < patchedBuffer.Length)
                    {
                        uint differenceLength = *controlBlock++;
                        uint extraLength = *controlBlock++;
                        uint sourceOffset = *controlBlock++;

                        // Apply the difference patch (Patched Data = Original data + Difference data)
                        for (uint i = 0; i < differenceLength; i++, n++, o++)
                        {
                            patchedBuffer[n] = differenceBlock[i];
                            if (o < originalData.Length)
                                patchedBuffer[n] += originalData[o];
                        }
                        differenceBlock += differenceLength;

                        // Apply the extra data patch (New data)
                        for (int e = 0; e < extraLength; e++)
                            patchedBuffer[n++] = extraBlock[e];
                        extraBlock += extraLength;

                        unchecked
                        {
                            o += (sourceOffset & 0x80000000) != 0 ? (0x80000000 - sourceOffset) : sourceOffset;
                        }
                    }
                }
                catch (IndexOutOfRangeException ex)
                {
                    throw new InvalidDataException(ErrorMessages.GetString("Bsd0PatchInvalidData"), ex);
                }

                return patchedBuffer;
            }
        }