Beispiel #1
0
 /// <summary>
 /// 读取消息头,如果有Gzip压缩时自动解压字节流
 /// </summary>
 /// <returns></returns>
 /// <exception cref="OverflowException"></exception>
 public MessageHead ReadHeadGzip()
 {
     try
     {
         MessageHead head = new MessageHead();
         head.HasGzip      = true;
         head.PacketLength = Length;
         if (CheckGzipBuffer())
         {
             byte[] gzipData = PopBuffer();
             head.GzipLength = gzipData.Length;
             //gzip格式500+gzip( 1000+ XXXXXX)
             //启用7z?
             byte[] deZipData = LZMA.Decompress(gzipData, 0);// GzipUtils.DeCompress(gzipData, 0, gzipData.Length);
             WriteByte(deZipData);
             Reset();
         }
         head.TotalLength = ReadInt();
         head.ErrorCode   = ReadInt();
         head.MsgId       = ReadInt();
         head.ErrorInfo   = ReadString();
         head.Action      = ReadInt();
         head.St          = ReadString();
         return(head);
     }
     catch (Exception ex)
     {
         string error = string.Format("read to {0}/{1}pos error,\r\nbytes:{2}", Offset, Length, ToHexString());
         throw new OverflowException(error, ex);
     }
 }
        public static string Load(string name)
        {
            string script = null;

            var index = name.IndexOf("(Clone)");

            if (index >= 0)
            {
                name = name.Substring(0, index);
            }

#if UNITY_EDITOR
            string filename = Application.dataPath + kLuaScriptDebugPath + "/" + name + ".lua";
            try
            {
                var fs = new StreamReader(filename, Encoding.UTF8);
                script = fs.ReadToEnd();
                fs.Close();
                fs.Dispose();
            }
            catch (System.Exception e)
            { }
#else
            var ta = ResourceUtils.Load <TextAsset>(kLuaScriptPath + "/" + name);
            if (ta == null)
            {
                script_cache_[name] = null;
                return(null);
            }
            var bytes = LZMA.Decompress(ta.bytes);
            script = Encoding.UTF8.GetString(bytes);
#endif
            return(script);
        }
Beispiel #3
0
        protected ShockwaveFlash(FlashReader input)
            : this(false)
        {
            Compression = (CompressionKind)input.ReadString(3)[0];
            Version     = input.ReadByte();
            FileLength  = input.ReadUInt32();

            switch (Compression)
            {
            case CompressionKind.LZMA:
            {
                byte[] decompressed = LZMA.Decompress(input.BaseStream, ((int)FileLength - 8));
                _input = new FlashReader(decompressed);
                break;
            }

            case CompressionKind.ZLIB:
            {
                _input = ZLIB.WrapDecompressor(input.BaseStream);
                break;
            }

            case CompressionKind.None:
            {
                _input = input;
                break;
            }
            }
            Frame = new FrameRecord(_input);
        }
Beispiel #4
0
        public MemoryStream DecompressEntry(int Index, FileStream fs)
        {
            MemoryStream    result = new MemoryStream();
            FileEntryStruct e      = Files[Index];
            uint            count  = 0;

            byte[] inputBlock;
            byte[] outputBlock = new byte[Header.MaxBlockSize];
            long   left        = e.RealUncompressedSize;

            fs.Seek(e.BlockOffsets[0], SeekOrigin.Begin);
            byte[] buff;
            if (e.BlockSizeTableIndex == 0xFFFFFFFF)
            {
                buff = new byte[e.RealUncompressedSize];
                fs.Read(buff, 0, buff.Length);
                result.Write(buff, 0, buff.Length);
            }
            else
            {
                while (left > 0)
                {
                    uint compressedBlockSize = e.BlockSizes[count];
                    if (compressedBlockSize == 0)
                    {
                        compressedBlockSize = Header.MaxBlockSize;
                    }
                    if (compressedBlockSize == Header.MaxBlockSize || compressedBlockSize == left)
                    {
                        buff = new byte[compressedBlockSize];
                        fs.Read(buff, 0, buff.Length);
                        result.Write(buff, 0, buff.Length);
                        left -= compressedBlockSize;
                    }
                    else
                    {
                        var uncompressedBlockSize = (uint)Math.Min(left, Header.MaxBlockSize);
                        if (compressedBlockSize < 5)
                        {
                            throw new Exception("compressed block size smaller than 5");
                        }
                        inputBlock = new byte[compressedBlockSize];
                        fs.Read(inputBlock, 0, (int)compressedBlockSize);
                        uint actualUncompressedBlockSize = uncompressedBlockSize;
                        uint actualCompressedBlockSize   = compressedBlockSize;

                        outputBlock = LZMA.Decompress(inputBlock, actualUncompressedBlockSize);
                        if (outputBlock.Length != actualUncompressedBlockSize)
                        {
                            throw new Exception("Decompression Error");
                        }
                        result.Write(outputBlock, 0, (int)actualUncompressedBlockSize);
                        left -= uncompressedBlockSize;
                    }
                    count++;
                }
            }
            return(result);
        }
Beispiel #5
0
        public void ExtractEntry(DLCEntry entry, Stream input, Stream output)
        {
            input.JumpTo(entry.dataOffset);
            if (entry.compressedBlockSizesIndex == -1)
            {
                output.WriteFromStream(input, entry.uncomprSize);
            }
            else
            {
                var  uncompressedBlockBuffers = new List <byte[]>();
                var  compressedBlockBuffers   = new List <byte[]>();
                var  blockBytesLeft           = new List <long>();
                long bytesLeft = entry.uncomprSize;
                for (int j = 0; j < entry.numBlocks; j++)
                {
                    blockBytesLeft.Add(bytesLeft);
                    int compressedBlockSize   = blockSizes[entry.compressedBlockSizesIndex + j];
                    int uncompressedBlockSize = (int)Math.Min(bytesLeft, maxBlockSize);
                    if (compressedBlockSize == 0)
                    {
                        compressedBlockSize = (int)maxBlockSize;
                    }
                    compressedBlockBuffers.Add(input.ReadToBuffer(compressedBlockSize));
                    uncompressedBlockBuffers.Add(null);
                    bytesLeft -= uncompressedBlockSize;
                }

                Parallel.For(0, entry.numBlocks, j =>
                {
                    int compressedBlockSize   = blockSizes[entry.compressedBlockSizesIndex + (int)j];
                    int uncompressedBlockSize = (int)Math.Min(blockBytesLeft[(int)j], maxBlockSize);
                    if (compressedBlockSize == 0 || compressedBlockSize == blockBytesLeft[(int)j])
                    {
                        uncompressedBlockBuffers[(int)j] = compressedBlockBuffers[(int)j];
                    }
                    else
                    {
                        uncompressedBlockBuffers[(int)j] = LZMA.Decompress(compressedBlockBuffers[(int)j], (uint)uncompressedBlockSize);
                        if (uncompressedBlockBuffers[(int)j].Length == 0)
                        {
                            throw new Exception();
                        }
                    }
                });

                for (int j = 0; j < entry.numBlocks; j++)
                {
                    output.WriteFromBuffer(uncompressedBlockBuffers[j]);
                }
            }
        }
Beispiel #6
0
        public static string Load(string name)
        {
            string script = null;

            var index = name.IndexOf("(Clone)");

            if (index >= 0)
            {
                name = name.Substring(0, index);
            }

            if (include_files.TryGetValue(name, out script))
            {
                return(script);
            }

            var fullpath = string.Concat(script_path, LuaScriptRuntimePath, "/", name, ".lua");

            script = LoadScript(name, fullpath);
            if (!string.IsNullOrEmpty(script))
            {
                return(script);
            }

            Debug.LogError(fullpath);

#if UNITY_EDITOR
            fullpath = string.Concat(script_path, kLuaScriptDevelopmentPath, "/", name, ".lua");
            script   = LoadScript(name, fullpath);
            if (!string.IsNullOrEmpty(script))
            {
                return(script);
            }
#endif

            var ta = Resources.Load <TextAsset>(string.Concat(kLuaScriptResourcePath, "/", name));
            if (ta == null)
            {
                include_files[name] = null;
                return(null);
            }

            var bytes = LZMA.Decompress(ta.bytes);
            script = Encoding.UTF8.GetString(bytes);
            include_files[name] = script;
            return(script);
        }
Beispiel #7
0
        /// <summary>
        /// Read the node hierarchy from the specified buffer.
        /// </summary>

        static public DataNode Read(byte[] bytes, SaveType type)
        {
            if (bytes == null || bytes.Length < 4)
            {
                return(null);
            }

            if (type == SaveType.Text)
            {
                MemoryStream stream = new MemoryStream(bytes);
                StreamReader reader = new StreamReader(stream);
                DataNode     node   = Read(reader);
                reader.Close();
                return(node);
            }
            else if (type == SaveType.Compressed)
            {
                bool skipPrefix = true;

                for (int i = 0; i < 4; ++i)
                {
                    if (bytes[i] != mLZMA[i])
                    {
                        skipPrefix = false;
                        break;
                    }
                }

                bytes = LZMA.Decompress(bytes, skipPrefix ? 4 : 0);
            }
            {
                MemoryStream stream = new MemoryStream(bytes);
                BinaryReader reader = new BinaryReader(stream);
                DataNode     node   = reader.ReadObject <DataNode>();
                reader.Close();
                return(node);
            }
        }
Beispiel #8
0
        public static Dictionary <uint, TextureMapEntry> LoadTextureMap(MEGame game)
        {
            // Read the vanilla file name table
            List <string> packageNames = null;
            {
                using var stream = File.OpenRead(Path.Combine(App.ExecFolder, @"TextureMap", $@"vanilla{game}.bin"));
                if (stream.ReadStringASCII(4) != @"MD5T")
                {
                    throw new Exception(@"Header of MD5 table doesn't match expected value!");
                }

                //Decompress
                var decompressedSize = stream.ReadInt32();
                //var compressedSize = stream.Length - stream.Position;

                var compressedBuffer   = stream.ReadToBuffer(stream.Length - stream.Position);
                var decompressedBuffer = LZMA.Decompress(compressedBuffer, (uint)decompressedSize);
                if (decompressedBuffer.Length != decompressedSize)
                {
                    throw new Exception(@"Vanilla database failed to decompress");
                }

                //Read
                MemoryStream table      = new MemoryStream(decompressedBuffer);
                int          numEntries = table.ReadInt32();
                packageNames = new List <string>(numEntries);
                //Package names
                for (int i = 0; i < numEntries; i++)
                {
                    //Read entry
                    packageNames.Add(table.ReadStringASCIINull().Replace('/', '\\').TrimStart('\\'));
                }
            }


            var tmf = Path.Combine(App.ExecFolder, @"TextureMap", $@"vanilla{game}Map.bin");

            using var fs = File.OpenRead(tmf);

            // read the precomputed vanilla texture map.
            // this map will help identify vanilla textures

            var magic = fs.ReadInt32();

            if (magic != 0x504D5443)
            {
                throw new Exception(@"Invalid precomputed texture map! Wrong magic");
            }
            var decompSize = fs.ReadUInt32();

            byte[] compresssed = fs.ReadToBuffer(fs.ReadInt32());

            var texMap = new MemoryStream(LZMA.Decompress(compresssed, decompSize));

            texMap.Seek(8, SeekOrigin.Begin); // skip magic, ???

            var textureCount = texMap.ReadInt32();
            Dictionary <uint, TextureMapEntry> map = new Dictionary <uint, TextureMapEntry>(textureCount);

            for (int i = 0; i < textureCount; i++)
            {
                var entry = TextureMapEntry.ReadTextureMapEntry(texMap, game, packageNames);
                map[entry.CRC] = entry;
            }

            return(map);
        }
        public static void DecompressTexture(byte[] DecompressedBuffer, MemoryStream stream, StorageTypes type, int uncompressedSize, int compressedSize)
        {
            uint blockTag = stream.ReadUInt32();

            if (blockTag != textureTag)
            {
                throw new Exception("Texture tag wrong");
            }
            uint blockSize = stream.ReadUInt32();

            if (blockSize != maxBlockSize)
            {
                throw new Exception("Texture header broken");
            }
            uint compressedChunkSize   = stream.ReadUInt32();
            uint uncompressedChunkSize = stream.ReadUInt32();

            if (uncompressedChunkSize != uncompressedSize)
            {
                throw new Exception("Texture header broken");
            }

            uint blocksCount = (uncompressedChunkSize + maxBlockSize - 1) / maxBlockSize;

            if ((compressedChunkSize + SizeOfChunk + SizeOfChunkBlock * blocksCount) != compressedSize)
            {
                throw new Exception("Texture header broken");
            }

            var blocks = new List <ChunkBlock>();

            for (uint b = 0; b < blocksCount; b++)
            {
                ChunkBlock block = new ChunkBlock
                {
                    comprSize   = stream.ReadUInt32(),
                    uncomprSize = stream.ReadUInt32()
                };
                blocks.Add(block);
            }

            for (int b = 0; b < blocks.Count; b++)
            {
                ChunkBlock block = blocks[b];
                block.compressedBuffer   = stream.ReadToBuffer(blocks[b].comprSize);
                block.uncompressedBuffer = new byte[maxBlockSize * 2];
                blocks[b] = block;
            }

            Parallel.For(0, blocks.Count, b =>
            {
                uint dstLen;
                ChunkBlock block = blocks[b];
                if (type == StorageTypes.extLZO || type == StorageTypes.pccLZO)
                {
                    dstLen = LZO2.Decompress(block.compressedBuffer, block.comprSize, block.uncompressedBuffer);
                }
                else if (type == StorageTypes.extZlib || type == StorageTypes.pccZlib)
                {
                    dstLen = Zlib.Decompress(block.compressedBuffer, block.comprSize, block.uncompressedBuffer);
                }
                else if (type == StorageTypes.extLZMA)
                {
                    block.uncompressedBuffer = LZMA.Decompress(block.compressedBuffer, block.uncomprSize);
                    dstLen = (uint)block.uncompressedBuffer.Length;
                }
                else
                {
                    throw new Exception("Compression type not expected!");
                }
                if (dstLen != block.uncomprSize)
                {
                    throw new Exception("Decompressed data size not expected!");
                }
            });

            int dstPos = 0;

            for (int b = 0; b < blocks.Count; b++)
            {
                Buffer.BlockCopy(blocks[b].uncompressedBuffer, 0, DecompressedBuffer, dstPos, (int)blocks[b].uncomprSize);
                dstPos += (int)blocks[b].uncomprSize;
            }
        }
Beispiel #10
0
        private static void ConvertToPreset(string fileName)
        {
            using (var stream = File.OpenRead(fileName))
            {
                using (var br = new BinaryReader(stream))
                {
                    var buf = new byte[IEND_MAGIC.Length];

                    var pos = 0;
                    for (;; stream.Position = ++pos)
                    {
                        var len = stream.Read(buf, 0, buf.Length);

                        if (len != IEND_MAGIC.Length)
                        {
                            Console.WriteLine($"WARN: {fileName} is not a valid PNG file.");
                            return;
                        }

                        if (BytesEqual(buf, IEND_MAGIC))
                        {
                            break;
                        }
                    }

                    // Skip CRC
                    stream.Position += 4;

                    var presetStartPos = stream.Position;

                    if (br.ReadString() != "CM3D2_PRESET")
                    {
                        Console.WriteLine("PNG file does not contain a preset!");
                        return;
                    }

                    var extDataPos = FindExtData(stream);

                    var dir  = Path.GetDirectoryName(Path.GetFullPath(fileName));
                    var name = Path.GetFileNameWithoutExtension(fileName);

                    using (var presetStream = File.Create(Path.Combine(dir, $"{name}.preset")))
                    {
                        Copy(stream, presetStream, presetStartPos,
                             extDataPos - (extDataPos < stream.Length ? EXT_DATA_BEGIN_MAGIC.Length : 0) -
                             presetStartPos);
                    }

                    if (stream.Length - extDataPos <= 0)
                    {
                        return;
                    }

                    stream.Position = extDataPos;
                    using (var ext = LZMA.Decompress(stream, EXT_DATA_END_MAGIC.Length))
                        using (var extOut = File.Create(Path.Combine(dir, $"{name}.preset.expreset.xml")))
                        {
                            Copy(ext, extOut, 0, ext.Length);
                        }
                }
            }
        }
Beispiel #11
0
        public MemoryStream DecompressEntry(FileEntryStruct e)
        {
            //Debug.WriteLine("Decompressing " + e.FileName);
            MemoryStream result = new MemoryStream();
            uint         count  = 0;

            byte[]     inputBlock;
            long       left = e.RealUncompressedSize;
            FileStream fs   = new FileStream(FileName, FileMode.Open, FileAccess.Read);

            fs.Seek(e.BlockOffsets[0], SeekOrigin.Begin);
            byte[] buff;
            if (e.BlockSizeTableIndex == 0xFFFFFFFF)
            {
                buff = new byte[e.RealUncompressedSize];
                fs.Read(buff, 0, buff.Length);
                result.Write(buff, 0, buff.Length);
            }
            else
            {
                while (left > 0)
                {
                    uint compressedBlockSize = e.BlockSizes[count];
                    if (compressedBlockSize == 0)
                    {
                        compressedBlockSize = Header.MaxBlockSize;
                    }
                    if (compressedBlockSize == Header.MaxBlockSize || compressedBlockSize == left)
                    {
                        //uncompressed?
                        buff = new byte[compressedBlockSize];
                        fs.Read(buff, 0, buff.Length);

                        result.Write(buff, 0, buff.Length);
                        left -= compressedBlockSize;
                    }
                    else
                    {
                        var uncompressedBlockSize = (uint)Math.Min(left, Header.MaxBlockSize);
                        if (compressedBlockSize < 5)
                        {
                            throw new Exception("compressed block size smaller than 5");
                        }

                        inputBlock = new byte[compressedBlockSize];
                        //Debug.WriteLine($"Decompressing at 0x{fs.Position:X8}");
                        fs.Read(inputBlock, 0, (int)compressedBlockSize);
                        uint actualUncompressedBlockSize = uncompressedBlockSize;
                        if (Header.CompressionScheme == "amzl" /* PC */ || Header.CompressionScheme == "lzma" /* PS3 (it doesn't appear to actually be LZMA!), WiiU */)
                        {
                            //if (Header.CompressionScheme == "lzma")
                            //{
                            //PS3 - This doesn't work. I'm not sure what kind of LZMA this uses but it has seemingly no header
                            //var attachedHeader = new byte[inputBlock.Length + 5];
                            //attachedHeader[0] = 0x5D;
                            ////attachedHeader[1] = (byte) (Header.Version >> 24);
                            ////attachedHeader[2] = (byte)(Header.Version >> 16);
                            ////attachedHeader[3] = (byte)(Header.Version >> 8);
                            ////attachedHeader[4] = (byte) Header.Version;
                            //attachedHeader[1] = (byte)Header.Version;
                            //attachedHeader[2] = (byte)(Header.Version >> 8);
                            //attachedHeader[3] = (byte)(Header.Version >> 16);
                            //attachedHeader[4] = (byte)(Header.Version >> 24);
                            //Buffer.BlockCopy(inputBlock,0,attachedHeader,5, inputBlock.Length);
                            //inputBlock = attachedHeader;
                            //}

                            var outputBlock = LZMA.Decompress(inputBlock, actualUncompressedBlockSize);
                            if (outputBlock.Length != actualUncompressedBlockSize)
                            {
                                throw new Exception("SFAR LZMA Decompression Error");
                            }
                            result.Write(outputBlock, 0, (int)actualUncompressedBlockSize);
                            left -= uncompressedBlockSize;
                            //continue;
                        }

                        if (Header.CompressionScheme == "lzx") //Xbox
                        {
                            var outputBlock  = new byte[actualUncompressedBlockSize];
                            var decompResult = LZX.Decompress(inputBlock, (uint)inputBlock.Length, outputBlock);
                            if (decompResult != 0)
                            {
                                throw new Exception("SFAR LZX Decompression Error");
                            }
                            result.Write(outputBlock, 0, (int)actualUncompressedBlockSize);
                            left -= uncompressedBlockSize;
                        }
                    }
                    count++;
                }
            }
            fs.Close();
            result.Position = 0;
            return(result);
        }
Beispiel #12
0
        public long Save(Stream inputStream,
                         Stream outputStream,
                         string token   = null,
                         byte[] pngData = null,
                         Action <decimal> compressProgress = null,
                         bool doComapre = true,
                         Action <decimal> compareProgress = null)
        {
            long dataSize = 0;

            Action <long, long> _compressProgress = null;

            if (null != compressProgress)
            {
                _compressProgress = (long inSize, long _) => compressProgress(Convert.ToDecimal(inSize) / dataSize);
            }

            //Make png watermarked
            using (BinaryReader binaryReader = new BinaryReader(inputStream))
                using (BinaryWriter binaryWriter = new BinaryWriter(outputStream))
                {
                    if (null == pngData)
                    {
                        pngData = ImageHelper.LoadPngBytes(binaryReader);
                    }
                    else
                    {
                        ImageHelper.SkipPng(binaryReader);
                        Logger.LogDebug("Skip Png:" + inputStream.Position);
                    }

                    dataSize = inputStream.Length - inputStream.Position;

                    binaryWriter.Write(pngData);

                    if (null == token)
                    {
                        token = GuessToken(binaryReader);
                    }

                    switch (token)
                    {
                    case Token.StudioToken:
                        //Studio
                        binaryWriter.Write(new Version(101, 0, 0, 0).ToString());
                        break;

                    case Token.CoordinateToken:
                        //Coordinate
                        binaryWriter.Write(101);
                        break;

                    default:
                        //Chara
                        if (token.IndexOf(Token.CharaToken) >= 0)
                        {
                            binaryWriter.Write(101);
                            break;
                        }

                        throw new Exception("Token not match.");
                    }

                    //為了通過 InvalidSceneFileProtection 和 DragAndDrop
                    binaryWriter.Write(token);

                    using (MemoryStream msCompressed = new MemoryStream())
                    {
                        //PngFile.SkipPng(inputStream);
                        long fileStreamPos = inputStream.Position;

                        LZMA.Compress(
                            inputStream,
                            msCompressed,
                            LzmaSpeed.Fastest,
                            DictionarySize.VeryLarge,
                            _compressProgress
                            );

                        Logger.LogDebug("Start compression test...");
                        if (doComapre)
                        {
                            using (MemoryStream msDecompressed = new MemoryStream())
                            {
                                msCompressed.Seek(0, SeekOrigin.Begin);

                                LZMA.Decompress(msCompressed, msDecompressed);
                                inputStream.Seek(fileStreamPos, SeekOrigin.Begin);
                                msDecompressed.Seek(0, SeekOrigin.Begin);
                                int    bufferSize = 1 << 10;
                                byte[] aByteA     = new byte[(int)bufferSize];
                                byte[] bByteA     = new byte[(int)bufferSize];

                                if ((inputStream.Length - inputStream.Position) != msDecompressed.Length)
                                {
                                    return(0);
                                }

                                for (long i = 0; i < msDecompressed.Length;)
                                {
                                    if (null != compressProgress)
                                    {
                                        compareProgress(Convert.ToDecimal(i) / msDecompressed.Length);
                                    }

                                    inputStream.Read(aByteA, 0, (int)bufferSize);
                                    i += msDecompressed.Read(bByteA, 0, (int)bufferSize);
                                    if (!aByteA.SequenceEqual(bByteA))
                                    {
                                        return(0);
                                    }
                                }
                            }
                        }
                        binaryWriter.Write(msCompressed.ToArray());
                        return(binaryWriter.BaseStream.Length);
                    }
                }
        }
Beispiel #13
0
        public long Load(Stream inputStream,
                         Stream outputStream,
                         string token   = null,
                         byte[] pngData = null,
                         Action <decimal> decompressProgress = null)
        {
            long dataSize = 0;
            Action <long, long> _decompressProgress = null;

            if (null != decompressProgress)
            {
                _decompressProgress = (long inSize, long _) => decompressProgress(Convert.ToDecimal(inSize) / dataSize);
            }

            using (BinaryReader binaryReader = new BinaryReader(inputStream))
                using (BinaryWriter binaryWriter = new BinaryWriter(outputStream))
                {
                    if (null == pngData)
                    {
                        pngData = ImageHelper.LoadPngBytes(binaryReader);
                    }
                    else
                    {
                        ImageHelper.SkipPng(binaryReader);
                        Logger.LogDebug("Skip Png:" + inputStream.Position);
                    }

                    if (!GuessCompressed(binaryReader))
                    {
                        //Extension.Logger.LogDebug("Not a compressed file.");
                        return(0);
                    }

                    try
                    {
                        if (null == token)
                        {
                            token = GuessToken(binaryReader);
                            if (null == token)
                            {
                                throw new FileLoadException();
                            }
                        }
                        bool checkfail = false;

                        switch (token)
                        {
                        case Token.StudioToken:
                            checkfail = !new Version(binaryReader.ReadString()).Equals(new Version(101, 0, 0, 0));
                            break;

                        case Token.CoordinateToken:
                        default:
                            //Token.CharaToken
                            checkfail = 101 != binaryReader.ReadInt32();
                            break;
                        }

                        if (checkfail)
                        {
                            throw new FileLoadException();
                        }
                    }
                    catch (FileLoadException e)
                    {
                        Logger.LogError("Corrupted file");
                        throw e;
                    }
                    try
                    {
                        //Discard token string
                        binaryReader.ReadString();

                        Logger.LogDebug("Start Decompress...");
                        binaryWriter.Write(pngData);

                        dataSize = inputStream.Length - inputStream.Position;
                        LZMA.Decompress(inputStream, outputStream, _decompressProgress);
                    }
                    catch (Exception)
                    {
                        Logger.LogError($"Decompression FAILDED. The file was corrupted during compression or storage.");
                        Logger.LogError($"Do not disable the byte comparison setting next time to avoid this.");
                        throw;
                    }
                    return(binaryWriter.BaseStream.Length);
                }
        }
Beispiel #14
0
        /// <summary>
        /// Patches a ROM in memory, writes to specified writable stream.
        /// </summary>
        /// <param name="inROMStream">The readable and seekable Stream of the input ROM</param>
        /// <param name="patchStream">The readable and seekable Stream of the patch</param>
        /// <param name="outROMStream">The writable and seekable Stream of the output ROM</param>
        /// <param name="prog"></param>
        public static void PatchROM(Stream inROMStream, Stream patchStream, Stream outROMStream, IProgress <float> prog)
        {
            PatchInformation pInfo;

            pInfo = ReadPatchFile(patchStream);

            MemoryStream uncompS04 = new MemoryStream((int)pInfo.Segment04Length);
            MemoryStream uncompGL  = new MemoryStream((int)pInfo.GeoLayoutLength);

            bool validROM = CheckROMBigEndian(inROMStream);

            if (!validROM)
            {
                throw new InvalidROMException("This ROM is not a Big Endian (z64) ROM.");
            }

            // Decompressing the compressed data and checking the ROM's byte order
            patchStream.Seek(0x20, SeekOrigin.Begin);
            byte[] s04arr = new byte[pInfo.compSegment04Length];
            patchStream.Read(s04arr, 0, s04arr.Length);
            MemoryStream s04comp = new MemoryStream(s04arr);

            LZMA.Decompress(s04comp, uncompS04);
            prog?.Report(1);
            if ((pInfo.Features & 2) == 0)
            {
                // Hierarchy (GL) not in Bank04, decompress at default location
                byte[] glarr = new byte[pInfo.compGeoLayoutLength];
                patchStream.Read(glarr, 0, glarr.Length);
                MemoryStream glcomp = new MemoryStream(glarr);
                LZMA.Decompress(glcomp, uncompGL);
                glcomp.Dispose();
            }
            s04comp.Dispose();

            //Writing to ROM str

            outROMStream.Seek(0x2ABCE4, SeekOrigin.Begin);
            outROMStream.Write(BitConverter.GetBytes(pInfo.GeoLayoutSegOffset), 0, 4);
            prog?.Report(3f);
            // Extend S04
            if ((pInfo.Features & 1) == 1)
            {
                outROMStream.Seek(0x2ABCA4, SeekOrigin.Begin);
                outROMStream.Write(new byte[] { 0x01, 0x1A, 0x35, 0xB8, 0x01, 0x1F, 0xFF, 0x00 }, 0, 8);
            }
            prog?.Report(3.2f);
            outROMStream.Seek(Task.Run(() => GetSegmentOffset(outROMStream, 04)).Result, SeekOrigin.Begin);
            outROMStream.Write(uncompS04.GetBuffer(), 0, (int)uncompS04.Length);
            prog?.Report(3.6f);
            if ((pInfo.Features & 2) == 0)
            {
                // GL not in Bank 04, write uncompressed GL
                outROMStream.Seek(pInfo.GeoLayoutStartMargin, SeekOrigin.Begin);
                outROMStream.Write(uncompGL.GetBuffer(), 0, (int)uncompGL.Length);
            }
            prog?.Report(3.8f);

            uncompGL.Dispose();
            uncompS04.Dispose();
            prog?.Report(4);
        }
Beispiel #15
0
        public static void Main(string[] args)
        {
            IntPtr Handle = GetConsoleWindow();

            ShowWindow(Handle, 3);
            SetWindowLong(Handle, -20, (int)GetWindowLong(Handle, -20) ^ 0x80000);
            SetLayeredWindowAttributes(Handle, 0, 227, 0x2);

            Console.Title = "[SHR] | SharpRoyale Asset Downloader | 1.0.0";

            Console.WriteLine(@"
       _________.__                       __________                     .__          
      /   _____/|  |__ _____ _____________\______   \ ____ ___.__._____  |  |   ____  
      \_____  \ |  |  \\__  \\_  __ \____ \|       _//  _ <   |  |\__  \ |  | _/ __ \ 
      /        \|   Y  \/ __ \|  | \/  |_> >    |   (  <_> )___  | / __ \|  |_\  ___/ 
     /_______  /|___|  (____  /__|  |   __/|____|_  /\____// ____|(____  /____/\___  >
             \/      \/     \/      |__|          \/       \/          \/          \/ Asset Downloader");

            Console.SetOut(_Prefixed);
            Console.WriteLine();

            Console.WriteLine("Starting...\n");

            Console.WriteLine("Menu:");
            Console.WriteLine(" -> Press A to check for a new patch.");
            Console.WriteLine(" -> Press B to convert all SC Textures to PNG. [EXPERIMENTAL]");
            Console.WriteLine(" -> Press C to delete the Fingerprint.\n");

_Entry:
            ConsoleKeyInfo _Input = Console.ReadKey(true);

            switch (_Input.Key)
            {
            case ConsoleKey.A:
            {
                Console.WriteLine("Downloading Fingerprint...");

                Hash_Module = new Hash_Module("game.clashroyaleapp.com");

                if (!ReferenceEquals(null, Hash_Module.Fingerprint))
                {
                    Console.SetCursorPosition(0, Console.CursorTop - 1);
                    Console.WriteLine($"Downloaded Fingerprint, Hash: {Hash_Module.Fingerprint.Hash} - Version: {Hash_Module.Fingerprint.Version}.\n");

                    if (!File.Exists("fingerprint.json"))
                    {
                        File.WriteAllText("fingerprint.json", JsonConvert.SerializeObject(Hash_Module.Fingerprint, new JsonSerializerSettings()
                            {
                                Formatting = Formatting.Indented
                            }));

                        Console.WriteLine($"Fingerprint has been saved.");
                    }
                    else
                    {
                        Fingerprint _Fingerprint = JsonConvert.DeserializeObject <Fingerprint>(File.ReadAllText("fingerprint.json"));

                        if (_Fingerprint.Hash == Hash_Module.Fingerprint.Hash)
                        {
                            Console.WriteLine($"No new Patch found.");
                            Console.ReadKey(true);
                            Environment.Exit(0);
                        }
                    }

                    if (!Directory.Exists("Output"))
                    {
                        Directory.CreateDirectory("Output");

                        Console.WriteLine("Output directory has been created.\n");
                    }
                    else
                    {
                        Directory.Delete("Output", true);
                        Directory.CreateDirectory("Output");

                        Console.WriteLine("Output directory has been cleared.\n");
                    }

                    Console.WriteLine($"Downloading {Hash_Module.Fingerprint.Files.Count} Files...\n\n");

                    using (WebClient _Client = new WebClient())
                    {
                        int Downloaded = 0;

                        foreach (var _File in Hash_Module.Fingerprint.Files)
                        {
                            string URL = $"{Settings.Hosts[0]}{Hash_Module.Fingerprint.Hash}/{_File.Name}";

                            try
                            {
                                if (!Directory.Exists($"Output/compressed/{Path.GetDirectoryName(_File.Name)}"))
                                {
                                    Directory.CreateDirectory($"Output/compressed/{Path.GetDirectoryName(_File.Name)}");
                                }

                                _Client.DownloadFile(URL, $"Output/compressed/{_File.Name}");

                                if (_File.Name.EndsWith(".csv") || _File.Name.EndsWith(".sc"))
                                {
                                    if (!Directory.Exists($"Output/decompressed/{Path.GetDirectoryName(_File.Name)}"))
                                    {
                                        Directory.CreateDirectory($"Output/decompressed/{Path.GetDirectoryName(_File.Name)}");
                                    }

                                    if (_File.Name.EndsWith(".sc"))
                                    {
                                        LZMA.Decompress($"Output/compressed/{_File.Name}", $"Output/decompressed/{_File.Name}", File_Type.SC);
                                    }
                                    else
                                    {
                                        LZMA.Decompress($"Output/compressed/{_File.Name}", $"Output/decompressed/{_File.Name}", File_Type.CSV);
                                    }
                                }

                                Downloaded++;

                                Console.SetCursorPosition(0, Console.CursorTop - 1);
                                Console.WriteLine($"Progress: {Math.Round((double)(100 * Downloaded) / Hash_Module.Fingerprint.Files.Count)}%, {Downloaded}/{Hash_Module.Fingerprint.Files.Count}");
                            }
                            catch (Exception)
                            {
                            }
                        }

                        Console.WriteLine();
                        Console.WriteLine($"Downloaded {Downloaded} of {Hash_Module.Fingerprint.Files.Count} Files.");
                    }
                }
                else
                {
                    Console.WriteLine("Failed to download the Fingerprint.");
                }

                break;
            }

            case ConsoleKey.B:
            {
                if (!Directory.Exists("Output/decompressed/sc"))
                {
                    Console.WriteLine("SC Directory not found. Please re-download the Assets.");
                    break;
                }

                if (!Directory.Exists("Output/png"))
                {
                    Directory.CreateDirectory("Output/png");
                }

                int Total = 0, Converted = 0;

                foreach (string _File in Directory.GetFiles("Output/decompressed/sc"))
                {
                    if (_File.EndsWith("_tex.sc"))
                    {
                        Total++;
                    }
                }

                Console.WriteLine();

                foreach (string _File in Directory.GetFiles("Output/decompressed/sc"))
                {
                    if (_File.EndsWith("_tex.sc"))
                    {
                        SC2PNG.ExportTextures(_File, $"Output/png/{Path.GetFileNameWithoutExtension(_File)}.png");
                        Converted++;

                        if (Converted > 1)
                        {
                            Console.SetCursorPosition(0, Console.CursorTop - 1);
                            Console.WriteLine($"Progress: {Math.Round((double)(100 * Converted) / Total)}%, {Converted}/{Total}");
                        }
                    }
                }

                Console.WriteLine();
                Console.WriteLine($"Converted {Converted} of {Total} Textures.");

                break;
            }

            case ConsoleKey.C:
            {
                if (File.Exists("fingerprint.json"))
                {
                    File.Delete("fingerprint.json");

                    Console.WriteLine("Fingerprint has been deleted.");
                }
                else
                {
                    Console.WriteLine("Fingerprint not found. Please re-download the Assets.");
                }

                break;
            }

            default:
            {
                goto _Entry;
            }
            }

            Console.ReadKey(true);
        }
        //        #region Decompression


        //        // REMOVE THIS METHOD AND USE THE STANDARDIZED ONE
        //        /// <summary>
        //        ///     decompress an entire ME3, 2, or 1 package file.
        //        /// </summary>
        //        /// <param name="pccFileName">pcc file's name to open.</param>
        //        /// <returns>a decompressed array of bytes.</returns>
        //        //public static Stream Decompress(string pccFileName)
        //        //{
        //        //    using (FileStream input = File.OpenRead(pccFileName))
        //        //    {
        //        //        EndianReader packageReader = EndianReader.SetupForPackageReading(input);
        //        //        packageReader.SkipInt32(); //skip package tag
        //        //        var versionLicenseePacked = packageReader.ReadUInt32();
        //        //        var unrealVersion = (ushort)(versionLicenseePacked & 0xFFFF);
        //        //        var licenseeVersion = (ushort)(versionLicenseePacked >> 16);

        //        //        //ME3
        //        //        if ((unrealVersion == MEPackage.ME3UnrealVersion || unrealVersion == MEPackage.ME3WiiUUnrealVersion) && licenseeVersion == MEPackage.ME3LicenseeVersion)
        //        //        {
        //        //            return DecompressME3(packageReader);
        //        //        }
        //        //        //Support other platforms
        //        //        //ME2 || ME1
        //        //        else if (unrealVersion == 512 && licenseeVersion == 130 || unrealVersion == 491 && licenseeVersion == 1008)
        //        //        {
        //        //            return DecompressME1orME2(input);
        //        //        }
        //        //        else
        //        //        {
        //        //            throw new FormatException("Not an ME1, ME2, or ME3 package file.");
        //        //        }
        //        //    }
        //        //}

        //        // REMOVE THIS METHOD AND USE THE STANDARDIZED ONE
        //        /// <summary>
        //        ///     decompress an entire ME1 or 2 pcc file.
        //        /// </summary>
        //        /// <param name="raw">pcc file passed in stream format</param>
        //        /// <returns>a decompressed stream.</returns>
        //        //public static MemoryStream DecompressME1orME2(Stream raw)
        //        //{
        //        //    raw.Seek(4, SeekOrigin.Begin);
        //        //    ushort versionLo = raw.ReadUInt16();
        //        //    ushort versionHi = raw.ReadUInt16();
        //        //    raw.Seek(12, SeekOrigin.Begin);
        //        //    int tempNameSize = raw.ReadInt32();
        //        //    raw.Seek(64 + tempNameSize, SeekOrigin.Begin);
        //        //    int tempGenerations = raw.ReadInt32();
        //        //    raw.Seek(32 + tempGenerations * 12, SeekOrigin.Current);

        //        //    //if ME1
        //        //    if (versionLo == 491 && versionHi == 1008)
        //        //    {
        //        //        raw.Seek(4, SeekOrigin.Current);
        //        //    }
        //        //    UnrealPackageFile.CompressionType compressionType = (UnrealPackageFile.CompressionType)raw.ReadUInt32();


        //        //    int pos = 4;
        //        //    int NumChunks = raw.ReadInt32();
        //        //    var Chunks = new List<Chunk>();

        //        //    //DebugOutput.PrintLn("Reading chunk headers...");
        //        //    for (int i = 0; i < NumChunks; i++)
        //        //    {
        //        //        Chunk c = new Chunk
        //        //        {
        //        //            uncompressedOffset = raw.ReadInt32(),
        //        //            uncompressedSize = raw.ReadInt32(),
        //        //            compressedOffset = raw.ReadInt32(),
        //        //            compressedSize = raw.ReadInt32()
        //        //        };
        //        //        c.Compressed = new byte[c.compressedSize];
        //        //        c.Uncompressed = new byte[c.uncompressedSize];
        //        //        //DebugOutput.PrintLn("Chunk " + i + ", compressed size = " + c.compressedSize + ", uncompressed size = " + c.uncompressedSize);
        //        //        //DebugOutput.PrintLn("Compressed offset = " + c.compressedOffset + ", uncompressed offset = " + c.uncompressedOffset);
        //        //        Chunks.Add(c);
        //        //    }

        //        //    //DebugOutput.PrintLn("\tRead Chunks...");
        //        //    int count = 0;
        //        //    for (int i = 0; i < Chunks.Count; i++)
        //        //    {
        //        //        Chunk c = Chunks[i];
        //        //        raw.Seek(c.compressedOffset, SeekOrigin.Begin);
        //        //        c.Compressed = raw.ReadToBuffer(c.compressedSize);

        //        //        ChunkHeader h = new ChunkHeader
        //        //        {
        //        //            magic = BitConverter.ToInt32(c.Compressed, 0),
        //        //            blocksize = BitConverter.ToInt32(c.Compressed, 4),
        //        //            compressedsize = BitConverter.ToInt32(c.Compressed, 8),
        //        //            uncompressedsize = BitConverter.ToInt32(c.Compressed, 12)
        //        //        };
        //        //        if (h.magic != -1641380927)
        //        //            throw new FormatException("Chunk magic number incorrect");
        //        //        //DebugOutput.PrintLn("Chunkheader read: Magic = " + h.magic + ", Blocksize = " + h.blocksize + ", Compressed Size = " + h.compressedsize + ", Uncompressed size = " + h.uncompressedsize);
        //        //        pos = 16;
        //        //        int blockCount = (h.uncompressedsize % h.blocksize == 0)
        //        //            ?
        //        //            h.uncompressedsize / h.blocksize
        //        //            :
        //        //            h.uncompressedsize / h.blocksize + 1;
        //        //        var BlockList = new List<Block>();
        //        //        //DebugOutput.PrintLn("\t\t" + count + " Read Blockheaders...");
        //        //        for (int j = 0; j < blockCount; j++)
        //        //        {
        //        //            Block b = new Block
        //        //            {
        //        //                compressedsize = BitConverter.ToInt32(c.Compressed, pos),
        //        //                uncompressedsize = BitConverter.ToInt32(c.Compressed, pos + 4)
        //        //            };
        //        //            //DebugOutput.PrintLn("Block " + j + ", compressed size = " + b.compressedsize + ", uncompressed size = " + b.uncompressedsize);
        //        //            pos += 8;
        //        //            BlockList.Add(b);
        //        //        }
        //        //        int outpos = 0;
        //        //        //DebugOutput.PrintLn("\t\t" + count + " Read and decompress Blocks...");
        //        //        foreach (Block b in BlockList)
        //        //        {
        //        //            var datain = new byte[b.compressedsize];
        //        //            var dataout = new byte[b.uncompressedsize];
        //        //            for (int j = 0; j < b.compressedsize; j++)
        //        //                datain[j] = c.Compressed[pos + j];
        //        //            pos += b.compressedsize;

        //        //            switch (compressionType)
        //        //            {
        //        //                case UnrealPackageFile.CompressionType.LZO:
        //        //                    {
        //        //                        if (
        //        //                                LZO2.Decompress(datain, (uint)datain.Length, dataout) != b.uncompressedsize)
        //        //                            throw new Exception("LZO decompression failed!");
        //        //                        break;
        //        //                    }
        //        //                case UnrealPackageFile.CompressionType.Zlib:
        //        //                    {
        //        //                        if (ZlibHelper.Zlib.Decompress(datain, (uint)datain.Length, dataout) != b.uncompressedsize)
        //        //                            throw new Exception("Zlib decompression failed!");
        //        //                        break;
        //        //                    }
        //        //                default:
        //        //                    throw new Exception("Unknown compression type for this package.");
        //        //            }
        //        //            for (int j = 0; j < b.uncompressedsize; j++)
        //        //                c.Uncompressed[outpos + j] = dataout[j];
        //        //            outpos += b.uncompressedsize;
        //        //        }
        //        //        c.header = h;
        //        //        c.blocks = BlockList;
        //        //        count++;
        //        //        Chunks[i] = c;
        //        //    }

        //        //    MemoryStream result = new MemoryStream();
        //        //    foreach (Chunk c in Chunks)
        //        //    {
        //        //        result.Seek(c.uncompressedOffset, SeekOrigin.Begin);
        //        //        result.WriteFromBuffer(c.Uncompressed);
        //        //    }

        //        //    return result;
        //        //}

        //        /// <summary>
        //        /// Reads
        //        /// </summary>
        //        /// <param name="input"></param>
        //        /// <param name="compressionType"></param>
        //        /// <returns></returns>
        //        public static byte[] DecompressChunks(EndianReader input, List<Chunk> chunkTable, UnrealPackageFile.CompressionType compressionType)
        //        {
        //            var fullUncompressedSize = chunkTable.Sum(x => x.uncompressedSize);
        //            byte[] decompressedBuffer = new byte[fullUncompressedSize];
        //            foreach (var chunk in chunkTable)
        //            {
        //                //Header of individual chunk
        //                input.Seek(chunk.compressedOffset, SeekOrigin.Begin);
        //                var uncompressedOffset = input.ReadUInt32(); //where to write to into the decompressed buffer
        //                var uncompressedSize = input.ReadUInt32(); //how much to write
        //                var compressedOffset = input.ReadUInt32(); //where to read from
        //                var compressedSize = input.ReadUInt32(); //how much to read
        //                var firstBlockInfoOffset = (int)input.Position;

        //                var buff = new byte[compressedSize];
        //                input.Seek(compressedOffset, SeekOrigin.Begin);
        //                input.Read(buff, 0, buff.Length);
        //                if (compressionType == UnrealPackageFile.CompressionType.Zlib)
        //                {

        //                }
        //                else if (compressionType == UnrealPackageFile.CompressionType.LZMA)
        //                {

        //                }
        //                //AmaroK86.MassEffect3.ZlibBlock.ZBlock.Decompress(buff, i);
        //                //tasks[i] = AmaroK86.MassEffect3.ZlibBlock.ZBlock.Decompress(buff, i);
        //            }

        //            return decompressedBuffer;
        //        }

        //        #region Block decompression
        //        public static readonly uint zlibmagic = 0x9E2A83C1;
        //        public static readonly uint zlibmaxsegmentsize = 0x20000;


        //        public static byte[] DecompressZLibBlock(byte[] buffer, int num = 0)
        //        {
        //            if (buffer == null)
        //                throw new ArgumentNullException();
        //            using (MemoryStream buffStream = new MemoryStream(buffer))
        //            {
        //                EndianReader reader = EndianReader.SetupForReading(buffStream, (int)zlibmagic, out int zlibBlockMagic);
        //                if ((uint)zlibBlockMagic != zlibmagic)
        //                {
        //                    throw new InvalidDataException("found an invalid zlib block, wrong magic");
        //                }

        //                uint buffMaxSegmentSize = reader.ReadUInt32();
        //                if (buffMaxSegmentSize != zlibmaxsegmentsize)
        //                {
        //                    throw new FormatException("Wrong segment size for ZLIB!");
        //                }

        //                uint totComprSize = reader.ReadUInt32();
        //                uint totUncomprSize = reader.ReadUInt32();

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

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

        //                    reader.Seek(dataSegm, SeekOrigin.Begin);
        //                    //Console.WriteLine("compr size: {0}, uncompr size: {1}, data offset: 0x{2:X8}", comprSegm, uncomprSegm, dataSegm);
        //                    byte[] src = reader.ReadBytes(comprSegm);
        //                    byte[] dst = new byte[uncomprSegm];
        //                    if (Zlib.Decompress(src, (uint)src.Length, dst) != uncomprSegm)
        //                        throw new Exception("Zlib decompression failed!");

        //                    Buffer.BlockCopy(dst, 0, outputBuffer, buffOff, uncomprSegm);

        //                    buffOff += uncomprSegm;
        //                    dataSegm += comprSegm;
        //                }

        //                reader.Close();
        //                return outputBuffer;
        //            }
        //        }
        //        #endregion

        //        /// <summary>
        //        ///     decompress an entire ME3 pcc file into a new stream
        //        /// </summary>
        //        /// <param name="input">pcc file passed in stream format (wrapped in endianreader)</param>
        //        /// <returns>a decompressed array of bytes</returns>
        //        //public static MemoryStream DecompressME3(EndianReader input)
        //        //{
        //        //    input.Seek(0, SeekOrigin.Begin);
        //        //    var magic = input.ReadUInt32();
        //        //    if (magic != 0x9E2A83C1)
        //        //    {
        //        //        throw new FormatException("not a pcc file");
        //        //    }

        //        //    var versionLo = input.ReadUInt16();
        //        //    var versionHi = input.ReadUInt16();

        //        //    //if (versionLo != 684 &&
        //        //    //    versionHi != 194)
        //        //    //{
        //        //    //    throw new FormatException("unsupported pcc version");
        //        //    //}

        //        //    long headerSize = 8;

        //        //    input.Seek(4, SeekOrigin.Current);
        //        //    headerSize += 4;

        //        //    var folderNameLength = input.ReadInt32();
        //        //    headerSize += 4;

        //        //    var folderNameByteLength =
        //        //        folderNameLength >= 0 ? folderNameLength : (-folderNameLength * 2);
        //        //    input.Seek(folderNameByteLength, SeekOrigin.Current);
        //        //    headerSize += folderNameByteLength;

        //        //    var packageFlagsOffset = input.Position;
        //        //    var packageFlags = input.ReadUInt32();
        //        //    headerSize += 4;

        //        //    if ((packageFlags & 0x02000000u) == 0)
        //        //    {
        //        //        throw new FormatException("pcc file is already decompressed");
        //        //    }

        //        //    if ((packageFlags & 8) != 0)
        //        //    {
        //        //        input.Seek(4, SeekOrigin.Current);
        //        //        headerSize += 4;
        //        //    }

        //        //    uint nameCount = input.ReadUInt32();
        //        //    uint nameOffset = input.ReadUInt32();

        //        //    input.Seek(52, SeekOrigin.Current);
        //        //    headerSize += 60;

        //        //    var generationsCount = input.ReadUInt32();
        //        //    input.Seek(generationsCount * 12, SeekOrigin.Current);
        //        //    headerSize += generationsCount * 12;

        //        //    input.Seek(20, SeekOrigin.Current);
        //        //    headerSize += 24;

        //        //    var blockCount = input.ReadUInt32();
        //        //    int headBlockOff = (int)input.Position;
        //        //    var afterBlockTableOffset = headBlockOff + (blockCount * 16);
        //        //    var indataOffset = afterBlockTableOffset + 8;

        //        //    input.Seek(0, SeekOrigin.Begin);
        //        //    MemoryStream output = new MemoryStream();
        //        //    output.Seek(0, SeekOrigin.Begin);

        //        //    output.WriteFromStream(input.BaseStream, headerSize);
        //        //    output.WriteUInt32(0);// block count

        //        //    input.Seek(afterBlockTableOffset, SeekOrigin.Begin);
        //        //    output.WriteFromStream(input.BaseStream, 8);

        //        //    //check if has extra name list (don't know it's usage...)
        //        //    if ((packageFlags & 0x10000000) != 0)
        //        //    {
        //        //        long curPos = output.Position;
        //        //        output.WriteFromStream(input.BaseStream, nameOffset - curPos);
        //        //    }

        //        //    //decompress blocks in parallel
        //        //    var tasks = new Task<byte[]>[blockCount];
        //        //    var uncompressedOffsets = new uint[blockCount];
        //        //    for (int i = 0; i < blockCount; i++)
        //        //    {
        //        //        input.Seek(headBlockOff, SeekOrigin.Begin);
        //        //        uncompressedOffsets[i] = input.ReadUInt32();
        //        //        var uncompressedSize = input.ReadUInt32();
        //        //        var compressedOffset = input.ReadUInt32();
        //        //        var compressedSize = input.ReadUInt32();
        //        //        headBlockOff = (int)input.Position;

        //        //        var buff = new byte[compressedSize];
        //        //        input.Seek(compressedOffset, SeekOrigin.Begin);
        //        //        input.Read(buff, 0, buff.Length);
        //        //        AmaroK86.MassEffect3.ZlibBlock.ZBlock.Decompress(buff, i);
        //        //        //tasks[i] = AmaroK86.MassEffect3.ZlibBlock.ZBlock.Decompress(buff, i);
        //        //    }
        //        //    Task.WaitAll(tasks);
        //        //    for (int i = 0; i < blockCount; i++)
        //        //    {
        //        //        output.Seek(uncompressedOffsets[i], SeekOrigin.Begin);
        //        //        output.WriteFromBuffer(tasks[i].Result);
        //        //    }

        //        //    //Do not change the IsCompressed bit as it will not accurately reflect the state of the file on disk.
        //        //    //output.Seek(packageFlagsOffset, SeekOrigin.Begin);
        //        //    //output.WriteUInt32(packageFlags & ~0x02000000u, ); //Mark file as decompressed.
        //        //    return output;
        //        //}


        /// <summary>
        /// Decompresses a fully compressed package file. These only occur on console platforms.
        /// </summary>
        /// <param name="rawInput">Input stream to read from</param>
        /// <param name="compressionType">Known compression type of package. If this is not known, it will attempt to be determined, and this variable will be updated.</param>
        /// <returns></returns>
        public static MemoryStream DecompressFullyCompressedPackage(EndianReader rawInput, ref UnrealPackageFile.CompressionType compressionType)
        {
            rawInput.Position = 0;
            var magic            = rawInput.ReadInt32();
            var blockSize        = rawInput.ReadInt32();
            var compressedSize   = rawInput.ReadInt32();
            var decompressedSize = rawInput.ReadInt32();

            var blockCount = 0;

            if (decompressedSize < blockSize)
            {
                blockCount = 1;
            }
            else
            {
                // Calculate the number of blocks
                blockCount = decompressedSize / blockSize;
                if (decompressedSize % blockSize != 0)
                {
                    blockCount++;                                    //Add one to decompress the final data
                }
            }


            MemoryStream outStream = new MemoryStream();
            List <(int blockCompressedSize, int blockDecompressedSize)> blockTable = new List <(int blockCompressedSize, int blockDecompressedSize)>();

            // Read Block Table
            int i = 0;

            while (i < blockCount)
            {
                blockTable.Add((rawInput.ReadInt32(), rawInput.ReadInt32()));
                i++;
            }

            int index = 0;

            foreach (var btInfo in blockTable)
            {
                // Decompress
                //Debug.WriteLine($"Decompressing data at 0x{raw.Position:X8}");
                var datain = rawInput.ReadToBuffer(btInfo.blockCompressedSize);
                if (compressionType == UnrealPackageFile.CompressionType.None)
                {
                    // We have to determine if it's LZMA or LZX based on first few bytes
                    if (datain[0] == 0x5D && BitConverter.ToInt32(datain, 1) == 0x10000)
                    {
                        // This is LZMA header
                        Debug.WriteLine("Fully compressed package: Detected LZMA compression");
                        compressionType = UnrealPackageFile.CompressionType.LZMA;
                    }
                    else
                    {
                        Debug.WriteLine("Fully compressed package: Detected LZX compression");
                        compressionType = UnrealPackageFile.CompressionType.LZX;
                    }
                }

                var dataout = new byte[btInfo.blockDecompressedSize];
                if (dataout.Length == datain.Length)
                {
                    // WiiU SFXGame has weird case where one single block has same sizes and does not have LZMA compression flag for some reason
                    dataout = datain;
                }
                else
                {
                    switch (compressionType)
                    {
                    case UnrealPackageFile.CompressionType.LZO:
                        if (LZO2.Decompress(datain, (uint)datain.Length, dataout) != btInfo.blockDecompressedSize)
                        {
                            throw new Exception("LZO decompression failed!");
                        }
                        break;

                    case UnrealPackageFile.CompressionType.Zlib:
                        if (Zlib.Decompress(datain, (uint)datain.Length, dataout) != btInfo.blockDecompressedSize)
                        {
                            throw new Exception("Zlib decompression failed!");
                        }
                        break;

                    case UnrealPackageFile.CompressionType.LZMA:
                        dataout = LZMA.Decompress(datain, (uint)btInfo.blockDecompressedSize);
                        if (dataout.Length != btInfo.blockDecompressedSize)
                        {
                            throw new Exception("LZMA decompression failed!");
                        }
                        break;

                    case UnrealPackageFile.CompressionType.LZX:
                        if (LZX.Decompress(datain, (uint)datain.Length, dataout) != 0)
                        {
                            throw new Exception("LZX decompression failed!");
                        }
                        break;

                    default:
                        throw new Exception("Unknown compression type for this package.");
                    }
                }

                index++;
                outStream.WriteFromBuffer(dataout);
            }

            outStream.Position = 0;
            return(outStream);
        }
Beispiel #17
0
        private static void Save(string path, string token)
        {
            if (!KK_SaveLoadCompression.Enable.Value || !KK_SaveLoadCompression.Notice.Value)
            {
                return;
            }
            byte[] pngData;
            string TempPath = Path.Combine(KK_SaveLoadCompression.CacheDirectory.CreateSubdirectory("Compressed").FullName, Path.GetFileName(path));

            //這裡用cleanedPath作"_compressed"字串清理
            string cleanedPath = path;

            while (cleanedPath.Contains("_compressed"))
            {
                cleanedPath = cleanedPath.Replace("_compressed", "");
            }

            if (cleanedPath != path)
            {
                File.Copy(path, cleanedPath, true);
                Logger.LogDebug($"Clean Path: {cleanedPath}");
            }

            //Update Cache
            string decompressPath = Path.Combine(KK_SaveLoadCompression.CacheDirectory.CreateSubdirectory("Decompressed").FullName, Path.GetFileName(cleanedPath));

            File.Copy(path, decompressPath, true);

            using (FileStream fileStreamReader = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) {
                using (BinaryReader binaryReader = new BinaryReader(fileStreamReader)) {
                    Logger.LogInfo("Start Compress");
                    pngData = PngFile.LoadPngBytes(binaryReader);
                    Texture2D png = new Texture2D(2, 2);
                    png.LoadImage(pngData);

                    Texture2D watermark  = Extension.Extension.LoadDllResource($"KK_SaveLoadCompression.Resources.zip_watermark.png");
                    float     scaleTimes = (token == StudioToken) ? .14375f : .30423f;
                    watermark = Extension.Extension.Scale(watermark, Convert.ToInt32(png.width * scaleTimes), Convert.ToInt32(png.width * scaleTimes));
                    png       = Extension.Extension.OverwriteTexture(
                        png,
                        watermark,
                        0,
                        png.height - watermark.height
                        );
                    //Logger.LogDebug($"Add Watermark: zip");
                    pngData = png.EncodeToPNG();
                }
            }

            Thread newThread = new Thread(doMain);

            newThread.Start();

            void doMain()
            {
                bool successFlag = true;

                try {
                    using (FileStream fileStreamReader = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) {
                        float startTime = Time.time;
                        using (FileStream fileStreamWriter = new FileStream(TempPath, FileMode.Create, FileAccess.Write)) {
                            using (BinaryWriter binaryWriter = new BinaryWriter(fileStreamWriter)) {
                                binaryWriter.Write(pngData);

                                switch (token)
                                {
                                case StudioToken:
                                    //Studio
                                    binaryWriter.Write(new Version(101, 0, 0, 0).ToString());
                                    break;

                                case CoordinateToken:
                                    //Coordinate
                                    binaryWriter.Write(101);
                                    break;

                                default:
                                    //Chara
                                    if (token.IndexOf(CharaToken) >= 0)
                                    {
                                        binaryWriter.Write(101);
                                        break;
                                    }

                                    throw new Exception("Token not match.");
                                }

                                //為了通過 InvalidSceneFileProtection 和 DragAndDrop
                                binaryWriter.Write(token);

                                using (MemoryStream msCompressed = new MemoryStream()) {
                                    PngFile.SkipPng(fileStreamReader);

                                    long fileStreamPos = fileStreamReader.Position;
                                    LZMA.Compress(fileStreamReader, msCompressed, LzmaSpeed.Fastest, KK_SaveLoadCompression.DictionarySize.Value,
                                                  delegate(long inSize, long _) {
                                        KK_SaveLoadCompression.Progress = $"Compressing: {Convert.ToInt32(inSize * 100 / (fileStreamReader.Length - fileStreamPos))}%";
                                    }
                                                  );
                                    KK_SaveLoadCompression.Progress = "";

                                    Logger.LogInfo("Start compression test...");
                                    using (MemoryStream msDecompressed = new MemoryStream()) {
                                        if (!KK_SaveLoadCompression.SkipSaveCheck.Value)
                                        {
                                            msCompressed.Seek(0, SeekOrigin.Begin);

                                            LZMA.Decompress(msCompressed, msDecompressed,
                                                            delegate(long inSize, long _) {
                                                KK_SaveLoadCompression.Progress = $"Decompressing: {Convert.ToInt32(inSize * 100 / (fileStreamReader.Length - fileStreamPos))}%";
                                            }
                                                            );
                                            KK_SaveLoadCompression.Progress = "";
                                            fileStreamReader.Seek(fileStreamPos, SeekOrigin.Begin);
                                            msDecompressed.Seek(0, SeekOrigin.Begin);

                                            for (int i = 0; i < msDecompressed.Length; i++)
                                            {
                                                KK_SaveLoadCompression.Progress = $"Comparing: {i * 100 / msDecompressed.Length}%";
                                                int aByte = fileStreamReader.ReadByte();
                                                int bByte = msDecompressed.ReadByte();
                                                if (aByte.CompareTo(bByte) != 0)
                                                {
                                                    successFlag = false;
                                                    break;
                                                }
                                            }
                                            KK_SaveLoadCompression.Progress = "";
                                        }
                                        if (successFlag)
                                        {
                                            long newSize = msCompressed.Length + token.Length + pngData.Length;
                                            binaryWriter.Write(msCompressed.ToArray());
                                            LogLevel logLevel = KK_SaveLoadCompression.DisplayMessage.Value ? (LogLevel.Message | LogLevel.Info) : LogLevel.Info;
                                            Logger.LogInfo($"Compression test SUCCESS");
                                            Logger.Log(logLevel, $"Compression finish in {Math.Round(Time.time - startTime, 2)} seconds");
                                            Logger.Log(logLevel, $"Size compress from {fileStreamReader.Length} bytes to {newSize} bytes");
                                            Logger.Log(logLevel, $"Compress ratio: {Math.Round(Convert.ToDouble(fileStreamReader.Length) / newSize, 2)}, which means it is now {Math.Round(100 / (Convert.ToDouble(fileStreamReader.Length) / newSize), 2)}% big.");
                                        }
                                        else
                                        {
                                            Logger.LogError($"Compression test FAILED");
                                        }
                                    }
                                }
                            }
                        }
                    }

                    //複製或刪除檔案
                    if (successFlag)
                    {
                        string compressedPath = cleanedPath;
                        if (!KK_SaveLoadCompression.DeleteTheOri.Value)
                        {
                            compressedPath = cleanedPath.Substring(0, cleanedPath.Length - 4) + "_compressed.png";
                        }

                        File.Copy(TempPath, compressedPath, true);
                        Logger.LogDebug($"Write to: {compressedPath}");

                        //因為File.Delete()不是立即執行完畢,不能有「砍掉以後立即在同位置寫入」的操作,所以是這個邏輯順序
                        //如果相同的話,上方就已經覆寫了;不同的話此處再做刪除
                        if (path != compressedPath && path != cleanedPath)
                        {
                            File.Delete(path);
                            Logger.LogDebug($"Delete Original File: {path}");
                        }
                    }
                } catch (Exception e) {
                    if (e is IOException && successFlag)
                    {
                        //覆寫時遇到讀取重整會IOException: Sharing violation on path,這在Compress太快時會發生
                        //Retry
                        try {
                            if (File.Exists(TempPath))
                            {
                                if (KK_SaveLoadCompression.DeleteTheOri.Value)
                                {
                                    File.Copy(TempPath, path, true);
                                }
                            }
                        } catch (Exception) {
                            //Copy to a new name if failed twice
                            File.Copy(TempPath, path.Substring(0, path.Length - 4) + "_compressed2.png");
                            Logger.LogError("Overwrite was FAILED twice. Fallback to use the '_compressed2' path.");
                        }
                    }
                    else
                    {
                        Logger.LogError($"An unknown error occurred. If your files are lost, please find them at %TEMP%/{KK_SaveLoadCompression.GUID}");
                        throw;
                    }
                } finally {
                    if (File.Exists(TempPath))
                    {
                        File.Delete(TempPath);
                    }
                }
            }
        }
Beispiel #18
0
        /// <summary>
        /// Se llama cuando existen datos disponibles para un cliente
        /// </summary>
        private static void DatosDisponibles(object arg)
        {
            ClienteTCP cliente = (ClienteTCP)arg;

            if (cliente.DatosRecibidos != null)
            {
                NetworkStream stream = cliente.TcpClient.GetStream();
                BinaryReader  lector = new BinaryReader(stream);

                while (true)
                {
                    try
                    {
                        if (cliente.TcpClient.Available > 0)
                        {
                            bool   comprimido    = lector.ReadBoolean();
                            ushort comando       = lector.ReadUInt16();
                            int    longitudArray = lector.ReadInt32();
                            byte[] datos         = lector.ReadBytes((int)longitudArray);

                            if (comprimido)
                            {
                                datos = LZMA.Decompress(datos);
                            }

                            string cadena = Encoding.UTF8.GetString(datos);

                            string[] parametros = ObtenerSubCadenas(cadena);

                            //Llamar al evento
                            if (cliente.ControlInvoke != null)
                            {
                                foreach (Delegate delegado in cliente.DatosRecibidos.GetInvocationList())
                                {
                                    cliente.ControlInvoke.Invoke(delegado, new object[] { comando, parametros, cadena, cliente });
                                    Application.DoEvents();
                                    if (cliente.DatosRecibidos == null)
                                    {
                                        break;
                                    }
                                }
                            }
                            else
                            {
                                cliente.DatosRecibidos(comando, parametros, cadena, cliente);
                                Application.DoEvents();
                                if (cliente.DatosRecibidos == null)
                                {
                                    break;
                                }
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                    catch
                    {
                        break;
                    }
                }
            }
        }
        /// <summary>
        /// Decompresses a compressed package. Works with ME1/ME2/ME3/UDK
        /// </summary>
        /// <param name="raw"></param>
        /// <param name="compressionInfoOffset"></param>
        /// <param name="compressionType"></param>
        /// <param name="NumChunks"></param>
        /// <param name="game"></param>
        /// <param name="platform"></param>
        /// <returns></returns>
        public static MemoryStream DecompressPackage(EndianReader raw, long compressionInfoOffset, UnrealPackageFile.CompressionType compressionType = UnrealPackageFile.CompressionType.None, int NumChunks = 0, MEGame game = MEGame.Unknown, GamePlatform platform = GamePlatform.PC)
        {
            raw.BaseStream.JumpTo(compressionInfoOffset);
            if (compressionType == UnrealPackageFile.CompressionType.None)
            {
                compressionType = (UnrealPackageFile.CompressionType)raw.ReadUInt32();
            }

            if (NumChunks == 0)
            {
                NumChunks = raw.ReadInt32();
            }
            var Chunks          = new List <Chunk>();
            var chunkTableStart = raw.Position;

            //DebugOutput.PrintLn("Reading chunk headers...");
            for (int i = 0; i < NumChunks; i++)
            {
                Chunk c = new Chunk
                {
                    uncompressedOffset = raw.ReadInt32(),
                    uncompressedSize   = raw.ReadInt32(),
                    compressedOffset   = raw.ReadInt32(),
                    compressedSize     = raw.ReadInt32()
                };
                c.Compressed   = new byte[c.compressedSize];
                c.Uncompressed = new byte[c.uncompressedSize];
                Chunks.Add(c);
            }


            //DebugOutput.PrintLn("\tRead Chunks...");
            int count = 0;

            for (int i = 0; i < Chunks.Count; i++)
            {
                Chunk c = Chunks[i];
                //Debug.WriteLine($"Compressed offset at {c.compressedOffset:X8}");
                raw.Seek(c.compressedOffset, SeekOrigin.Begin);
                raw.Read(c.Compressed, 0, c.compressedSize);

                ChunkHeader h = new ChunkHeader
                {
                    magic = EndianReader.ToInt32(c.Compressed, 0, raw.Endian),
                    // must force block size for ME1 xbox cause in place of block size it seems to list package tag again which breaks loads of things
                    blocksize        = (platform == GamePlatform.Xenon && game == MEGame.ME1) ? 0x20000 : EndianReader.ToInt32(c.Compressed, 4, raw.Endian),
                    compressedsize   = EndianReader.ToInt32(c.Compressed, 8, raw.Endian),
                    uncompressedsize = EndianReader.ToInt32(c.Compressed, 12, raw.Endian)
                };

                if (h.magic != -1641380927)
                {
                    throw new FormatException("Chunk magic number incorrect");
                }
                //DebugOutput.PrintLn("Chunkheader read: Magic = " + h.magic + ", Blocksize = " + h.blocksize + ", Compressed Size = " + h.compressedsize + ", Uncompressed size = " + h.uncompressedsize);
                int pos        = 16;
                int blockCount = h.uncompressedsize / h.blocksize;
                if (h.uncompressedsize % h.blocksize != 0)
                {
                    blockCount++;
                }
                var BlockList = new List <Block>();
                //DebugOutput.PrintLn("\t\t" + count + " Read Blockheaders...");
                for (int j = 0; j < blockCount; j++)
                {
                    Block b = new Block
                    {
                        compressedsize   = EndianReader.ToInt32(c.Compressed, pos, raw.Endian),
                        uncompressedsize = EndianReader.ToInt32(c.Compressed, pos + 4, raw.Endian)
                    };
                    //DebugOutput.PrintLn("Block " + j + ", compressed size = " + b.compressedsize + ", uncompressed size = " + b.uncompressedsize);
                    pos += 8;
                    BlockList.Add(b);
                }
                int outpos   = 0;
                int blocknum = 0;
                //DebugOutput.PrintLn("\t\t" + count + " Read and decompress Blocks...");
                foreach (Block b in BlockList)
                {
                    //Debug.WriteLine("Decompressing block " + blocknum);
                    var datain  = new byte[b.compressedsize];
                    var dataout = new byte[b.uncompressedsize];
                    Buffer.BlockCopy(c.Compressed, pos, datain, 0, b.compressedsize);
                    //for (int j = 0; j < b.compressedsize; j++)
                    //    datain[j] = c.Compressed[pos + j];
                    pos += b.compressedsize;

                    switch (compressionType)
                    {
                    case UnrealPackageFile.CompressionType.LZO:
                    {
                        if (LZO2.Decompress(datain, (uint)datain.Length, dataout) != b.uncompressedsize)
                        {
                            throw new Exception("LZO decompression failed!");
                        }
                        break;
                    }

                    case UnrealPackageFile.CompressionType.Zlib:
                    {
                        if (Zlib.Decompress(datain, (uint)datain.Length, dataout) != b.uncompressedsize)
                        {
                            throw new Exception("Zlib decompression failed!");
                        }
                        break;
                    }

                    case UnrealPackageFile.CompressionType.LZMA:
                        dataout = LZMA.Decompress(datain, (uint)b.uncompressedsize);
                        if (dataout.Length != b.uncompressedsize)
                        {
                            throw new Exception("LZMA decompression failed!");
                        }
                        break;

                    case UnrealPackageFile.CompressionType.LZX:
                        if (LZX.Decompress(datain, (uint)datain.Length, dataout) != 0)
                        {
                            throw new Exception("LZX decompression failed!");
                        }
                        break;

                    default:
                        throw new Exception("Unknown compression type for this package.");
                    }
                    for (int j = 0; j < b.uncompressedsize; j++)
                    {
                        c.Uncompressed[outpos + j] = dataout[j];
                    }
                    outpos += b.uncompressedsize;
                    blocknum++;
                }
                c.header = h;
                c.blocks = BlockList;
                count++;
                Chunks[i] = c;
            }

            MemoryStream result = new MemoryStream();

            foreach (Chunk c in Chunks)
            {
                result.Seek(c.uncompressedOffset, SeekOrigin.Begin);
                result.WriteFromBuffer(c.Uncompressed);
            }

            // Reattach the original header
            result.Position = 0;
            raw.Position    = 0;
            raw.BaseStream.CopyToEx(result, Chunks.MinBy(x => x.uncompressedOffset).uncompressedOffset); // Copy the header in
            // Does header need adjusted here to be accurate?
            // Do we change it to show decompressed, as the actual state, or the state of what it was on disk?

            return(result);
        }
        public void Actualizar(string url, string carpetaInstalacion, string nombrePrograma)
        {
            try
            {
                /* Formato archivos de actualizacion
                 * Cadena de version
                 * Numero de archivos
                 *      Cadena de nombre de archivo
                 *      Cadena de carpeta de destino de archivo
                 *      Longitud del archivo (long)
                 *      Array de bytes con el contenido
                 */
                ventanaProgreso = new Progreso();
                ventanaProgreso.Show();

                System.Net.WebClient cliente = new System.Net.WebClient();

                System.IO.Stream       myStream = cliente.OpenRead(url);
                System.IO.BinaryReader lector   = new BinaryReader(myStream);

                string versionDisponible = lector.ReadString().Trim();
                ventanaProgreso.label1.Text = string.Format("Actualizando {0} a la versión {1}", nombrePrograma, versionDisponible);
                lector.Close();

                Application.DoEvents();

                string archivoActualizacion = Path.GetTempFileName();
                DescargarArchivo(url, archivoActualizacion);

                try
                {
                    FileStream archivo = new FileStream(archivoActualizacion, FileMode.Open);
                    lector = new BinaryReader(archivo);
                    lector.ReadString();//Omitir la versión
                    int numeroArchivos = lector.ReadInt32();

                    ventanaProgreso.progressBar1.Value   = 0;
                    ventanaProgreso.progressBar1.Maximum = numeroArchivos;
                    for (int contador = 0; contador < numeroArchivos; contador++)
                    {
                        try
                        {
                            string nombreArchivo  = lector.ReadString();
                            string carpetaDestino = lector.ReadString();
                            int    tamaño         = lector.ReadInt32();

                            string rutaDestino;
                            if (carpetaDestino == "\\")
                            {
                                rutaDestino = Path.Combine(carpetaInstalacion, nombreArchivo);
                            }
                            else if (Path.IsPathRooted(carpetaDestino))
                            {
                                rutaDestino = Path.Combine(carpetaDestino, nombreArchivo);
                            }
                            else
                            {
                                rutaDestino = Path.Combine(Path.Combine(carpetaInstalacion, carpetaDestino), nombreArchivo);
                            }

                            if (Directory.Exists(Path.GetDirectoryName(rutaDestino)) == false)
                            {
                                Directory.CreateDirectory(Path.GetDirectoryName(rutaDestino));
                            }

                            try
                            {
                                ventanaProgreso.label2.Text = string.Format("Actualizando archivo \"{0}\"", nombreArchivo);
                            }
                            catch { }


                            MemoryStream res     = new MemoryStream(lector.ReadBytes(tamaño));
                            FileStream   destino = new FileStream(rutaDestino, FileMode.Create, FileAccess.Write);

                            LZMA.Decompress(res, destino);

                            destino.Close();
                            res.Close();

                            Application.DoEvents();
                            ventanaProgreso.progressBar1.Value++;
                        }
                        catch (Exception error) { MessageBox.Show("Error: " + error.Message); }
                    }
                }
                catch { }
                finally
                {
                    lector.Close();
                }
            }
            catch { }
        }
Beispiel #21
0
        private static void Load(ref string path, string token)
        {
            string        n       = Path.GetFileName(path);
            DirectoryInfo d       = KK_SaveLoadCompression.CacheDirectory.CreateSubdirectory("Decompressed");
            string        tmpPath = Path.Combine(d.FullName, n);

            if (File.Exists(tmpPath))
            {
                path = tmpPath;
                Logger.LogDebug("Load from cache: " + path);
                return;
            }

            using (FileStream fileStreamReader = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) {
                using (BinaryReader binaryReader = new BinaryReader(fileStreamReader)) {
                    byte[] pngData;
                    try {
                        bool checkfail = false;
                        pngData = PngFile.LoadPngBytes(binaryReader);

                        switch (token)
                        {
                        case StudioToken:
                            checkfail = !new Version(binaryReader.ReadString()).Equals(new Version(101, 0, 0, 0));
                            break;

                        case CoordinateToken:
                        case CharaToken:
                            checkfail = 101 != binaryReader.ReadInt32();
                            break;
                        }

                        if (checkfail)
                        {
                            return;
                        }
                    } catch (Exception) {
                        //在這裡發生讀取錯誤,那大概不是個正確的存檔
                        //因為已經有其它檢核的plugin存在,直接拋給他處理
                        Logger.Log(LogLevel.Error | LogLevel.Message, "Corrupted file: " + path);
                        return;
                    }
                    try {
                        //Discard token string
                        binaryReader.ReadString();

                        Logger.LogDebug("Start Decompress...");
                        //KK_Fix_CharacterListOptimizations依賴檔名做比對
                        using (FileStream fileStreamWriter = new FileStream(tmpPath, FileMode.Create, FileAccess.Write)) {
                            using (BinaryWriter binaryWriter = new BinaryWriter(fileStreamWriter)) {
                                binaryWriter.Write(pngData);

                                long fileStreamPos = fileStreamReader.Position;
                                LZMA.Decompress(fileStreamReader, fileStreamWriter,
                                                delegate(long inSize, long _) {
                                    KK_SaveLoadCompression.Progress = $"Decompressing: {Convert.ToInt32(inSize * 100 / (fileStreamReader.Length - fileStreamPos))}%";
                                }
                                                );
                                KK_SaveLoadCompression.Progress = "";
                            }
                        }

                        path = tmpPath;
                        Logger.LogDebug($"Decompression FINISH");
                    } catch (Exception) {
                        Logger.LogError($"Decompression FAILDED. The file was damaged during compression.");
                        Logger.LogError($"Do not disable the byte comparison setting next time to avoid this.");
                        return;
                    }
                }
            }
        }
Beispiel #22
0
        private void LoadHeader(Stream stream)
        {
            uint tag = stream.ReadUInt32();

            if (tag != SfarTag)
            {
                throw new Exception("Wrong SFAR tag");
            }
            uint sfarVersion = stream.ReadUInt32();

            if (sfarVersion != SfarVersion)
            {
                throw new Exception("Wrong SFAR version");
            }

            uint dataOffset    = stream.ReadUInt32();
            uint entriesOffset = stream.ReadUInt32();

            TotalFilesInDLC = stream.ReadUInt32();
            uint sizesArrayOffset = stream.ReadUInt32();

            maxBlockSize = stream.ReadUInt32();
            uint compressionTag = stream.ReadUInt32();

            if (compressionTag != LZMATag)
            {
                throw new Exception("Not LZMA compression for SFAR file");
            }

            uint numBlockSizes = 0;

            stream.JumpTo(entriesOffset);
            filesList = new List <DLCEntry>();
            for (int i = 0; i < TotalFilesInDLC; i++)
            {
                DLCEntry file = new DLCEntry
                {
                    filenameHash = stream.ReadToBuffer(16),
                    compressedBlockSizesIndex = stream.ReadInt32(),
                    uncomprSize = stream.ReadUInt32()
                };
                file.uncomprSize |= (long)stream.ReadByte() << 32;
                file.dataOffset   = stream.ReadUInt32();
                file.dataOffset  |= (long)stream.ReadByte() << 32;
                file.numBlocks    = (uint)((file.uncomprSize + maxBlockSize - 1) / maxBlockSize);
                filesList.Add(file);
                numBlockSizes    += file.numBlocks;
                UncompressedSize += file.uncomprSize;
            }

            stream.JumpTo(sizesArrayOffset);
            blockSizes = new List <ushort>();
            for (int i = 0; i < numBlockSizes; i++)
            {
                blockSizes.Add(stream.ReadUInt16());
            }

            filenamesIndex = -1;
            for (int i = 0; i < TotalFilesInDLC; i++)
            {
                if (StructuralComparisons.StructuralEqualityComparer.Equals(filesList[i].filenameHash, FileListHash))
                {
                    stream.JumpTo(filesList[i].dataOffset);
                    int    compressedBlockSize = blockSizes[filesList[i].compressedBlockSizesIndex];
                    byte[] inBuf  = stream.ReadToBuffer(compressedBlockSize);
                    byte[] outBuf = LZMA.Decompress(inBuf, (uint)filesList[i].uncomprSize);
                    if (outBuf.Length == 0)
                    {
                        throw new Exception();
                    }
                    StreamReader filenamesStream = new StreamReader(new MemoryStream(outBuf));
                    while (filenamesStream.EndOfStream == false)
                    {
                        string name = filenamesStream.ReadLine();
                        byte[] hash = MD5.Create().ComputeHash(Encoding.ASCII.GetBytes(name.ToLowerInvariant()));
                        for (int l = 0; l < TotalFilesInDLC; l++)
                        {
                            if (StructuralComparisons.StructuralEqualityComparer.Equals(filesList[l].filenameHash, hash))
                            {
                                DLCEntry f = filesList[l];
                                f.filenamePath = name.Replace('/', '\\');
                                filesList[l]   = f;
                            }
                        }
                    }
                    filenamesIndex = i;
                    break;
                }
            }
        }