public void Load() { var sw = Stopwatch.StartNew(); while (true) { using (var texReader = new BinaryReader(File.OpenRead(_textureFile))) { Byte[] IsCompressed = texReader.ReadBytes(2); if (BitConverter.ToString(IsCompressed) == "53-43") { texReader.BaseStream.Seek(26, SeekOrigin.Begin); DialogResult result = MessageBox.Show("The tool detected that you have load a compressed file.\nWould you like to decompress and load it?\nPlease note,Choosing to decompressed will override the compressed file with a new one", "SC File Is Compresed", MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button2); if (result == DialogResult.Yes) { string IsSc = BitConverter.ToString(texReader.ReadBytes(2)); texReader.Close(); if (IsSc == "53-43") { Lzham.DecompressSc(_textureFile); } else { Lzma.Decompress(_textureFile); } continue; } break; } Console.WriteLine(texReader.BaseStream.Length); texReader.BaseStream.Seek(0, SeekOrigin.Begin); while (true) { long texoffset = texReader.BaseStream.Position; var packetId = texReader.ReadByte(); var packetSize = texReader.ReadUInt32(); if (packetSize > 0) { var tex = new Texture(this); tex.SetOffset(texoffset); tex.Read(packetId, packetSize, texReader); this._textures.Add(tex); if (texReader.BaseStream.Position != texReader.BaseStream.Length) { continue; } } _eofTexOffset = texoffset; break; } } break; } while (true) { using (var reader = new BinaryReader(File.OpenRead(_infoFile))) { Byte[] IsCompressed = reader.ReadBytes(2); Console.WriteLine(BitConverter.ToString(IsCompressed) == "53-43"); if (BitConverter.ToString(IsCompressed) == "53-43") { reader.BaseStream.Seek(26, SeekOrigin.Begin); DialogResult result = MessageBox.Show("The tool detected that you have load a compressed file.\nWould you like to decompress and load it?\nPlease note,Choosing to decompressed will override the compressed file with a new one", @"SC File Is Compresed", MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button2); if (result == DialogResult.Yes) { string IsSc = BitConverter.ToString(reader.ReadBytes(2)); reader.Close(); if (IsSc == "53-43") { Lzham.DecompressSc(_infoFile); } else { Lzma.Decompress(_infoFile); } continue; } break; } reader.BaseStream.Seek(0, SeekOrigin.Begin); var shapeCount = reader.ReadUInt16(); // a1 + 8 var movieClipCount = reader.ReadUInt16(); // a1 + 12 var textureCount = reader.ReadUInt16(); // a1 + 16 var textFieldCount = reader.ReadUInt16(); // a1 + 24 var matrixCount = reader.ReadUInt16(); // a1 + 28 var colorTransformCount = reader.ReadUInt16(); // a1 + 32 int colorTransfromID = 0; #if DEBUG Console.WriteLine(@"ShapeCount: " + shapeCount); Console.WriteLine(@"MovieClipCount: " + movieClipCount); Console.WriteLine(@"TextureCount: " + textureCount); Console.WriteLine(@"TextFieldCount: " + textFieldCount); Console.WriteLine(@"Matrix2x3Count: " + matrixCount); Console.WriteLine(@"ColorTransformCount: " + colorTransformCount); #endif // 5 useless bytes, not even used by Supercell reader.ReadByte(); // 1 octet reader.ReadUInt16(); // 2 octets reader.ReadUInt16(); // 2 octets _exportStartOffset = reader.BaseStream.Position; _exportCount = reader.ReadUInt16(); // a1 + 20 Console.WriteLine(@"ExportCount: " + _exportCount); // Reads the Export IDs. for (int i = 0; i < _exportCount; i++) { var export = new Export(this); export.SetId(reader.ReadUInt16()); _exports.Add(export); } // Reads the Export names. for (int i = 0; i < _exportCount; i++) { var nameLength = reader.ReadByte(); var name = Encoding.UTF8.GetString(reader.ReadBytes(nameLength)); var export = (Export)_exports[i]; export.SetExportName(name); } while (reader.BaseStream.Position != reader.BaseStream.Length) { long offset = reader.BaseStream.Position; var datatag = reader.ReadByte(); var tag = datatag.ToString("X2"); //Block type var tagSize = reader.ReadUInt32(); //Size in bytes #if DEBUG //Console.WriteLine("dataBlockTag: " + tag); //Console.WriteLine("dataBlockSize: " + tagSize); #endif switch (tag) { default: //Console.WriteLine("dataBlockTag: " + tag); //Console.WriteLine("dataBlockSize: " + tagSize); var defaultDataBlockContent = reader.ReadBytes(Convert.ToInt32(tagSize)); defaultDataBlockContent = null; break; case "00": _eofOffset = offset; foreach (ScObject t in _exports) { int index = _movieClips.FindIndex(movie => movie.Id == t.Id); if (index != -1) { ((Export)t).SetDataObject((MovieClip)_movieClips[index]); } } break; case "01": case "18": if (tagSize > 6) { var texture = new Texture(this); texture.SetOffset(offset); texture.Read(UInt32.Parse(tag), tagSize, reader); //_eofTexOffset = reader.BaseStream.Position; this._textures.Add(texture); } else { var pixelFormat = reader.ReadByte(); var width = reader.ReadUInt16(); var height = reader.ReadUInt16(); Console.WriteLine("pixelFormat: " + pixelFormat); Console.WriteLine("width: " + width); Console.WriteLine("height: " + height); } break; case "02": case "12": var shape = new Shape(this); shape.SetOffset(offset); shape.Read(reader, tag); this._shapes.Add(shape); break; case "03": case "0C": var movieClip = new MovieClip(this, datatag); movieClip.SetOffset(offset); movieClip.Read(reader, tag); _movieClips.Add(movieClip); break; case "08": float[] Points = new float[6]; for (int Index = 0; Index < 6; Index++) { Points[Index] = reader.ReadInt32(); } Matrix _Matrix = new Matrix(Points[0] / 1024, Points[1] / 1024, Points[2] / 1024, Points[3] / 1024, Points[4] / -20, Points[5] / -20); this._matrixs.Add(_Matrix); //Console.WriteLine("\t matrixVal: " + Points[0] / 1024 + "\n\t matrixVal: " + Points[1] / 1024 + "\n\t matrixVal: " + Points[2] / 1024 + "\n\t matrixVal: " + Points[3] / 1024 + "\n\t matrixVal: " + Points[4] / -20 + "\n\t matrixVal: " + Points[5] / -20); break; case "09": var ra = reader.ReadByte(); var ga = reader.ReadByte(); var ba = reader.ReadByte(); var am = reader.ReadByte(); var rm = reader.ReadByte(); var gm = reader.ReadByte(); var bm = reader.ReadByte(); this._colors.Add(new Tuple <Color, byte, Color>(Color.FromArgb(ra, ga, ba), am, Color.FromArgb(rm, gm, bm))); //int id = this._colors.Count - 1; //Console.WriteLine("\t -ct-" + id + "--ColorA: rgb(" + this._colors[id].Item1.R + "," + this._colors[id].Item1.G + "," + this._colors[id].Item1.B + ") & " + this._colors[id].Item2 + " & rgb(" + this._colors[id].Item3.R + "," + this._colors[id].Item3.G + "," + this._colors[id].Item3.B + ")"); break; } } sw.Stop(); Program.Interface.Text = $@"Royale Editor : {Path.GetFileNameWithoutExtension(_textureFile)}"; Program.Interface.Update(); Console.WriteLine(@"SC File loading finished in {0}ms", sw.Elapsed.TotalMilliseconds); } break; } }
public uint Finish() { handle = IntPtr.Zero; return(Lzham.DecompressDeinit(handle)); }
public static LoadError LoadFromStream(Stream stream, out Cnk0 cnk0) { if (stream == null) { cnk0 = null; return(LoadError.NullStream); } BinaryReader binaryReader = new BinaryReader(stream); //header char[] magic = binaryReader.ReadChars(4); if (magic[0] != 'C' || magic[1] != 'N' || magic[2] != 'K' || magic[3] != '0') { cnk0 = null; return(LoadError.BadHeader); } int version = binaryReader.ReadInt32(); if (version != VERSION) { cnk0 = null; return(LoadError.VersionMismatch); } uint uncompressedSize = binaryReader.ReadUInt32(); uint compressedSize = binaryReader.ReadUInt32(); byte[] inputBuffer = binaryReader.ReadBytes((int)compressedSize); binaryReader.Close(); byte[] outputBuffer = new byte[uncompressedSize]; Lzham.ZStream zStream = new Lzham.ZStream(); Lzham.ZInflateInit2(zStream, 20); zStream.AvailableInputBytes = compressedSize; zStream.AvailableOutputBytes = uncompressedSize; GCHandle inputBufferGCHandle = GCHandle.Alloc(inputBuffer, GCHandleType.Pinned); GCHandle outputBufferGCHandle = GCHandle.Alloc(outputBuffer, GCHandleType.Pinned); zStream.NextInputByte = inputBufferGCHandle.AddrOfPinnedObject(); zStream.NextOutputByte = outputBufferGCHandle.AddrOfPinnedObject(); Lzham.ZInflate(zStream, (int)Lzham.ZFlush.Finish); Lzham.ZInflateEnd(zStream); inputBufferGCHandle.Free(); outputBufferGCHandle.Free(); MemoryStream memoryStream = new MemoryStream(outputBuffer); binaryReader = new BinaryReader(memoryStream); cnk0 = new Cnk0(); //tiles uint tileCount = binaryReader.ReadUInt32(); cnk0.Tiles = new Tile[tileCount]; for (uint i = 0; i < tileCount; ++i) { Tile tile; if (Tile.LoadFromStream(memoryStream, out tile) != Tile.LoadError.None) { cnk0 = null; return(LoadError.BadTile); } cnk0.Tiles[i] = tile; } //unknown block uint unknown0 = binaryReader.ReadUInt32(); uint unknown1 = binaryReader.ReadUInt32(); binaryReader.BaseStream.Seek(unknown1 * 4, SeekOrigin.Current); //indices uint indexCount = binaryReader.ReadUInt32(); cnk0.Indices = new ushort[indexCount]; for (int i = 0; i < indexCount; ++i) { cnk0.Indices[i] = binaryReader.ReadUInt16(); } //vertices uint vertexCount = binaryReader.ReadUInt32(); cnk0.Vertices = new Vertex[vertexCount]; for (int i = 0; i < vertexCount; ++i) { Vertex vertex; if (Vertex.LoadFromStream(binaryReader.BaseStream, out vertex) != Vertex.LoadError.None) { cnk0 = null; return(LoadError.BadVertex); } cnk0.Vertices[i] = vertex; } //render batches uint renderBatchCount = binaryReader.ReadUInt32(); cnk0.RenderBatches = new RenderBatch[renderBatchCount]; for (uint i = 0; i < renderBatchCount; ++i) { RenderBatch renderBatch; if (RenderBatch.LoadFromStream(binaryReader.BaseStream, out renderBatch) != RenderBatch.LoadError.None) { cnk0 = null; return(LoadError.BadRenderBatch); } cnk0.RenderBatches[i] = renderBatch; } binaryReader.Close(); return(LoadError.None); }
/// <summary> /// Reads the entry from the VPK package. /// </summary> /// <param name="entry">Package entry.</param> /// <param name="progressReporter">Progress report callback.</param> /// <param name="validateCrc">If true, CRC32 will be calculated and verified for read data.</param> /// <returns>Output buffer.</returns> public async Task <Memory <byte> > ReadEntryAsync(PackageEntry entry, IProgress <int> progressReporter, bool validateCrc = true) { DecompressState decompressState = null; var parameters = new DecompressParameters(); parameters.DictSizeLog2 = 20; var blockReadBuffer = new Memory <byte>(new byte[MAX_ENTRY_CHUNK_SIZE]); var outputBuffer = new Memory <byte>(new byte[entry.SmallData.Length + entry.TotalLength]); var outputOffset = 0; if (entry.SmallData.Length > 0) { entry.SmallData.CopyTo(outputBuffer); outputOffset += entry.SmallData.Length; } if (entry.TotalCompressedLength < entry.TotalLength) { decompressState = Lzham.DecompressInit(parameters); } if (entry.TotalLength > 0) { Stream fs = null; ushort currentArchiveIndex = 0x7FFF; try { foreach (var chunk in entry.Chunks) { var streamOffset = chunk.Offset; if (currentArchiveIndex != chunk.ArchiveIndex) { currentArchiveIndex = chunk.ArchiveIndex; fs?.Close(); } if (chunk.ArchiveIndex != 0x7FFF) { if (currentArchiveIndex != chunk.ArchiveIndex) { currentArchiveIndex = chunk.ArchiveIndex; fs?.Close(); } if (!IsDirVPK) { throw new InvalidOperationException("Given VPK is not a _dir, but entry is referencing an external archive."); } var vpkDirectory = Path.GetDirectoryName(FileName); var vpkName = Path.GetFileName(FileName); foreach (var prefix in VPK_PREFIXES) { if (vpkName.StartsWith(prefix)) { vpkName = vpkName.Substring(prefix.Length); break; } } var fileName = Path.Combine(vpkDirectory, $"{vpkName}_{chunk.ArchiveIndex:D3}.vpk"); fs = new FileStream(fileName, FileMode.Open, FileAccess.Read); } else { fs = Reader.BaseStream; streamOffset += HeaderSize + TreeSize; } fs.Seek(streamOffset, SeekOrigin.Begin); var readBuffer = blockReadBuffer.Slice(0, (int)chunk.CompressedLength); var bytesRead = await fs.ReadAsync(readBuffer); if (bytesRead != chunk.CompressedLength) { throw new InvalidOperationException($"Attempted to read {chunk.CompressedLength} bytes, got {bytesRead.ToString()}."); } if (chunk.CompressedLength < chunk.Length) { var decompressedSpan = outputBuffer.Slice(outputOffset); var decompressResult = Lzham.DecompressMemory(parameters, readBuffer, ref decompressedSpan); if (decompressResult != DecompressStatus.Success) { throw new InvalidOperationException($"Error attempting to decompress: {decompressResult.ToString()}"); } outputOffset += (int)chunk.Length; } else { readBuffer.CopyTo(outputBuffer.Slice(outputOffset)); outputOffset += bytesRead; } if (progressReporter != null) { progressReporter.Report(outputOffset); } } } finally { if (currentArchiveIndex != 0x7FFF) { fs?.Close(); } } } if (validateCrc && entry.CRC32 != Crc32.Compute(outputBuffer)) { throw new InvalidDataException("CRC32 mismatch for read data."); } if (decompressState != null) { var deinitResult = Lzham.DecompressDeinit(decompressState); if (deinitResult >= DecompressStatus.FirstFailureCode) { throw new InvalidOperationException($"Error attempting to deinitialize compressor: {deinitResult.ToString()}"); } } return(outputBuffer); }