/// <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); }
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); }
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); }
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]); } } }
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); }
/// <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); } }
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; } }
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); } } } }
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); }
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); } } }
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); } }
/// <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); }
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); }
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); } } } }
/// <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 { } }
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; } } } }
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; } } }