Beispiel #1
0
        private static void DecompressLzo(Entry entry, Stream input, Stream output)
        {
            input.Seek(entry.Offset, SeekOrigin.Begin);

            var compressedData = new byte[entry.CompressedSize];

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

            var uncompressedData         = new byte[entry.UncompressedSize];
            int actualUncompressedLength = uncompressedData.Length;

            var result = LZO.Decompress(compressedData,
                                        0,
                                        compressedData.Length,
                                        uncompressedData,
                                        0,
                                        ref actualUncompressedLength);

            if (result != LZO.ErrorCode.Success)
            {
                throw new FormatException(string.Format("LZO decompression failure ({0})", result));
            }

            if (actualUncompressedLength != uncompressedData.Length)
            {
                throw new FormatException("LZO decompression failure (uncompressed size mismatch)");
            }

            output.Write(uncompressedData, 0, uncompressedData.Length);
        }
        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 saveGame =
                                    Serializer.Deserialize <WillowTwoSave.WillowTwoPlayerSaveGame>(innerUncompressedData);
                                SaveExpansion.ExtractExpansionSavedataFromUnloadableItemData(saveGame);

                                using (var testData = new MemoryStream())
                                {
                                    SaveExpansion.AddExpansionSavedataToUnloadableItemData(saveGame);
                                    Serializer.Serialize(testData, saveGame);

                                    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);
        }
Beispiel #3
0
        private FastBinaryReader GetDataStream(ZFSFileInfo fileInfo)
        {
            ZFSFileInfo originalFile = null;

            if (fileInfo.ContainingPakFilename != null)
            {
                originalFile = fileInfo;
                fileInfo     = _files[fileInfo.ContainingPakFilename];
            }

            if (fileInfo.Compression == 0)
            {
                FastBinaryReader br = new FastBinaryReader(_zfsMemory)
                {
                    Position = fileInfo.Offset,
                    Length   = (int)(fileInfo.Offset + fileInfo.Length)
                };

                if (originalFile != null)
                {
                    br.Position += originalFile.Offset;
                    br.Length    = (int)(br.Position + originalFile.Length);
                }

                return(br);
            }

            CompressionAlgorithm compressionAlgorithm;

            if (fileInfo.Compression == 2)
            {
                compressionAlgorithm = CompressionAlgorithm.LZO1X;
            }
            else if (fileInfo.Compression == 4)
            {
                compressionAlgorithm = CompressionAlgorithm.LZO1Y;
            }
            else
            {
                throw new Exception("Unknown compression " + fileInfo.Compression);
            }

            byte[] fileData = new byte[fileInfo.Length];
            Buffer.BlockCopy(_zfsMemory, (int)fileInfo.Offset, fileData, 0, fileData.Length);

            byte[] decompressedData = new byte[fileInfo.DecompressedLength];
            uint   length           = LZO.Decompress(fileData, decompressedData, fileInfo.DecompressedLength, compressionAlgorithm);

            if (length != fileInfo.DecompressedLength)
            {
                throw new Exception("Decompressed length does not match expected decompressed length");
            }

            FastBinaryReader reader = new FastBinaryReader(decompressedData)
            {
                Position = 0,
                Length   = decompressedData.Length
            };

            if (originalFile != null)
            {
                reader.Position = originalFile.Offset;
                reader.Length   = (int)(originalFile.Offset + originalFile.Length);
            }

            return(reader);
        }
Beispiel #4
0
        static void Main(string[] args)
        {
            uint HPNT = (5 * 4);
            uint HDMY = (14 * 4);


            using (BinaryReader buffer = new BinaryReader(File.Open(args[0], FileMode.Open)))
            {
                LZO lzo = new LZO();

                //Grab string header
                var stringbytes = new List <char>();
                while (buffer.PeekChar() != 0x00)
                {
                    stringbytes.Add(buffer.ReadChar());
                }
                buffer.ReadChar(); //null string termination not handled by ReadString()

                //Skeleton and Origin
                Byte[] header      = buffer.ReadBytes(41);
                UInt16 NumberHPNTs = buffer.ReadUInt16();
                UInt16 NumberHDMYs = buffer.ReadUInt16();
                UInt32 HLPR_Size   = buffer.ReadUInt32();
                Byte[] pad1        = buffer.ReadBytes(2);

                Byte[] helper_points  = new Byte[HPNT * NumberHPNTs];
                Byte[] helper_dummies = new Byte[HDMY * NumberHDMYs];
                Byte[] helpers        = new Byte[HLPR_Size];

                UInt16 compressed_point_size = buffer.ReadUInt16();
                if (compressed_point_size > 0)
                {
                    Byte[] compressed = buffer.ReadBytes(compressed_point_size);
                    Byte[] runoff     = buffer.ReadBytes(3);
                    helper_points = lzo.Decompress(compressed, compressed_point_size, helper_points, (int)(HPNT * NumberHPNTs));
                    System.Buffer.BlockCopy(runoff, 0, helper_points, helper_points.Length - 3, 3);
                }
                else
                {
                    helper_points = buffer.ReadBytes((int)(HPNT * NumberHPNTs));
                }

                UInt16 compressed_dummy_size = buffer.ReadUInt16();
                if (compressed_dummy_size > 0)
                {
                    Byte[] compressed = buffer.ReadBytes(compressed_dummy_size);
                    Byte[] runoff     = buffer.ReadBytes(3);
                    helper_dummies = lzo.Decompress(compressed, compressed_dummy_size, helper_dummies, (int)(HDMY * NumberHDMYs));
                    System.Buffer.BlockCopy(runoff, 0, helper_dummies, helper_dummies.Length - 3, 3);
                }
                else
                {
                    helper_dummies = buffer.ReadBytes((int)(HDMY * NumberHDMYs));
                }

                UInt16 compressed_helper_size = buffer.ReadUInt16();
                if (compressed_helper_size > 0)
                {
                    Byte[] compressed = buffer.ReadBytes(compressed_helper_size);
                    Byte[] runoff     = buffer.ReadBytes(3);
                    helpers = lzo.Decompress(compressed, compressed_helper_size, new byte[HLPR_Size], (int)HLPR_Size);
                    System.Buffer.BlockCopy(runoff, 0, helpers, helpers.Length - 3, 3);
                }
                else
                {
                    helpers = buffer.ReadBytes((int)HLPR_Size);
                }


                UInt32 NumberMaterials = buffer.ReadUInt32();
                UInt32 NumberSubMeshes = buffer.ReadUInt32();
                UInt32 NumberBones     = buffer.ReadUInt32();
                UInt32 SizeOfBoneIndex = buffer.ReadUInt32();
                byte[] pad2            = buffer.ReadBytes(1);
                UInt16 unk1            = buffer.ReadUInt16();
                UInt16 unk2            = buffer.ReadUInt16();
                Byte[] identitymatrix  = buffer.ReadBytes(12 * 4); //matrix, 12 floats

                for (var i = 1; i < NumberBones; i++)
                {
                }
                for (var i = 1; i < NumberMaterials; i++)
                {
                }
                for (var i = 1; i < NumberSubMeshes; i++)
                {
                }


                string newfile = Path.ChangeExtension(args[0], null) + ".unpacked.bbm";
                (new FileInfo(newfile)).Directory.Create();
                using (BinaryWriter b = new BinaryWriter(File.Open(newfile, FileMode.Create)))
                {
                    //Leave it uncompressed
                    compressed_point_size  = 0;
                    compressed_dummy_size  = 0;
                    compressed_helper_size = 0;
                    //None of this is needed
                    NumberMaterials = 0;
                    NumberSubMeshes = 0;
                    NumberBones     = 0;
                    unk1            = 0;
                    unk2            = 0;

                    //Write a new file...
                    b.Write(stringbytes.ToArray());
                    b.Write(new Byte[] { 0x00 });
                    b.Write(header);
                    b.Write(NumberHPNTs);
                    b.Write(NumberHDMYs);
                    b.Write(HLPR_Size);
                    b.Write(pad1);
                    b.Write(compressed_point_size);
                    b.Write(helper_points);
                    b.Write(compressed_dummy_size);
                    b.Write(helper_dummies);
                    b.Write(compressed_helper_size);
                    b.Write(helpers);
                    b.Write(NumberMaterials);
                    b.Write(NumberSubMeshes);
                    b.Write(NumberBones);
                    b.Write(SizeOfBoneIndex);
                    b.Write(pad2);
                    b.Write(unk1);
                    b.Write(unk2);
                    b.Write(identitymatrix);
                    //Nothing after this is needed or read by the game...
                }
            }
        }
        private static void Main(string[] args)
        {
            bool showHelp       = false;
            bool overwriteFiles = false;
            bool verbose        = false;

            var options = new OptionSet()
            {
                { "o|overwrite", "overwrite existing files", v => overwriteFiles = v != null },
                { "v|verbose", "be verbose", v => verbose = v != null },
                { "h|help", "show this message and exit", v => showHelp = v != null },
            };

            List <string> extras;

            try
            {
                extras = options.Parse(args);
            }
            catch (OptionException e)
            {
                Console.Write("{0}: ", GetExecutableName());
                Console.WriteLine(e.Message);
                Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName());
                return;
            }

            if (extras.Count < 1 || extras.Count > 2 || showHelp == true)
            {
                Console.WriteLine("Usage: {0} [OPTIONS]+ input_tms [output_dir]", GetExecutableName());
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

            string inputPath  = extras[0];
            string outputPath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(inputPath, null) + "_unpack";

            var endian = Endian.Little;

            using (var input = File.OpenRead(inputPath))
            {
                var uncompressedSize3 = input.ReadValueU32(endian);
                var fileCount         = input.ReadValueU32(endian);
                var magic             = input.ReadValueU32(endian);
                var version           = input.ReadValueU32(endian);

                if (magic != 0x9E2A83C1 ||
                    version != 0x00020000)
                {
                    throw new FormatException();
                }

                var compressedSize1   = input.ReadValueU32(endian);
                var uncompressedSize1 = input.ReadValueU32(endian);
                var compressedSize2   = input.ReadValueU32(endian);
                var uncompressedSize2 = input.ReadValueU32(endian);

                if (compressedSize1 != compressedSize2 ||
                    uncompressedSize1 != uncompressedSize2 ||
                    uncompressedSize1 != uncompressedSize3)
                {
                    throw new FormatException();
                }

                var compressedBytes   = input.ReadBytes(compressedSize1);
                var uncompressedBytes = new byte[uncompressedSize1];

                var actualUncompressedSize = (int)uncompressedSize1;
                var result = LZO.Decompress(compressedBytes,
                                            0,
                                            (int)compressedSize1,
                                            uncompressedBytes,
                                            0,
                                            ref actualUncompressedSize);
                if (result != LZO.ErrorCode.Success)
                {
                    throw new FormatException();
                }

                if (actualUncompressedSize != uncompressedSize1)
                {
                    throw new FormatException();
                }

                using (var data = new MemoryStream(uncompressedBytes))
                {
                    for (uint i = 0; i < fileCount; i++)
                    {
                        var entryNameLength = data.ReadValueS32(endian);
                        if (entryNameLength < 0)
                        {
                            throw new NotImplementedException();
                        }

                        var entryName       = data.ReadString(entryNameLength, true, Encoding.ASCII);
                        var entryTextLength = data.ReadValueS32(endian);

                        Encoding entryTextEncoding;
                        if (entryTextLength >= 0)
                        {
                            entryTextEncoding = Encoding.ASCII;
                        }
                        else
                        {
                            entryTextEncoding = Encoding.Unicode;
                            entryTextLength   = (-entryTextLength) * 2;
                        }
                        var entryText = data.ReadString(entryTextLength, true, entryTextEncoding);

                        var entryPath = Path.Combine(outputPath, entryName);
                        if (overwriteFiles == false &&
                            File.Exists(entryPath) == true)
                        {
                            continue;
                        }

                        if (verbose == true)
                        {
                            Console.WriteLine(entryName);
                        }

                        var entryParentPath = Path.GetDirectoryName(entryPath);
                        if (string.IsNullOrEmpty(entryParentPath) == false)
                        {
                            Directory.CreateDirectory(entryParentPath);
                        }

                        using (var output = new StreamWriter(entryPath, false, entryTextEncoding))
                        {
                            output.Write(entryText);
                        }
                    }
                }
            }
        }