Ejemplo n.º 1
0
        ///<summary>
        /// 重启报文
        ///</summary>
        ///<returns></returns>
        public override string Serialize()
        {
            // 包头 F3
            // 功能码	03
            // 子功能码	00
            // CRC校验	2bytes
            var data = new List <string>
            {
                Header,
                Convert.ToString(FunctionCode, 16),
                Convert.ToString(SubFunctionCode, 16),
            };

            var crc = CrcHelper.GetCrc16(data);

            data.AddRange(crc);
            return(data.Join(","));
        }
Ejemplo n.º 2
0
        ///<summary>
        /// 报文
        ///</summary>
        ///<returns></returns>
        public override string Serialize()
        {
            //0xF1 10 00 00 01,41,00,00,脚本长度4字节小端,密码长度4字节小端 CRC
            // 包头 F1
            // 功能码	10
            // 子功能码	00
            // 操作码	00
            // 脚本长度4字节小端	01,41
            // 密码长度4字节小端	00,00
            // CRC校验	2bytes
            var data = new List <string>
            {
                Header,
                FunctionCode.ToString(),
                Convert.ToString(SubFunctionCode, 16),
                Convert.ToString(OperateCode, 16),
                "01",
                "41",
                "00",
                "00"
            };
            var cData = new List <string>();

            for (var i = 0; i < 4; i++)
            {
                cData.Add(Convert.ToString((byte)(DataLength >> i * 8 & 0xff), 16));
            }
            data.AddRange(cData);
            cData.Clear();
            for (var i = 0; i < 4; i++)
            {
                cData.Add(Convert.ToString((byte)(PwdLength >> i * 8 & 0xff), 16));
            }
            data.AddRange(cData);

            var crc = CrcHelper.GetCrc16(data);

            data.AddRange(crc);
            return(data.Join(","));
        }
Ejemplo n.º 3
0
        public byte[] BuildBytes()
        {
            var list = new List <byte>();

            list.AddRange(Header);
            list.AddRange(EncodingHelper.HexToBytes(Length.ToHex(4)));
            list.AddRange(EncodingHelper.HexToBytes(SessionId));
            list.AddRange(Device.Bytes);
            list.AddRange(Command.GetBytes());

            Crc16 = CrcHelper.GetCrc16(list.ToArray()).ToHex(4);
            list.AddRange(EncodingHelper.HexToBytes(Crc16));

            Body          = list.CloneRange(Header.Length + 2, Length).ToArray();
            BodyHex       = Body.ToHex();
            EncryptedBody = filter.Crypto.Encrypt(Body);

            list.RemoveRange(Header.Length + 2, Length);
            list.AddRange(EncryptedBody);

            return(list.ToArray());
        }
Ejemplo n.º 4
0
        public IdatChunk ToIdatChunk()
        {
            uint newCrc;

            using (var msCrc = new MemoryStream())
            {
                msCrc.WriteBytes(new[] { (byte)'I', (byte)'D', (byte)'A', (byte)'T' });
                msCrc.WriteBytes(FrameData);

                newCrc = CrcHelper.Calculate(msCrc.ToArray());
            }

            using (var ms = new MemoryStream())
            {
                ms.WriteUInt32(Helper.ConvertEndian(Length - 4));
                ms.WriteBytes(new[] { (byte)'I', (byte)'D', (byte)'A', (byte)'T' });
                ms.WriteBytes(FrameData);
                ms.WriteUInt32(Helper.ConvertEndian(newCrc));
                ms.Position = 0;

                return(new IdatChunk(ms));
            }
        }
Ejemplo n.º 5
0
        public static byte GetExtraCrc(string xMessageName, IEnumerable <MessageField> xMessageFields)
        {
            UInt16 crc = CrcHelper.GetCrc(xMessageName + ' ');

            IList <MessageFieldCrcData> fieldCrcDatas = ToMessageFieldCrcDatas(xMessageFields);

            foreach (MessageFieldCrcData fieldCrcData in fieldCrcDatas.OrderByDescending(t => t.TypeLength).ThenBy(t => t.DefinitionIndex).ToList())
            {
                String translatedRawType = TypeHelper.TranslatePrimitiveRawType(fieldCrcData.Field.Type);
                string rawDataType       = TypeHelper.ToRawDataType(translatedRawType);
                crc = CrcHelper.GetCrc(rawDataType + ' ', crc);
                crc = CrcHelper.GetCrc(fieldCrcData.Field.Name + ' ', crc);

                if (fieldCrcData.ArrayLength > 1)
                {
                    crc = CrcHelper.GetCrc((byte)fieldCrcData.ArrayLength, crc);
                }
            }

            byte result = (byte)((crc & 0xFF) ^ (crc >> 8));

            return(result);
        }
Ejemplo n.º 6
0
        internal ApngFrame GetFrame(int index)
        {
            //Build each frame using:
            //Starting blocks: IHDR, tIME, zTXt, tEXt, iTXt, pHYs, sPLT, (iCCP | sRGB), sBIT, gAMA, cHRM, PLTE, tRNS, hIST, bKGD.
            //Image data: IDAT.
            //End block: IEND.

            var chunks      = Chunks.Where(w => w.FrameGroupId == index).ToList();
            var otherChunks = Chunks.Where(w => w.FrameGroupId == -1 && w.ChunkType != "IDAT").ToList();

            if (!chunks.Any())
            {
                return(null);
            }

            var frame = new ApngFrame();

            //First frame • Second frame
            //Default image is part of the animation:       fcTL + IDAT • fcTL + fdAT
            //Default image isn't part of the animation:    IDAT • fcTL + fdAT

            if (chunks[0].ChunkType == "fcTL")
            {
                var fctl = FctlChunk.Read(chunks[0].Length, chunks[0].ChunkData);
                frame.Delay     = fctl.DelayNum == 0 ? 10 : (int)(fctl.DelayNum / (fctl.DelayDen == 0 ? 100d : fctl.DelayDen) * 1000d);
                frame.Width     = fctl.Width;
                frame.Height    = fctl.Height;
                frame.Left      = fctl.XOffset;
                frame.Top       = fctl.YOffset;
                frame.ColorType = Ihdr.ColorType;
                frame.BitDepth  = Ihdr.BitDepth;
                frame.DisposeOp = fctl.DisposeOp;
                frame.BlendOp   = fctl.BlendOp;

                using (var stream = new MemoryStream())
                {
                    //Png signature, 8 bytes.
                    stream.WriteBytes(new byte[] { 137, 80, 78, 71, 13, 10, 26, 10 });

                    //Image header chunk. 25 bytes.
                    Ihdr.Write(stream, fctl.Width, fctl.Height);

                    //Any other auxiliar chunks.
                    foreach (var other in otherChunks)
                    {
                        other.Write(stream);
                    }

                    //Frame has multiple chunks.
                    if (chunks.Count > 2)
                    {
                        var datas = new List <byte[]>();

                        //Data chunks.
                        for (var i = 1; i < chunks.Count; i++)
                        {
                            switch (chunks[i].ChunkType)
                            {
                            case "fdAT":
                            {
                                var fdat = FdatChunk.Read(chunks[i].Length, chunks[i].ChunkData);
                                datas.Add(fdat.FrameData);
                                break;
                            }

                            case "IDAT":
                            {
                                var idat = IdatChunk.Read(chunks[i].Length, chunks[i].ChunkData);
                                datas.Add(idat.FrameData);
                                break;
                            }
                            }
                        }

                        //Write combined frame data.
                        var length = datas.Sum(s => s.Length);

                        stream.WriteUInt32(BitHelper.ConvertEndian((uint)length));                                                                      //4 bytes.
                        stream.WriteBytes(Encoding.ASCII.GetBytes("IDAT"));                                                                             //4 bytes.
                        stream.WriteBytes(datas.SelectMany(s => s).ToArray());                                                                          //XX bytes.
                        stream.WriteUInt32(BitHelper.ConvertEndian(CrcHelper.Calculate(stream.PeekBytes(stream.Position - (length + 4), length + 4)))); //CRC, 4 bytes.
                    }
                    else
                    {
                        switch (chunks[1].ChunkType)
                        {
                        case "fdAT":
                        {
                            var fdat = FdatChunk.Read(chunks[1].Length, chunks[1].ChunkData);
                            fdat.Write(stream);
                            break;
                        }

                        case "IDAT":
                        {
                            var idat = IdatChunk.Read(chunks[1].Length, chunks[1].ChunkData);
                            idat.Write(stream);
                            break;
                        }
                        }
                    }

                    //End chunk.
                    stream.WriteUInt32(BitHelper.ConvertEndian(0u));                                                            //Chunk length, 4 bytes.
                    stream.WriteBytes(Encoding.ASCII.GetBytes("IEND"));                                                         //Chunk type, 4 bytes.
                    stream.WriteUInt32(BitHelper.ConvertEndian(CrcHelper.Calculate(stream.PeekBytes(stream.Position - 4, 4)))); //CRC, 4 bytes.

                    //Gets the whole Png.
                    frame.ImageData = stream.ToArray();
                }
            }
            else
            {
                //This is not supposed to happen.
                //All chunks with an FrameGroupId are grouped with a starting fcTL, ending with a IDAT or fdAT chunk.
                LogWriter.Log(new Exception("Missing fcTL on frame number " + index), $"It was not possible to read frame number {index}");
                return(null);
            }

            return(frame);
        }
Ejemplo n.º 7
0
        internal void AddFrame(string path, Int32Rect rect, int delay = 66)
        {
            using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                if (IsFirstFrame)
                {
                    //Png Header: 8 bytes.
                    InternalStream.WriteBytes(stream.ReadBytes(8));

                    //IHDR chunk. 13 bytes (Length + Type + CRC, 4 bytes each) = 25 bytes.
                    InternalStream.WriteBytes(stream.ReadBytes(25));

                    //acTL: Animation control chunk. 8 bytes (Length + Type + CRC, 4 bytes each) = 20 bytes.
                    InternalStream.WriteUInt32(BitHelper.ConvertEndian(8u));                                                                              //Length, 4 bytes.
                    InternalStream.WriteBytes(Encoding.ASCII.GetBytes("acTL"));                                                                           //Chunk type, 4 bytes.
                    InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)FrameCount));                                                                //NumFrames, 4 bytes.
                    InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)RepeatCount));                                                               //NumPlays, 4 bytes.
                    InternalStream.WriteUInt32(BitHelper.ConvertEndian(CrcHelper.Calculate(InternalStream.PeekBytes(InternalStream.Position - 12, 12)))); //CRC, 4 bytes.
                }

                //fcTL: Frame control chunk. 26 bytes (Length + Type + CRC, 4 bytes each) = 38 bytes.
                InternalStream.WriteUInt32(BitHelper.ConvertEndian(26u));                    //Length, 4 bytes.
                InternalStream.WriteBytes(Encoding.ASCII.GetBytes("fcTL"));                  //Chunk type, 4 bytes.
                InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)SequenceNumber++)); //SequenceNumber, 4 bytes.
                InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)rect.Width));       //Width, 4 bytes.
                InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)rect.Height));      //Height, 4 bytes.
                InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)rect.X));           //OffsetX, 4 bytes.
                InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)rect.Y));           //OffsetY, 4 bytes.
                InternalStream.WriteUInt16(BitHelper.ConvertEndian((ushort)delay));          //Delay numerator, 2 bytes.
                InternalStream.WriteUInt16(BitHelper.ConvertEndian((ushort)1000));           //Delay denominator, 2 bytes.

                if (IsFirstFrame)
                {
                    InternalStream.WriteByte((byte)DisposeOps.None); //DisposeOp, 1 byte.
                    InternalStream.WriteByte((byte)BlendOps.Source); //BlendOp, 1 byte.
                }
                else
                {
                    InternalStream.WriteByte((byte)DisposeOps.None); //DisposeOp, 1 byte.
                    InternalStream.WriteByte((byte)BlendOps.Over);   //BlendOp, 1 byte.
                }

                InternalStream.WriteUInt32(BitHelper.ConvertEndian(CrcHelper.Calculate(InternalStream.PeekBytes(InternalStream.Position - 30, 30)))); //CRC, 4 bytes.

                //fdAT: Frame data chunk. 4 + n bytes (Length + Type + CRC, 4 bytes each) = 16 + n bytes, where n is the frame data.
                var dataList = GetData(stream);

                foreach (var data in dataList)
                {
                    if (IsFirstFrame)
                    {
                        InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)data.Length));                                                                                           //Length, 4 bytes.
                        InternalStream.WriteBytes(Encoding.ASCII.GetBytes("IDAT"));                                                                                                       //Chunk type, 4 bytes.
                        InternalStream.WriteBytes(data);                                                                                                                                  //Frame data, n bytes.
                        InternalStream.WriteUInt32(BitHelper.ConvertEndian(CrcHelper.Calculate(InternalStream.PeekBytes(InternalStream.Position - (data.Length + 4), data.Length + 4)))); //CRC, 4 bytes.
                    }
                    else
                    {
                        InternalStream.WriteUInt32(BitHelper.ConvertEndian(4 + (uint)data.Length));                                                                                       //Length, 4 bytes.
                        InternalStream.WriteBytes(Encoding.ASCII.GetBytes("fdAT"));                                                                                                       //Chunk type, 4 bytes.
                        InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)SequenceNumber++));                                                                                      //SequenceNumber, 4 bytes.
                        InternalStream.WriteBytes(data);                                                                                                                                  //Frame data, n bytes.
                        InternalStream.WriteUInt32(BitHelper.ConvertEndian(CrcHelper.Calculate(InternalStream.PeekBytes(InternalStream.Position - (data.Length + 8), data.Length + 8)))); //CRC, 4 bytes.
                    }
                }

                IsFirstFrame = false;
            }
        }
Ejemplo n.º 8
0
 /// <summary>
 /// Determines whether [is update package available].
 /// </summary>
 /// <returns></returns>
 public bool IsUpdatePackageAvailable()
 {
     return(LatestVersion != null && File.Exists(ConstantsBase.UpdatePath) &&
            String.Equals(CrcHelper.GetCrc32HashToString(ConstantsBase.UpdatePath), LatestVersion.CrcHash,
                          StringComparison.CurrentCultureIgnoreCase));
 }
Ejemplo n.º 9
0
 /// <summary>
 /// Simple method to compare checksums
 /// </summary>
 /// <param name="toComputeData">Actual hash</param>
 /// <param name="expectedHash">To be expetected hash</param>
 /// <returns></returns>
 private static bool CompareCrcHashes(byte[] toComputeData, string expectedHash)
 {
     return (int.Parse(CrcHelper.GetCrc32HashFromMemoryToString(toComputeData).ToLower(), System.Globalization.NumberStyles.HexNumber) == int.Parse(expectedHash.ToLower(), System.Globalization.NumberStyles.HexNumber));
 }
Ejemplo n.º 10
0
        /// <summary>
        /// Reads index file and creates deserialized data
        /// </summary>
        /// <param name="filePath">Path to index file</param>
        /// <param name="indexKey">Index XTEA key</param>
        /// <param name="parentFile">Parent file</param>
        /// <returns></returns>
        public static List<IndexItem> ReadIndexFile(string filePath, byte[] indexKey, string parentFile)
        {
            byte[] plainData = NormalizeIndexFile(filePath, indexKey);

            if (plainData == null)
                return null;

            var rtnList = new List<IndexItem>();

            rtnList.Clear();

            //Remove header
            var dataBuffer = new byte[plainData.Length - 12];
            Array.Copy(plainData, 12, dataBuffer, 0, plainData.Length - 12);

            //Convert byte[] to int
            int fileCount = IOHelper.ReadIntFromArray(plainData, 8, 4);
            int indexVersion = IOHelper.ReadIntFromArray(plainData, 4, 4);

            if (indexVersion != 2)
            {
                //WindowLog.LogOutputMessage(Log.LogId.ETER_INDEX_WRONG_IDX_VERSION_LOG, args: fileCount); TODO
                return null;
            }

            //Holding variables
            var Index = new byte[4];
            var FileName = new byte[161];
            var FilenameCRC = new byte[4];
            var DiskSize = new byte[4];
            var DataSize = new byte[4];
            var CRC = new byte[4];
            var FileOffset = new byte[4];
            var PackedType = new byte[1];

            //Loop through files
            for (int i = 0; i < fileCount; i++)
            {
                Array.Copy(dataBuffer, 0 + (192 * i), Index, 0, 4);

                Array.Copy(dataBuffer, 4 + (192 * i), FileName, 0, 161);

                Array.Copy(dataBuffer, 168 + (192 * i), FilenameCRC, 0, 4);

                Array.Copy(dataBuffer, 172 + (192 * i), DiskSize, 0, 4);

                Array.Copy(dataBuffer, 176 + (192 * i), DataSize, 0, 4);

                Array.Copy(dataBuffer, 180 + (192 * i), CRC, 0, 4);

                Array.Copy(dataBuffer, 184 + (192 * i), FileOffset, 0, 4);

                Array.Copy(dataBuffer, 188 + (192 * i), PackedType, 0, 1);

                string tempFileName = Encoding.Default.GetString(FileName).Replace("\0", "");

                string fileName = tempFileName.Contains("type\"") ? tempFileName.Substring(0, tempFileName.IndexOf("type\"", StringComparison.Ordinal) - 1) : tempFileName;

                // Fail-safe to make sure the path is valid
                if (!CrcHelper.GetCrc32HashFromMemoryToByteArray(Encoding.Default.GetBytes(fileName)).SequenceEqual(FilenameCRC))
                {
                    for (int j = 1; j < fileName.Length; j++)
                    {
                        var newFileName = fileName.Substring(0, j);
                        if (
                            CrcHelper.GetCrc32HashFromMemoryToByteArray(Encoding.Default.GetBytes(newFileName)).Reverse().ToArray()
                                .SequenceEqual(FilenameCRC))
                        {
                            fileName = newFileName;
                            break;
                        }
                    }
                }

                // New drive point?
                //DPHelper.CheckIfContainsDrivePoint(fileName); TODO

                rtnList.Add(new IndexItem(BitConverter.ToInt32(Index, 0),
                    fileName,
                    System.Text.RegularExpressions.Regex.Replace(BitConverter.ToString(FilenameCRC), "-", ""),
                    BitConverter.ToInt32(DiskSize, 0),
                    BitConverter.ToInt32(DataSize, 0),
                    BitConverter.ToInt32(CRC, 0).ToString("X"),
                    BitConverter.ToInt32(FileOffset, 0),
                    Convert.ToInt32(PackedType[0]),
                    parentFile));
            }

            return rtnList;
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Buils EIX and EPK files
        /// </summary>
        /// <param name="list">Deserialized list</param>
        /// <param name="packFilePath">Path to EPK file, including the name</param>
        /// <param name="unpackedFilesPath">Path to unpacked files</param>
        /// <param name="indexKey">Index XTEA key</param>
        /// <param name="packKey">Pack XTEA key</param>
        /// <param name="errorLogCallBack"></param>
        /// <param name="progressCallback">Callback if progress updates are needed</param>
        /// <returns></returns>
        public static bool BuildIndexAndPackFiles(
            List<IndexItem> list,
            string packFilePath,
            string unpackedFilesPath,
            byte[] indexKey,
            byte[] packKey,
            Action<ErrorItem> errorLogCallBack,
            Action<int, int> progressCallback,
            Action fatalErrorCallback)
        {
            using (var fStream = new MemoryStream())
            {
                packFilePath = packFilePath.Replace("\\", "/");
                // Check if directory exists
                string directoryPath = packFilePath.Substring(0, packFilePath.LastIndexOf("/"));
                Directory.CreateDirectory(directoryPath);

                // Create stream to EPK file
                var epkStream = new FileStream(EterHelper.ReplaceWithEpkExt(packFilePath), FileMode.Create);

                // Size from header for each file
                int decompressedSize = 0;
                int compressedSize = 0;
                uint encryptedSize = 0;

                // File counter to index files
                int indexCount = 0;

                // Progress variables
                double actionProgress = 0;

                // FileOffset holder (EPK stream's length)
                int fileOffset = 0;

                // Write first header to EIX file
                fStream.Write(ConstantsBase.EterFourCc, 0, ConstantsBase.EterFourCc.Length);
                fStream.Write(BitConverter.GetBytes(2), 0, 4);
                fStream.Write(BitConverter.GetBytes(list.Count), 0, 4);

                try
                {
                    foreach (IndexItem item in list)
                    {
                        // Loop through items
                        var fileName = new byte[161];
                        var fileNameCrc = new byte[4];

                        //Index item's structure (totalizing 192 bytes)
                        #region Byte Holders

                        var fileIndex = new byte[4];
                        var realDataSize = new byte[4];
                        var dataSize = new byte[4];
                        var dataCrc = new byte[4];
                        var dataOffset = new byte[4];
                        var padding3B = new byte[3];

                        #endregion

                        // Set all backslashs to forwards slashes
                        item.Filename = item.Filename.Replace('\\', '/');

                        // Get raw data
                        byte[] rawData = IOHelper.ReadFile(unpackedFilesPath + item.Filename);

                        // Header sizees
                        int encryptedFileSize = 0;
                        int compressedFileSize = 0;
                        int decompressedFileSize = 0;

                        // Set real data & decompressed size to raw data's lenth
                        realDataSize = BitConverter.GetBytes(rawData.Length);
                        decompressedFileSize = rawData.Length;

                        // Set fileoffset to actual stream's length
                        fileOffset = (int)epkStream.Length;

                        #region File Type Processing

                        // Switch through the 3 possible cases
                        switch (item.PackType)
                        {
                            case 0:
                                // Write data to EPK stream
                                epkStream.Write(rawData, 0, rawData.Length);

                                // Set data size equal to raw data since no compression nor encrypted occured
                                dataSize = BitConverter.GetBytes(rawData.Length);
                                break;
                            case 1:
                            case 2:
                                // Compress data
                                byte[] compressedDataBuffer = LzoHelper.CompressData(rawData.Length, rawData);

                                // Create buffer to hold header + compressedData
                                byte[] compressedDataWithHeaderBuffer = new byte[compressedDataBuffer.Length + 4];

                                // Copy header and compressedData to previously created buffer
                                Array.Copy(ConstantsBase.LzoFourCc, 0, compressedDataWithHeaderBuffer, 0, 4);
                                Array.Copy(compressedDataBuffer, 0, compressedDataWithHeaderBuffer, 4, compressedDataBuffer.Length);

                                // Set dataSize to compressedSize (since it assumes it's type 1)
                                dataSize = BitConverter.GetBytes(compressedDataWithHeaderBuffer.Length + 16);

                                // Set compressedSize
                                compressedFileSize = compressedDataBuffer.Length;

                                // If type 2
                                if (item.PackType == 2)
                                {
                                    // Get encrypted size (ALWAYS the upper multiple)
                                    encryptedFileSize = GetUpperMultiple(compressedDataWithHeaderBuffer.Length);

                                    // Resize data to fit encryptedSize
                                    Array.Resize(ref compressedDataWithHeaderBuffer, encryptedFileSize);

                                    // Encrypt Data
                                    Xtea.Encrypt2(ref compressedDataWithHeaderBuffer, packKey);

                                    // Set dataSize to encryptedData + header
                                    dataSize = BitConverter.GetBytes(compressedDataWithHeaderBuffer.Length + 16);
                                }

                                // Write header of file to EPK stream
                                epkStream.Write(ConstantsBase.LzoFourCc, 0, 4);
                                epkStream.Write(BitConverter.GetBytes(encryptedFileSize), 0, 4);
                                epkStream.Write(BitConverter.GetBytes(compressedFileSize), 0, 4);
                                epkStream.Write(BitConverter.GetBytes(decompressedFileSize), 0, 4);

                                // Write actual data
                                epkStream.Write(compressedDataWithHeaderBuffer, 0, compressedDataWithHeaderBuffer.Length);
                                break;
                        }

                        #endregion

                        #region Building index file

                        // Check if string replacment is needed
                        string virtualPathFile = DrivePointManager.InsertDrivePoints(item.Filename);

                        // Populate byte[] with data
                        fileIndex = BitConverter.GetBytes(item.Index);
                        byte[] fileNameTemp = Encoding.Default.GetBytes(virtualPathFile);
                        fileNameCrc = CrcHelper.GetCrc32HashFromMemoryToByteArray(Encoding.Default.GetBytes(virtualPathFile));
                        realDataSize = (realDataSize == null) ? BitConverter.GetBytes(item.DiskSize) : realDataSize;
                        dataSize = (dataSize == null) ? BitConverter.GetBytes(item.Size) : dataSize;
                        dataCrc = CrcHelper.GetCrc32HashToByteArray(unpackedFilesPath + item.Filename);
                        dataOffset = BitConverter.GetBytes(fileOffset);
                        var compressedType = (byte)item.PackType;

                        // Check if filename buffer is expectedSize
                        if (fileNameTemp.Length != 161)
                        {
                            Array.Copy(fileNameTemp, 0, fileName, 0, fileNameTemp.Length);
                        }

                        // Write data to EIX's stream
                        fStream.Write(fileIndex, 0, fileIndex.Length);
                        fStream.Write(fileName, 0, 161);
                        fStream.Write(padding3B, 0, padding3B.Length);
                        fStream.Write(fileNameCrc.Reverse().ToArray(), 0, fileNameCrc.Length);
                        fStream.Write(realDataSize, 0, realDataSize.Length);
                        fStream.Write(dataSize, 0, dataSize.Length);
                        fStream.Write(dataCrc.Reverse().ToArray(), 0, dataCrc.Length);
                        fStream.Write(dataOffset, 0, dataOffset.Length);
                        fStream.WriteByte(compressedType);
                        fStream.Write(padding3B, 0, padding3B.Length);

                        indexCount++;
                        #endregion

                        // Update progress
                        actionProgress = (indexCount / (double)list.Count * 100.0);
                        progressCallback(0, (int)actionProgress);
                    }
                }
                catch (Exception ex)
                {
                    //WindowLog.LogExceptioToFile(ex.ToString()); TODO
                    fatalErrorCallback();
                    throw;
                }

                // Assign current stream's lenght to decmopressedSize
                decompressedSize = (int)fStream.Length;

                // Buffer to hold compressedData
                byte[] compressedData = LzoHelper.CompressData(decompressedSize, fStream.ToArray());

                // Buffer with compressedData + MCOZ header
                byte[] compressedDataWithHeader = new byte[compressedData.Length + 4];

                // Copy Header to buffer
                Array.Copy(ConstantsBase.LzoFourCc, 0, compressedDataWithHeader, 0, 4);

                // Copy data to buffer
                Array.Copy(compressedData, 0, compressedDataWithHeader, 4, compressedData.Length);

                // Save compressedSize
                compressedSize = compressedData.Length;

                // Save encryptedSize (round to upper multiple)
                encryptedSize = (uint)GetUpperMultiple(compressedSize + 4);

                // Resize array to fit new size
                Array.Resize(ref compressedDataWithHeader, (int)encryptedSize);

                // Encrypt data
                Xtea.Encrypt2(ref compressedDataWithHeader, indexKey);

                // Create buffer to hold final data + header
                var outputFileBuffer = new byte[compressedDataWithHeader.Length + 16];

                // Copy header to buffer
                Array.Copy(ConstantsBase.LzoFourCc, 0, outputFileBuffer, 0, 4);
                Array.Copy(BitConverter.GetBytes(encryptedSize), 0, outputFileBuffer, 4, 4);
                Array.Copy(BitConverter.GetBytes(compressedSize), 0, outputFileBuffer, 8, 4);
                Array.Copy(BitConverter.GetBytes(decompressedSize), 0, outputFileBuffer, 12, 4);

                // Copy data to buffer
                Array.Copy(compressedDataWithHeader, 0, outputFileBuffer, 16, compressedDataWithHeader.Length);

                // Close stream
                epkStream.Close();
                epkStream.Dispose();

                // Save file
                File.WriteAllBytes(EterHelper.ReplaceWithEixExt(packFilePath), outputFileBuffer);

                return true;
            }
        }