public static IEnumerable <WZProperty> DirectoryChildren(WZProperty self) { using (WZReader reader = self.FileContainer.GetContentReader(null, self)) { reader.BaseStream.Seek(self.Offset, SeekOrigin.Begin); int count = reader.ReadWZInt(); WZProperty[] children = new WZProperty[count]; string name = null; for (int i = 0; i < count; ++i) { byte type = reader.ReadByte(); switch (type) { case 1: reader.ReadBytes(10); continue; case 2: int dedupedAt = (int)(reader.ReadInt32() + reader.ContentsStart); reader.PeekFor(() => { reader.BaseStream.Position = dedupedAt; type = reader.ReadByte(); name = reader.ReadWZString(false, self.Encrypted | self.Container.Encrypted); }); break; case 3: case 4: name = reader.ReadWZString(false, self.Encrypted | self.Container.Encrypted); break; default: throw new Exception("Unknown child type"); } if (name == null) { throw new InvalidOperationException("Found a property without a name, this shouldn't be possible."); } uint size = (uint)reader.ReadWZInt(); int checksum = reader.ReadWZInt(); uint offset = reader.ReadWZOffset(); WZProperty childProperty = new WZProperty( name, self != null ? Path.Combine(self.Path, name) : name, reader.Package, type == 3 ? PropertyType.Directory : type == 4 ? PropertyType.Image : throw new InvalidOperationException("Not sure what this is, but I don't handle it"), self, size, checksum, offset ); // These can be lazy loaded yield return(Resolve(reader.Package, childProperty)); } } }
public void Image(BinaryWriter writer, WZProperty self) { if (!imgLocations.ContainsKey(self)) { imgLocations.Add(self, (uint)writer.BaseStream.Position); } else { imgLocations[self] = (uint)writer.BaseStream.Position; // Pretty sure this should never happen } using (WZReader reader = self.FileContainer.GetContentReader(null, self)) { reader.BaseStream.Seek(self.Offset, SeekOrigin.Begin); writer.Write(reader.ReadBytes((int)self.Size)); } //writer.Write((byte)0x73); // Regular img //GetWZStringBytes(writer, "Property"); //writer.Write((short)0); //PropertyList(writer, self.Children); }
public static WZProperty Audio(WZReader reader, WZProperty self) { byte unk = reader.ReadByte(); int length = reader.ReadWZInt(); int duration = reader.ReadWZInt(); WZProperty result = new WZPropertyWeak <byte[]>( () => { Package.Logging($"{self.Path} (Audio) - {unk}"); using (reader = self.FileContainer.GetContentReader(null, self)) { reader.BaseStream.Seek(self.Offset + 1, SeekOrigin.Begin); if (length > sbyte.MaxValue || length <= sbyte.MinValue) { reader.BaseStream.Seek(5, SeekOrigin.Current); } else { reader.BaseStream.Seek(1, SeekOrigin.Current); } if (duration > sbyte.MaxValue || duration <= sbyte.MinValue) { reader.BaseStream.Seek(5, SeekOrigin.Current); } else { reader.BaseStream.Seek(1, SeekOrigin.Current); } return(reader.ReadBytes(length)); } }, self ); result.Size = (uint)length; result.Meta.Add("duration", duration); result.Meta.Add("unk", unk); return(result); }
public static byte[] ResolveHash(WZProperty prop) { using (WZReader reader = prop.FileContainer.GetContentReader(null, prop)) using (SHA1 sha = SHA1.Create()) { reader.BaseStream.Position = prop.Offset; switch (prop.Type) { case PropertyType.Image: reader.BaseStream.Position = prop.ContainerStartLocation; byte imgType = reader.ReadByte(); if (imgType == 1) { byte unk = reader.ReadByte(); return(reader.GetLuaScriptBytes().ToArray()); } else { return(new byte[0]); } case PropertyType.Directory: return(new byte[0]); case PropertyType.SubProperty: return(new byte[0]); case PropertyType.Convex: return(new byte[0]); case PropertyType.Vector2: return(sha.ComputeHash(reader.GetWZIntBytes().Concat(reader.GetWZIntBytes()).ToArray())); case PropertyType.UOL: return(sha.ComputeHash(reader.GetWZStringBlockBytes(prop.Encrypted | prop.Container.Encrypted))); case PropertyType.Audio: using (Stream sub = new SubStream(reader.BaseStream, (int)reader.BaseStream.Position, prop.Size)) return(sha.ComputeHash(sub)); case PropertyType.Canvas: reader.BaseStream.Seek(1, SeekOrigin.Current); byte[][] childHashes; if (reader.ReadByte() == 1) { reader.BaseStream.Seek(2, SeekOrigin.Current); childHashes = PropertyList(reader, prop).ToArray().Select(c => ResolveHash(c)).ToArray(); } else { childHashes = new byte[0][]; } int width = reader.ReadWZInt(); // width int height = reader.ReadWZInt(); // height int format1 = reader.ReadWZInt(); // format 1 byte format2 = reader.ReadByte(); // format 2 reader.BaseStream.Seek(4, SeekOrigin.Current); uint blockLen = (uint)reader.ReadInt32(); ushort header = reader.PeekFor(() => reader.ReadUInt16()); byte[] imageHash = new byte[0]; using (Stream sub = new SubStream(reader.BaseStream, reader.BaseStream.Position, blockLen - 1)) imageHash = sha.ComputeHash(sub); if (childHashes.Length > 0) { return(calcAggregateHash(sha, childHashes.Prepend(imageHash).ToArray())); } else { return(imageHash); } default: byte[] nameHash = sha.ComputeHash(reader.GetWZStringBlockBytes(prop.Encrypted | prop.Container.Encrypted)); byte type = reader.ReadByte(); switch (type) { case 0: return(nameHash); case 0x10: return(calcAggregateHash(sha, nameHash, sha.ComputeHash(reader.ReadBytes(1)))); case 0x11: return(calcAggregateHash(sha, nameHash, sha.ComputeHash(reader.ReadBytes(1)))); case 0x0B: case 2: case 0x12: return(calcAggregateHash(sha, nameHash, sha.ComputeHash(reader.ReadBytes(2)))); case 3: return(calcAggregateHash(sha, nameHash, sha.ComputeHash(reader.GetWZIntBytes()))); case 19: return(calcAggregateHash(sha, nameHash, sha.ComputeHash(reader.GetWZIntBytes()))); case 4: return(calcAggregateHash(sha, nameHash, sha.ComputeHash(reader.GetWZSingleBytes()))); case 5: return(calcAggregateHash(sha, nameHash, sha.ComputeHash(reader.ReadBytes(8)))); case 8: return(calcAggregateHash(sha, nameHash, sha.ComputeHash(reader.GetWZStringBlockBytes(prop.Container.Encrypted)))); case 9: return(calcAggregateHash(sha, nameHash, sha.ComputeHash(reader.ReadBytes(reader.ReadInt32())))); case 20: return(calcAggregateHash(sha, nameHash, sha.ComputeHash(reader.GetWZLongBytes()))); case 21: return(calcAggregateHash(sha, nameHash, sha.ComputeHash(reader.GetWZLongBytes()))); default: System.Diagnostics.Debugger.Break(); Console.WriteLine("Wow"); if (type > 100) { throw new Exception("Unknown property type at ParsePropertyList"); } else { return(new byte[0]); } } } } }