예제 #1
0
        /// <summary>
        /// Decodes buffer.
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="seed"></param>
        private void Decode(ref byte[] buffer)
        {
            var mt = new MTRandom((uint)((this.Seed << 7) ^ 0xA9C36DE1));

            for (int i = 0; i < buffer.Length; ++i)
            {
                buffer[i] = (byte)(buffer[i] ^ mt.GetUInt32());
            }
        }
예제 #2
0
        /// <summary>
        /// Decodes buffer.
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="seed"></param>
        private void Decode(ref byte[] buffer)
        {
            // KR beta (v1) didn't have encoding yet
            if (this.Header.FormatVersion == 1)
            {
                return;
            }

            var mt = new MTRandom((this.Seed << 7) ^ 0xA9C36DE1);

            for (var i = 0; i < buffer.Length; ++i)
            {
                buffer[i] = (byte)(buffer[i] ^ mt.GetUInt32());
            }
        }
예제 #3
0
        /// <summary>
        /// Writes pack file to given location.
        /// </summary>
        /// <param name="filePath"></param>
        public void Save(string filePath, CompressionStrength compression = CompressionStrength.Default)
        {
            var blankLength = this.Header.BlankLength;
            var fileCount   = this.Count;

            using (var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                using (var bw = new BinaryWriter(fs))
                {
                    var entryStarts = new Dictionary <IPackListEntry, long>();

                    // Header
                    bw.Write(this.Header.Signature);
                    bw.Write(this.Header.FormatVersion);
                    bw.Write(this.Header.PackVersion);
                    bw.Write(fileCount);
                    bw.Write(this.Header.FileTime1.ToFileTimeUtc());
                    bw.Write(this.Header.FileTime2.ToFileTimeUtc());
                    bw.Write(Encoding.UTF8.GetBytes(this.Header.BasePath.PadRight(480, '\0')));
                    bw.Write(fileCount);

                    var headerLengthsStart = bw.BaseStream.Position;
                    bw.Write(this.Header.ListLength);
                    bw.Write(blankLength);
                    bw.Write(this.Header.DataLength);
                    bw.Write(this.Header.Zero);

                    // List
                    var entryListStart = bw.BaseStream.Position;
                    foreach (var entry in _entries.Values)
                    {
                        bw.Write((byte)entry.NameType);

                        if (entry.NameType <= PackListNameType.L64)
                        {
                            var size  = (0x10 * ((byte)entry.NameType + 1));
                            var bytes = Encoding.UTF8.GetBytes(entry.RelativePath.PadRight(size - 1, '\0'));

                            bw.Write(bytes);
                        }
                        else if (entry.NameType == PackListNameType.L96)
                        {
                            var size  = 0x60;
                            var bytes = Encoding.UTF8.GetBytes(entry.RelativePath.PadRight(size - 1, '\0'));

                            bw.Write(bytes);
                        }
                        else if (entry.NameType == PackListNameType.LDyn)
                        {
                            var bytes = Encoding.UTF8.GetBytes(entry.RelativePath + '\0');

                            bw.Write(bytes.Length);
                            bw.Write(bytes);
                        }
                        else
                        {
                            throw new Exception("Unknown entry name type '" + entry.NameType + "'.");
                        }

                        bw.Write(entry.Seed);
                        bw.Write(entry.Zero);

                        entryStarts[entry] = bw.BaseStream.Position;
                        bw.Write(0);                 // DataOffset
                        bw.Write(0);                 // CompressedSize
                        bw.Write(0);                 // DecompressedSize

                        bw.Write(entry.IsCompressed ? 1 : 0);
                        bw.Write(entry.FileTime1.ToFileTimeUtc());
                        bw.Write(entry.FileTime2.ToFileTimeUtc());
                        bw.Write(entry.FileTime3.ToFileTimeUtc());
                        bw.Write(entry.FileTime4.ToFileTimeUtc());
                        bw.Write(entry.FileTime5.ToFileTimeUtc());
                    }

                    var entryListEnd    = bw.BaseStream.Position;
                    var entryListLength = (int)(entryListEnd - entryListStart);

                    bw.Write(new byte[blankLength]);

                    // Data
                    var dataOffset    = 0;
                    var dataListStart = bw.BaseStream.Position;
                    foreach (var entry in _entries.Values)
                    {
                        // Get data
                        var data             = entry.GetData();
                        var uncompressedSize = data.Length;

                        if (entry.IsCompressed)
                        {
                            // Compress data
                            var    dataStart = bw.BaseStream.Position;
                            byte[] compressed;

                            using (var ms = new MemoryStream())
                            {
                                var zlib = new ZOutputStream(ms, (int)compression);
                                zlib.Write(data, 0, data.Length);
                                zlib.finish();

                                compressed = ms.ToArray();
                            }

                            var mt = new MTRandom((entry.Seed << 7) ^ 0xA9C36DE1);
                            for (var i = 0; i < compressed.Length; ++i)
                            {
                                compressed[i] = (byte)(compressed[i] ^ mt.GetUInt32());
                            }

                            data = compressed;
                        }

                        bw.Write(data);

                        var dataEnd        = bw.BaseStream.Position;
                        var compressedSize = data.Length;
                        var listPos        = entryStarts[entry];

                        // Overwrite entry information
                        bw.BaseStream.Seek(listPos, SeekOrigin.Begin);
                        bw.Write(dataOffset);
                        bw.Write(compressedSize);
                        bw.Write(uncompressedSize);
                        bw.BaseStream.Seek(dataEnd, SeekOrigin.Begin);

                        dataOffset += compressedSize;
                    }

                    var dataListEnd    = bw.BaseStream.Position;
                    var dataListLength = (int)(dataListEnd - dataListStart);

                    bw.BaseStream.Seek(headerLengthsStart, SeekOrigin.Begin);
                    bw.Write(entryListLength + blankLength);
                    bw.Seek(4, SeekOrigin.Current);
                    bw.Write(dataListLength);
                    bw.BaseStream.Seek(dataListEnd, SeekOrigin.Begin);
                }
        }