Exemplo n.º 1
0
        private void loadTOCfile(string path)
        {
            
            FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read);
            int memsize = (int)fileStream.Length;
            memory = new byte[memsize];
            int count;
            int sum = 0;
            while ((count = fileStream.Read(memory, sum, memsize - sum)) > 0) sum += count;
            fileStream.Close();
            if (memsize > 0)
            {
                content = new List<Inventory>();
                Inventory temp = new Inventory();
                MemoryStream myStream = new MemoryStream(memory);
                if (myStream.ReadValueU32() == 0x3AB70C13)
                {
                    myStream.Seek(8, SeekOrigin.Begin);
                    uint jumpSize = myStream.ReadValueU32();
                    myStream.Seek(jumpSize * 8, SeekOrigin.Current);
                    uint blockSize;
                    do
                    {
                        temp = new Inventory();
                        long position = myStream.Position;
                        uint value = myStream.ReadValueU32();
                        blockSize = value & 0xFFFF;
                        uint offset = (uint)myStream.Position;
                        uint fileSize = myStream.ReadValueU32();
                        myStream.Seek(20, SeekOrigin.Current);


                        string filePath = myStream.ReadStringZ();

                        myStream.Seek(position + blockSize, SeekOrigin.Begin);

                        temp.name = filePath;
                        temp.offset = offset;
                        temp.size = fileSize;
                        content.Add(temp);

                    } while (blockSize != 0);
                }
                myStream.Close();
            }
        }
Exemplo n.º 2
0
        public GameHeader(MemoryStream stream)
        {
            var Length = stream.ReadValueU32(false);
            var opCode = stream.ReadValueU8();
            var Flags = stream.ReadValueU8();

            this.SetData(Length, opCode, Flags);
        }
Exemplo n.º 3
0
        public TextureGroup(PCCObject pccObj, byte[] data)
        {
            enumTextureGroups = new List<ByteProp>();
            pccRef = pccObj;

            MemoryStream buffer = new MemoryStream(data);

            firstVal = buffer.ReadValueU32();
            buffer.Seek(16, SeekOrigin.Begin);
            otherVal = buffer.ReadValueU32();

            int numEnums = buffer.ReadValueS32();
            for (int i = 0; i < numEnums; i++)
            {
                ByteProp aux = new ByteProp(pccRef.Names[buffer.ReadValueS32()], buffer.ReadValueS32());
                enumTextureGroups.Add(aux);
            }
        }
Exemplo n.º 4
0
        private bnet.protocol.storage.ExecuteResponse GetHeroDigest(IClient client, bnet.protocol.storage.ExecuteRequest request)
        {
            var results = new List<bnet.protocol.storage.OperationResult>();

            foreach(var operation in request.OperationsList)
            {
                // find the requested toons entity-id.
                var stream = new MemoryStream(operation.RowId.Hash.ToByteArray());
                
                // contains ToonHandle in field form with one unknown field (which is not in message definition):
                // int16 unknown; uint8 realm; uint8 region; uint32 program; uint64 id;
                stream.ReadValueU16(); // unknown
                stream.ReadValueU8(); // realm
                stream.ReadValueU8(); // region 
                stream.ReadValueU32(false); // program
                    
                var toonId=stream.ReadValueU64(false);

                if(!client.Account.Toons.ContainsKey(toonId))
                {
                    Logger.Error("Can't find the requested toon: " + toonId);
                    continue;
                }

                var toon = client.Account.Toons[toonId];                    
                var operationResult = bnet.protocol.storage.OperationResult.CreateBuilder().SetTableId(operation.TableId);
                operationResult.AddData(
                    bnet.protocol.storage.Cell.CreateBuilder()
                        .SetColumnId(request.OperationsList[0].ColumnId)
                        .SetRowId(request.OperationsList[0].RowId)
                        .SetVersion(1)
                        .SetData(toon.Digest.ToByteString())
                        .Build()
                    );
                results.Add(operationResult.Build());
            }

            var builder = bnet.protocol.storage.ExecuteResponse.CreateBuilder();            
            foreach(var result in results)
            {
                builder.AddResults(result);
            }            
            return builder.Build();
        }
Exemplo n.º 5
0
        public ME3SaltTexture2D(ME3PCCObject pccObj, int texIdx, String pathBioGame, uint hash = 0)
        {
            allPccs = new List<string>();
            hasChanged = false;
            Hash = hash;

            if (pccObj.isExport(texIdx) && (pccObj.Exports[texIdx].ClassName == className || pccObj.Exports[texIdx].ClassName == class2 || pccObj.Exports[texIdx].ClassName == class3))
            {
                Class = pccObj.Exports[texIdx].ClassName;
                ME3ExportEntry expEntry = pccObj.Exports[texIdx];
                properties = new Dictionary<string, SaltPropertyReader.Property>();
                byte[] rawData = (byte[])expEntry.Data.Clone();
                int propertiesOffset = SaltPropertyReader.detectStart(pccObj, rawData);
                headerData = new byte[propertiesOffset];
                Buffer.BlockCopy(rawData, 0, headerData, 0, propertiesOffset);
                pccOffset = expEntry.DataOffset;
                List<SaltPropertyReader.Property> tempProperties = SaltPropertyReader.getPropList(pccObj, rawData);
                texName = expEntry.ObjectName;
                for (int i = 0; i < tempProperties.Count; i++)
                {
                    SaltPropertyReader.Property property = tempProperties[i];
                    if (property.Name == "UnpackMin")
                        UnpackNum++;

                    if (!properties.ContainsKey(property.Name))
                        properties.Add(property.Name, property);

                    switch (property.Name)
                    {
                        case "Format":
                            texFormat = Textures.Methods.ParseFormat(pccObj.Names[property.Value.IntValue].Substring(3));
                            break;
                        case "TextureFileCacheName": arcName = property.Value.NameValue.Name; break;
                        case "LODGroup": LODGroup = property.Value.NameValue.Name; break;
                        case "None": dataOffset = (uint)(property.offsetval + property.Size); break;
                    }
                }
                if (!String.IsNullOrEmpty(arcName))
                    FullArcPath = GetTexArchive(pathBioGame);

                // if "None" property isn't found throws an exception
                if (dataOffset == 0)
                    throw new Exception("\"None\" property not found");
                else
                {
                    imageData = new byte[rawData.Length - dataOffset];
                    Buffer.BlockCopy(rawData, (int)dataOffset, imageData, 0, (int)(rawData.Length - dataOffset));
                }
            }
            else
                throw new Exception("Texture2D " + texIdx + " not found");

            pccExpIdx = texIdx;
            MemoryStream dataStream = new MemoryStream(imageData);  // FG: we will move forward with the memorystream (we are reading an export entry for a texture object data inside the pcc)
            numMipMaps = dataStream.ReadValueU32();                 // FG: 1st int32 (4 bytes / 32bits) is number of mipmaps
            uint count = numMipMaps;

            privateimgList = new List<ImageInfo>();
            ArcDataSize = 0;
            while (dataStream.Position < dataStream.Length && count > 0)
            {
                ImageInfo imgInfo = new ImageInfo();                            // FG: store properties in ImageInfo struct (code at top)
                imgInfo.storageType = (storage)dataStream.ReadValueS32();       // FG: 2nd int32 storage type (see storage types above in enum_struct)
                imgInfo.uncSize = dataStream.ReadValueS32();                    // FG: 3rd int32 uncompressed texture size
                imgInfo.cprSize = dataStream.ReadValueS32();                    // FG: 4th int32 compressed texture size
                imgInfo.offset = dataStream.ReadValueS32();                     // FG: 5th int32 texture offset
                if (imgInfo.storageType == storage.pccSto)
                {
                    //imgInfo.offset = (int)(pccOffset + dataOffset); // saving pcc offset as relative to exportdata offset, not absolute
                    imgInfo.offset = (int)dataStream.Position; // saving pcc offset as relative to exportdata offset, not absolute
                    //MessageBox.Show("Pcc class offset: " + pccOffset + "\nimages data offset: " + imgInfo.offset.ToString());
                    dataStream.Seek(imgInfo.uncSize, SeekOrigin.Current);       // FG: if local storage, texture data follows, so advance datastream to after uncompressed_size (pcc storage type only)
                }
                else if (imgInfo.storageType == storage.arcCpr || imgInfo.storageType == storage.arcUnc)
                {
                    ArcDataSize += imgInfo.uncSize;
                }
                imgInfo.imgSize = new ImageSize(dataStream.ReadValueU32(), dataStream.ReadValueU32());  // FG: 6th & 7th [or nth and (nth + 1) if local] int32 are width x height
                privateimgList.Add(imgInfo);                                                                   // FG: A salty's favorite, add the struct to a list<struct>
                count--;
            }


            // save what remains
            int remainingBytes = (int)(dataStream.Length - dataStream.Position);
            footerData = new byte[remainingBytes];
            dataStream.Read(footerData, 0, footerData.Length);


            dataStream.Dispose();
        }
Exemplo n.º 6
0
        public List<ImageInfo> imgList { get; private set; } // showable image list

        public Texture2D(ME3Package pccObj, int texIdx)
        {
            pccRef = pccObj;
            // check if texIdx is an Export index and a Texture2D class
            if (pccObj.isExport(texIdx) && (pccObj.Exports[texIdx].ClassName == className))
            {
                IExportEntry expEntry = pccObj.Exports[texIdx];
                properties = new Dictionary<string, PropertyReader.Property>();
                byte[] rawData = expEntry.Data;
                int propertiesOffset = PropertyReader.detectStart(pccObj, rawData, expEntry.ObjectFlags);
                headerData = new byte[propertiesOffset];
                Buffer.BlockCopy(rawData, 0, headerData, 0, propertiesOffset);
                pccOffset = (uint)expEntry.DataOffset;
                List<PropertyReader.Property> tempProperties = PropertyReader.getPropList(expEntry);
                texName = expEntry.ObjectName;
                for (int i = 0; i < tempProperties.Count; i++)
                {
                    PropertyReader.Property property = tempProperties[i];
                    if (!properties.ContainsKey(pccObj.Names[property.Name]))
                        properties.Add(pccObj.Names[property.Name], property);

                    switch (pccObj.Names[property.Name])
                    {
                        case "Format": texFormat = pccObj.Names[property.Value.IntValue].Substring(3); break;
                        case "TextureFileCacheName": arcName = pccObj.Names[property.Value.IntValue]; break;
                        case "LODGroup": LODGroup = pccObj.Names[property.Value.IntValue]; break;
                        case "None": dataOffset = (uint)(property.offsetval + property.Size); break;
                    }
                }

                // if "None" property isn't found throws an exception
                if (dataOffset == 0)
                    throw new Exception("\"None\" property not found");
                else
                {
                    imageData = new byte[rawData.Length - dataOffset];
                    Buffer.BlockCopy(rawData, (int)dataOffset, imageData, 0, (int)(rawData.Length - dataOffset));
                }
            }
            else
                throw new Exception("Texture2D " + texIdx + " not found");

            pccExpIdx = texIdx;
            MemoryStream dataStream = new MemoryStream(imageData);
            numMipMaps = dataStream.ReadValueU32();
            uint count = numMipMaps;

            imgList = new List<ImageInfo>();
            while (dataStream.Position < dataStream.Length && count > 0)
            {
                ImageInfo imgInfo = new ImageInfo();
                imgInfo.storageType = (storage)dataStream.ReadValueS32();
                imgInfo.uncSize = dataStream.ReadValueS32();
                imgInfo.cprSize = dataStream.ReadValueS32();
                imgInfo.offset = dataStream.ReadValueS32();
                if (imgInfo.storageType == storage.pccSto)
                {
                    //imgInfo.offset = (int)(pccOffset + dataOffset); // saving pcc offset as relative to exportdata offset, not absolute
                    imgInfo.offset = (int)dataStream.Position; // saving pcc offset as relative to exportdata offset, not absolute
                    //MessageBox.Show("Pcc class offset: " + pccOffset + "\nimages data offset: " + imgInfo.offset.ToString());
                    dataStream.Seek(imgInfo.uncSize, SeekOrigin.Current);
                }
                imgInfo.imgSize = new ImageSize(dataStream.ReadValueU32(), dataStream.ReadValueU32());
                imgList.Add(imgInfo);
                count--;
            }

            // save what remains
            /*int remainingBytes = (int)(dataStream.Length - dataStream.Position);
            footerData = new byte[remainingBytes];
            dataStream.Read(footerData, 0, footerData.Length);*/
        }
Exemplo n.º 7
0
        public ME2Texture2D(ME2PCCObject pcc, int pccExpID, String pathBioGame)
        {
            ME2ExportEntry exp = pcc.Exports[pccExpID];
            if (String.Compare(exp.ClassName, className) != 0 && String.Compare(exp.ClassName, class2) != 0 && String.Compare(exp.ClassName, class3) != 0)
            {
                throw new FormatException("Export is not a texture");
            }
            Class = exp.ClassName;
            exportOffset = exp.DataOffset;
            FullPackage = exp.PackageFullName;
            texName = exp.ObjectName;
            pccFileName = pcc.pccFileName;
            allPccs = new List<string>();
            allPccs.Add(pcc.pccFileName);
            properties = new Dictionary<string, SaltPropertyReader.Property>();
            byte[] rawData = (byte[])exp.Data.Clone();
            Compression = "No Compression";
            int propertiesOffset = SaltPropertyReader.detectStart(pcc, rawData);
            headerData = new byte[propertiesOffset];
            Buffer.BlockCopy(rawData, 0, headerData, 0, propertiesOffset);
            pccOffset = (uint)exp.DataOffset;
            UnpackNum = 0;
            List<SaltPropertyReader.Property> tempProperties = SaltPropertyReader.getPropList(pcc, rawData);
            for (int i = 0; i < tempProperties.Count; i++)
            {
                SaltPropertyReader.Property property = tempProperties[i];
                if (property.Name == "UnpackMin")
                    UnpackNum++;

                if (!properties.ContainsKey(property.Name))
                    properties.Add(property.Name, property);

                switch (property.Name)
                {
                    case "Format": texFormat = property.Value.StringValue; break;
                    case "TextureFileCacheName": arcName = property.Value.StringValue; break;
                    case "LODGroup": LODGroup = property.Value.StringValue; break;
                    case "CompressionSettings": Compression = property.Value.StringValue; break;
                    case "None": dataOffset = (uint)(property.offsetval + property.Size); break;
                }
            }
            // if "None" property isn't found throws an exception
            if (dataOffset == 0)
                throw new Exception("\"None\" property not found");

            if (!String.IsNullOrEmpty(arcName))
                FullArcPath = GetTexArchive(pathBioGame);

            imageData = new byte[rawData.Length - dataOffset];
            Buffer.BlockCopy(rawData, (int)dataOffset, imageData, 0, (int)(rawData.Length - dataOffset));

            //DebugOutput.PrintLn("ImageData size = " + imageData.Length);
            pccExpIdx = pccExpID;

            MemoryStream dataStream = new MemoryStream(imageData);
            privateimgList = new List<ImageInfo>();
            dataStream.ReadValueU32(); //Current position in pcc
            numMipMaps = dataStream.ReadValueU32();
            uint count = numMipMaps;
            ArcDataSize = 0;
            //DebugOutput.PrintLn(numMipMaps + " derp");
            while (dataStream.Position < dataStream.Length && count > 0)
            {
                ImageInfo imgInfo = new ImageInfo();
                imgInfo.storageType = (storage)dataStream.ReadValueS32();
                imgInfo.uncSize = dataStream.ReadValueS32();
                imgInfo.cprSize = dataStream.ReadValueS32();
                imgInfo.offset = dataStream.ReadValueS32();
                if (imgInfo.storageType == storage.pccSto)
                {
                    imgInfo.offset = (int)dataStream.Position;
                    dataStream.Seek(imgInfo.uncSize, SeekOrigin.Current);
                }
                else if (imgInfo.storageType == storage.arcCpr || imgInfo.storageType == storage.arcUnc)
                {
                    ArcDataSize += imgInfo.uncSize;
                }

                imgInfo.imgSize = new ImageSize(dataStream.ReadValueU32(), dataStream.ReadValueU32());
                if (privateimgList.Exists(img => img.imgSize == imgInfo.imgSize))
                {
                    uint width = imgInfo.imgSize.width;
                    uint height = imgInfo.imgSize.height;
                    if (width == 4 && privateimgList.Exists(img => img.imgSize.width == width))
                        width = privateimgList.Last().imgSize.width / 2;
                    if (width == 0)
                        width = 1;
                    if (height == 4 && privateimgList.Exists(img => img.imgSize.height == height))
                        height = privateimgList.Last().imgSize.height / 2;
                    if (height == 0)
                        height = 1;
                    imgInfo.imgSize = new ImageSize(width, height);
                    if (privateimgList.Exists(img => img.imgSize == imgInfo.imgSize))
                        throw new Exception("Duplicate image size found");
                }
                privateimgList.Add(imgInfo);
                count--;
                //DebugOutput.PrintLn("ImgInfo no: " + count + ", Storage Type = " + imgInfo.storageType + ", offset = " + imgInfo.offset);
            }
            // Grab the rest for the footer
            footerData = new byte[dataStream.Length - dataStream.Position];
            footerData = dataStream.ReadBytes(footerData.Length);
        }
Exemplo n.º 8
0
        private void loadTOCfile(string path)
        {
            BitConverter.IsLittleEndian = true;
            listBox1.Items.Clear();
            FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read);
            memsize = (int)fileStream.Length;
            memory = new byte[memsize];
            int count;
            int sum = 0;
            while ((count = fileStream.Read(memory, sum, memsize - sum)) > 0) sum += count;
            fileStream.Close();
            if (memsize > 0)
            {
                content = new List<Inventory>();
                Inventory temp = new Inventory();
                MemoryStream myStream = new MemoryStream(memory);
                if (myStream.ReadValueU32() == 0x3AB70C13)
                {
                    myStream.Seek(8, SeekOrigin.Begin);
                    uint jumpSize = myStream.ReadValueU32();
                    myStream.Seek(jumpSize * 8, SeekOrigin.Current);
                    uint blockSize;
                    do
                    {
                        temp = new Inventory();
                        long position = myStream.Position;
                        uint value = myStream.ReadValueU32();
                        blockSize = value & 0xFFFF;
                        uint offset = (uint)myStream.Position;
                        uint fileSize = myStream.ReadValueU32();
                        myStream.Seek(20, SeekOrigin.Current);


                        string filePath = myStream.ReadStringZ();

                        myStream.Seek(position + blockSize, SeekOrigin.Begin);

                        temp.name = filePath;
                        temp.offset = offset;
                        temp.size = fileSize;
                        content.Add(temp);

                    } while (blockSize != 0);
                }
                myStream.Close();
                for (int i = 0; i < content.Count(); i++)
                {
                    listBox1.Items.Add(content[i].offset.ToString("X") + " : " + content[i].name + " (bytes)" + content[i].size.ToString());
                }
            }
        }
        private static void Main(string[] args)
        {
            var paths = Directory.GetFiles("saves", "*.sav");

            var successes = 0;
            var failures = 0;

            foreach (var path in paths)
            {
                var name = Path.GetFileNameWithoutExtension(path);

                using (var input = File.OpenRead(path))
                {
                    var readHash = input.ReadBytes(20);
                    using (var data = input.ReadToMemoryStream(input.Length - 20))
                    {
                        byte[] computedHash;
                        using (var sha1 = new System.Security.Cryptography.SHA1Managed())
                        {
                            computedHash = sha1.ComputeHash(data);
                        }

                        if (readHash.SequenceEqual(computedHash) == false)
                        {
                            Console.WriteLine("{0}: failed (SHA1 mismatch)", name);
                            failures++;
                            continue;
                        }

                        data.Position = 0;
                        var uncompressedSize = data.ReadValueU32(Endian.Big);
                        var actualUncompressedSize = (int)uncompressedSize;
                        var uncompressedBytes = new byte[uncompressedSize];
                        var compressedSize = (int)(data.Length - 4);
                        var compressedBytes = data.ReadBytes(compressedSize);
                        var result = LZO.Decompress(compressedBytes,
                                                    0,
                                                    compressedSize,
                                                    uncompressedBytes,
                                                    0,
                                                    ref actualUncompressedSize);
                        if (result != LZO.ErrorCode.Success)
                        {
                            Console.WriteLine("{0}: failed (LZO error {1})", name, result);
                            failures++;
                            continue;
                        }

                        using (var outerData = new MemoryStream(uncompressedBytes))
                        {
                            var innerSize = outerData.ReadValueU32(Endian.Big);
                            var magic = outerData.ReadString(3);
                            if (magic != "WSG")
                            {
                                Console.WriteLine("{0}: failed (bad magic)", name);
                                failures++;
                                continue;
                            }

                            var version = outerData.ReadValueU32(Endian.Little);
                            if (version != 2 &&
                                version.Swap() != 2)
                            {
                                Console.WriteLine("{0}: failed (bad version)", name);
                                failures++;
                                continue;
                            }

                            var endian = version == 2 ? Endian.Little : Endian.Big;

                            var hash = outerData.ReadValueU32(endian);
                            var innerUncompressedSize = outerData.ReadValueS32(endian);

                            var innerCompressedBytes = outerData.ReadBytes(innerSize - 3 - 4 - 4 - 4);
                            var innerUncompressedBytes = Huffman.Decoder.Decode(innerCompressedBytes,
                                                                                innerUncompressedSize);
                            using (var innerUncompressedData = new MemoryStream(innerUncompressedBytes))
                            {
                                using (var output = File.Create("temp.bin"))
                                {
                                    output.WriteBytes(innerUncompressedBytes);
                                }

                                var save =
                                    Serializer.Deserialize<WillowTwoSave.WillowTwoPlayerSaveGame>(innerUncompressedData);

                                using (var testData = new MemoryStream())
                                {
                                    Serializer.Serialize(testData, save);

                                    testData.Position = 0;
                                    var testBytes = testData.ReadBytes((uint)testData.Length);
                                    if (innerUncompressedBytes.SequenceEqual(testBytes) == false)
                                    {
                                        Console.WriteLine("{0}: failed (reencode mismatch)", name);

                                        using (var output = File.Create(Path.Combine("failures", name + "_before.bin")))
                                        {
                                            output.WriteBytes(innerUncompressedBytes);
                                        }

                                        using (var output = File.Create(Path.Combine("failures", name + "_after.bin")))
                                        {
                                            output.WriteBytes(testBytes);
                                        }

                                        failures++;
                                        continue;
                                    }

                                    successes++;
                                }
                            }
                        }
                    }
                }
            }

            Console.WriteLine("{0} processed ({1} failed, {2} succeeded).",
                              paths.Length,
                              failures,
                              successes);
        }
        public static SaveFile Deserialize(Stream input, DeserializeSettings settings)
        {
            if (input.Position + 20 > input.Length)
            {
                throw new SaveCorruptionException("not enough data for save header");
            }

            var check = input.ReadValueU32(Endian.Big);
            if (check == 0x434F4E20)
            {
                throw new SaveFormatException("Xbox 360 save game loading is in the works");

            }
            input.Seek(-4, SeekOrigin.Current);

            var readSha1Hash = input.ReadBytes(20);
            using (var data = input.ReadToMemoryStream(input.Length - 20))
            {
                byte[] computedSha1Hash;
                using (var sha1 = new System.Security.Cryptography.SHA1Managed())
                {
                    computedSha1Hash = sha1.ComputeHash(data);
                }

                if ((settings & DeserializeSettings.IgnoreSha1Mismatch) == 0 &&
                    readSha1Hash.SequenceEqual(computedSha1Hash) == false)
                {
                    throw new SaveCorruptionException("invalid SHA1 hash");
                }

                data.Position = 0;
                var uncompressedSize = data.ReadValueU32(Endian.Big);

                var uncompressedBytes = new byte[uncompressedSize];
                if (uncompressedSize <= BlockSize)
                {
                    var actualUncompressedSize = (int)uncompressedSize;
                    var compressedSize = (uint)(data.Length - 4);
                    var compressedBytes = data.ReadBytes(compressedSize);
                    var result = LZO.Decompress(compressedBytes,
                                                0,
                                                (int)compressedSize,
                                                uncompressedBytes,
                                                0,
                                                ref actualUncompressedSize);
                    if (result != LZO.ErrorCode.Success)
                    {
                        throw new SaveCorruptionException(string.Format("LZO decompression failure ({0})", result));
                    }

                    if (actualUncompressedSize != (int)uncompressedSize)
                    {
                        throw new SaveCorruptionException("LZO decompression failure (uncompressed size mismatch)");
                    }
                }
                else
                {
                    var blockCount = data.ReadValueU32(Endian.Big);
                    var blockInfos = new List<Tuple<uint, uint>>();
                    for (uint i = 0; i < blockCount; i++)
                    {
                        var blockCompressedSize = data.ReadValueU32(Endian.Big);
                        var blockUncompressedSize = data.ReadValueU32(Endian.Big);
                        blockInfos.Add(new Tuple<uint, uint>(blockCompressedSize, blockUncompressedSize));
                    }

                    int uncompressedOffset = 0;
                    int uncompressedSizeLeft = (int)uncompressedSize;
                    foreach (var blockInfo in blockInfos)
                    {
                        var blockUncompressedSize = Math.Min((int)blockInfo.Item2, uncompressedSizeLeft);
                        var actualUncompressedSize = blockUncompressedSize;
                        var compressedSize = (int)blockInfo.Item1;
                        var compressedBytes = data.ReadBytes(compressedSize);
                        var result = LZO.Decompress(compressedBytes,
                                                    0,
                                                    compressedSize,
                                                    uncompressedBytes,
                                                    uncompressedOffset,
                                                    ref actualUncompressedSize);
                        if (result != LZO.ErrorCode.Success)
                        {
                            throw new SaveCorruptionException(string.Format("LZO decompression failure ({0})", result));
                        }

                        if (actualUncompressedSize != blockUncompressedSize)
                        {
                            throw new SaveCorruptionException("LZO decompression failure (uncompressed size mismatch)");
                        }

                        uncompressedOffset += blockUncompressedSize;
                        uncompressedSizeLeft -= blockUncompressedSize;
                    }

                    if (uncompressedSizeLeft != 0)
                    {
                        throw new SaveCorruptionException("LZO decompression failure (uncompressed size left != 0)");
                    }
                }

                using (var outerData = new MemoryStream(uncompressedBytes))
                {
                    var innerSize = outerData.ReadValueU32(Endian.Big);
                    var magic = outerData.ReadString(3);
                    if (magic != "WSG")
                    {
                        throw new SaveCorruptionException("invalid magic");
                    }

                    var version = outerData.ReadValueU32(Endian.Little);
                    if (version != 2 &&
                        version.Swap() != 2)
                    {
                        throw new SaveCorruptionException("invalid or unsupported version");
                    }
                    var endian = version == 2 ? Endian.Little : Endian.Big;

                    var readCRC32Hash = outerData.ReadValueU32(endian);
                    var innerUncompressedSize = outerData.ReadValueS32(endian);

                    var innerCompressedBytes = outerData.ReadBytes(innerSize - 3 - 4 - 4 - 4);
                    var innerUncompressedBytes = Huffman.Decoder.Decode(innerCompressedBytes,
                                                                        innerUncompressedSize);
                    if (innerUncompressedBytes.Length != innerUncompressedSize)
                    {
                        throw new SaveCorruptionException("huffman decompression failure");
                    }

                    var computedCRC32Hash = CRC32.Hash(innerUncompressedBytes, 0, innerUncompressedBytes.Length);
                    if ((settings & DeserializeSettings.IgnoreCrc32Mismatch) == 0 &&
                        computedCRC32Hash != readCRC32Hash)
                    {
                        throw new SaveCorruptionException("invalid CRC32 hash");
                    }

                    using (var innerUncompressedData = new MemoryStream(innerUncompressedBytes))
                    {
                        var saveGame =
                            ProtoBuf.Serializer.Deserialize<WillowTwoSave.WillowTwoPlayerSaveGame>(innerUncompressedData);

                        if ((settings & DeserializeSettings.IgnoreReencodeMismatch) == 0)
                        {
                            using (var testData = new MemoryStream())
                            {
                                ProtoBuf.Serializer.Serialize(testData, saveGame);

                                testData.Position = 0;
                                var testBytes = testData.ReadBytes((uint)testData.Length);
                                if (innerUncompressedBytes.SequenceEqual(testBytes) == false)
                                {
                                    throw new SaveCorruptionException("reencode mismatch");
                                }
                            }
                        }

                        saveGame.Decompose();
                        return new SaveFile()
                        {
                            Endian = endian,
                            SaveGame = saveGame,
                        };
                    }
                }
            }
        }
Exemplo n.º 11
0
        public static byte[] Decompress(byte[] buffer, int offset, int count)
        {
            if (buffer == null)
                throw new ArgumentNullException();
            if (count < 0)
                throw new FormatException();
            if (offset + count > buffer.Length)
                throw new IndexOutOfRangeException();

            using (MemoryStream buffStream = new MemoryStream(buffer, offset, count))
            {
                InflaterInputStream zipStream;
                uint magicStream = buffStream.ReadValueU32();
                if (magicStream != magic && magicStream.Swap() != magic)
                {
                    throw new InvalidDataException("found an invalid zlib block");
                }

                uint buffMaxSegmentSize = buffStream.ReadValueU32();
                if (buffMaxSegmentSize != maxSegmentSize)
                {
                    throw new FormatException();
                }

                uint totComprSize = buffStream.ReadValueU32();
                uint totUncomprSize = buffStream.ReadValueU32();

                byte[] outputBuffer = new byte[totUncomprSize];
                int numOfSegm = (int)Math.Ceiling((double)totUncomprSize / (double)maxSegmentSize);
                int headSegm = 16;
                int dataSegm = headSegm + (numOfSegm * 8);
                int buffOff = 0;

                for (int i = 0; i < numOfSegm; i++)
                {
                    buffStream.Seek(headSegm, SeekOrigin.Begin);
                    int comprSegm = buffStream.ReadValueS32();
                    int uncomprSegm = buffStream.ReadValueS32();
                    headSegm = (int)buffStream.Position;

                    buffStream.Seek(dataSegm, SeekOrigin.Begin);
                    //Console.WriteLine("compr size: {0}, uncompr size: {1}, data offset: 0x{2:X8}", comprSegm, uncomprSegm, dataSegm);
                    zipStream = new InflaterInputStream(buffStream);
                    zipStream.Read(outputBuffer, buffOff, uncomprSegm);
                    zipStream.Flush();
                    buffOff += uncomprSegm;
                    dataSegm += comprSegm;
                }
                buffStream.Close();
                return outputBuffer;
            }
        }
Exemplo n.º 12
0
        private bnet.protocol.storage.ExecuteResponse GetHeroDigest(MooNetClient client, bnet.protocol.storage.ExecuteRequest request)
        {
            var results = new List<bnet.protocol.storage.OperationResult>();

            foreach(var operation in request.OperationsList)
            {
                Google.ProtocolBuffers.ByteString data = null;

                // find the requested toons entity-id.
                var stream = new MemoryStream(operation.RowId.Hash.ToByteArray());

                // contains ToonHandle in field form with one unknown field (which is not in message definition):
                // int16 unknown; uint8 realm; uint8 region; uint32 program; uint64 id;
                stream.ReadValueU16(); // unknown
                stream.ReadValueU8(); // realm
                stream.ReadValueU8(); // region 
                stream.ReadValueU32(false); // program

                var toonId = stream.ReadValueU64(false);

                if (!client.Account.CurrentGameAccount.Toons.ContainsKey(toonId))
                {
                    Logger.Error("Can't find the requested toon: {0}", toonId);
                    continue;
                }

                var toon = client.Account.CurrentGameAccount.Toons[toonId];

                if (operation.ColumnId.Hash.Equals(HeroDigestColumn))
                    data = toon.Digest.ToByteString();
                else
                    Logger.Warn("Unknown ColumndId requested: {0}", operation.ColumnId.Hash.ToByteArray().HexDump());
                //else if (operation.ColumnId.Hash.Equals(HeroNameColumn))
                //    data = toon.NameText.ToByteString();
                                 
                var operationResult = bnet.protocol.storage.OperationResult.CreateBuilder().SetTableId(operation.TableId);
                operationResult.AddData(
                    bnet.protocol.storage.Cell.CreateBuilder()
                        .SetColumnId(request.OperationsList[0].ColumnId)
                        .SetRowId(request.OperationsList[0].RowId)
                        .SetVersion(1)
                        .SetData(data)
                        .Build()
                    );
                results.Add(operationResult.Build());
            }

            var builder = bnet.protocol.storage.ExecuteResponse.CreateBuilder();            
            foreach(var result in results)
            {
                builder.AddResults(result);
            }            
            return builder.Build();
        }