Beispiel #1
0
        public static IEnumerable <WZProperty> ImageChildren(WZProperty self)
        {
            using (WZReader reader = self.FileContainer.GetContentReader(null, self))
            {
                if (self.Offset >= reader.BaseStream.Length)
                {
                    yield break;
                }
                reader.BaseStream.Seek(self.Offset, SeekOrigin.Begin);

                if (reader.ReadByte() != 0x73)
                {
                    throw new InvalidOperationException("Image should have header of 0x73");
                }
                long oldPosition = reader.BaseStream.Position;
                if (!reader.ReadWZString(false, self.Encrypted).Equals("Property"))
                {
                    reader.BaseStream.Position = oldPosition;
                    if (!reader.ReadWZStringExpecting(out self.Encrypted, "Property", false))
                    {
                        throw new InvalidOperationException("Unknown encryption method");
                    }
                }
                if (reader.ReadInt16() != 0)
                {
                    throw new InvalidOperationException("Image needs to have 0 as part of header");
                }

                foreach (WZProperty prop in PropertyList(reader, self).ToArray())
                {
                    yield return(prop);
                }
            }
        }
Beispiel #2
0
        public static WZProperty Resolve(Package container, WZProperty self, WZReader reader)
        {
            switch (self.Type)
            {
            case PropertyType.Directory:
                return(self);

            case PropertyType.Image:
                return(Image(reader, self));

            case PropertyType.SubProperty:
                return(self);

            case PropertyType.Convex:
                return(self);

            case PropertyType.Vector2:
                return(Vector(reader, self));

            case PropertyType.Audio:
                return(Audio(reader, self));

            case PropertyType.Canvas:
                return(Canvas(reader, self));

            case PropertyType.UOL:
                return(UOL(reader, self));

            default:
                return(self);
            }
        }
Beispiel #3
0
        public Stream GetContentStream(WZProperty container = null)
        {
            Stream str = GetRawStream();

            str.Seek((container ?? MainDirectory).ContainerStartLocation, SeekOrigin.Begin);
            return(str);
        }
Beispiel #4
0
        public Package(PackageCollection parent, string fileLocation, ushort version = ushort.MinValue, bool?isImg = null)
        {
            Collection    = parent;
            FilePath      = fileLocation;
            FileName      = Path.GetFileNameWithoutExtension(FilePath).Replace(".rebuilt", "");
            streamFactory = new StreamFactory(() => File.Open(FilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
            isImg         = isImg ?? fileLocation.EndsWith(".img");

            using (WZReader file = GetRawReader()) {
                if (!isImg.Value)
                {
                    if (!file.ReadString(4).Equals("PKG1", StringComparison.CurrentCultureIgnoreCase))
                    {
                        throw new InvalidOperationException("Can not run on non-PKG1 files.");
                    }
                    FileSize = file.ReadInt64();
                    ContentsStartLocation = file.ReadUInt32();
                    FileDescription       = file.ReadNULTerminatedString(100);
                    Logging($"Loaded package {this.FileName} ({this.FileSize}, {this.ContentsStartLocation}) with Description: {this.FileDescription}");
                }
                MainDirectory = new WZProperty(FileName, FileName, this, isImg.Value ? PropertyType.Image : PropertyType.Directory, null, (uint)FileSize, -1, (uint)ContentsStartLocation + (uint)(isImg.Value ? 0 : 2));

                file.BaseStream.Seek(ContentsStartLocation, SeekOrigin.Begin);

                if (!isImg.Value)
                {
                    this.VersionHash = (byte)file.ReadUInt16();
                    Logging($"{this.FileName} - Version Hash: {this.VersionHash}");
                    if (!UpdateVersion(version))
                    {
                        Logging("Warning: Version is not wrong, expect corrupted / malformed data.");
                    }
                }
            }
        }
Beispiel #5
0
        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));
                }
            }
        }
Beispiel #6
0
        static WZProperty ParseExtendedProperty(WZReader reader, WZProperty parent, string name, bool maintainReader = false)
        {
            string       type = reader.ReadWZStringBlock(parent.Encrypted | parent.Container.Encrypted);
            PropertyType propType;

            switch (type)
            {
            case "Property":
                reader.BaseStream.Seek(2, SeekOrigin.Current);
                propType = PropertyType.SubProperty;
                break;

            case "Canvas":
                propType = PropertyType.Canvas;
                break;

            case "Shape2D#Vector2D":
                propType = PropertyType.Vector2;
                break;

            case "Shape2D#Convex2D":
                propType = PropertyType.Convex;
                break;

            case "Sound_DX8":
                propType = PropertyType.Audio;
                break;

            case "UOL":
                reader.BaseStream.Seek(1, SeekOrigin.Current);
                propType = PropertyType.UOL;
                break;

            default:
                throw new InvalidOperationException($"Unknown ExtendedProperty type {type}");
            }

            WZProperty result = new WZProperty(
                name,
                Path.Combine(parent.Path, name),
                parent.FileContainer,
                propType,
                parent,
                0,
                0,
                (uint)reader.BaseStream.Position
                );

            if (maintainReader)
            {
                return(Resolve(parent.FileContainer, result, reader));
            }
            else
            {
                return(Resolve(parent.FileContainer, result));
            }
        }
Beispiel #7
0
 public static WZProperty Resolve(Package container, WZProperty self)
 {
     // Determine lazy loading here
     using (WZReader reader = container.GetContentReader(null, self))
     {
         reader.BaseStream.Seek(self.Offset, SeekOrigin.Begin);
         return(Resolve(container, self, reader));
     }
 }
Beispiel #8
0
 public static IEnumerable <WZProperty> SubPropChildren(WZProperty self)
 {
     using (WZReader reader = self.FileContainer.GetContentReader(null, self))
     {
         reader.BaseStream.Seek(self.Offset, SeekOrigin.Begin);
         foreach (WZProperty prop in PropertyList(reader, self).ToArray())
         {
             yield return(prop);
         }
     }
 }
Beispiel #9
0
 public static IEnumerable <WZProperty> ConvexChildren(WZProperty self)
 {
     using (WZReader reader = self.FileContainer.GetContentReader(null, self))
     {
         reader.BaseStream.Position = self.Offset;
         int count = reader.ReadWZInt();
         for (int i = 0; i < count; ++i)
         {
             yield return(ParseExtendedProperty(reader, self, i.ToString(), true));
         }
     }
 }
        public void Lua(BinaryWriter writer, WZProperty self)
        {
            writer.Write((byte)0x01);
            string s       = ((IWZPropertyVal <string>)self).Value;
            bool   isASCII = s.All(c => c <= byte.MaxValue);
            int    length  = s.Length * (isASCII ? -1 : 1);

            IEnumerable <byte> lengthBytes;

            if (length >= 127)
            {
                lengthBytes = new byte[] { 127 }
            }
Beispiel #11
0
        static WZProperty Canvas(WZReader reader, WZProperty self)
        {
            // Define the variables ahead of time that way we can come back to them
            int  width = 0, height = 0, format1 = 0, format2 = 0;
            uint blockLen = 0, position = 0;

            // Define what well be doing once we come back
            WZProperty result = new WZPropertyWeak <Image <Rgba32> >(
                () => {
                using (reader = self.FileContainer.GetContentReader(null, self))
                {
                    reader.BaseStream.Seek(position + 1, SeekOrigin.Begin);
                    ushort header = reader.PeekFor(() => reader.ReadUInt16());
                    return(reader.ParsePNG(
                               width,
                               height,
                               format1 + format2,
                               header != 0x9C78 && header != 0xDA78,
                               blockLen - 1
                               ));
                }
            }, self
                );

            reader.BaseStream.Seek(1, SeekOrigin.Current);
            if (reader.ReadByte() == 1) // Has children
            {
                reader.BaseStream.Seek(2, SeekOrigin.Current);
                result.Children = PropertyList(reader, result).ToArray();
            }
            else
            {
                result.Children = new WZProperty[0];
            }
            width   = reader.ReadWZInt(); // width
            height  = reader.ReadWZInt(); // height
            format1 = reader.ReadWZInt(); // format 1
            format2 = reader.ReadByte();  // format 2
            reader.BaseStream.Seek(4, SeekOrigin.Current);
            blockLen    = (uint)reader.ReadInt32();
            result.Size = (uint)blockLen;
            position    = (uint)reader.BaseStream.Position;

            return(result);
        }
Beispiel #12
0
        public static WZProperty Image(WZReader reader, WZProperty self)
        {
            if (self.Offset >= reader.BaseStream.Length)
            {
                return(self);
            }
            self.ContainerStartLocation = self.Offset;
            reader.Container            = self;
            byte imgType = reader.ReadByte();

            if (imgType == 1)
            {
                return(new WZPropertyWeak <string>(() =>
                {
                    using (reader = self.FileContainer.GetContentReader(null, self))
                    {
                        reader.BaseStream.Seek(self.Offset, SeekOrigin.Begin);
                        reader.ReadByte();
                        return reader.ReadLuaScript();
                    }
                }, self.NameWithoutExtension, self.Path, self.FileContainer, PropertyType.Lua, self.Parent, self.Size, self.Checksum, self.Offset));
            }
            if (imgType != 0x73)
            {
                throw new InvalidOperationException("Unknown image type, not supported!");
            }
            long oldPosition = reader.BaseStream.Position;

            if (!reader.ReadWZString(false, self.Encrypted).Equals("Property"))
            {
                reader.BaseStream.Position = oldPosition;
                if (!reader.ReadWZStringExpecting(out self.Encrypted, "Property", false))
                {
                    throw new InvalidOperationException("Unknown encryption method");
                }
            }
            if (reader.ReadInt16() != 0)
            {
                throw new InvalidOperationException("Image needs to have 0 as part of header");
            }

            return(self);
        }
        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);
        }
Beispiel #14
0
        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);
        }
Beispiel #15
0
 public WZPropertyVal(K val, string name, string path, Package container, PropertyType type, WZProperty parent, uint size, int checksum, uint offset)
     : base(name, path, container, type, parent, size, checksum, offset)
 {
     Value = val;
 }
Beispiel #16
0
 public WZPropertyVal(K val, WZProperty original)
     : this(val, original.NameWithoutExtension, original.Path, original.FileContainer, original.Type, original.Parent, original.Size, original.Checksum, original.Offset)
 {
     this.Encrypted = original.Encrypted;
 }
Beispiel #17
0
 public WZPropertyWeak(Func <K> val, string name, string path, Package container, PropertyType type, WZProperty parent, uint size, int checksum, uint offset) : base(name, path, container, type, parent, size, checksum, offset)
 {
     _weakValue = new WeakishReference <K>(null, val);
 }
Beispiel #18
0
 public WZReader GetContentReader(Encoding encoding = null, WZProperty container = null) => new WZReader(this, container ?? MainDirectory, GetContentStream(container), encoding ?? Encoding.ASCII, VersionKey, VersionHash, ContentsStartLocation);
Beispiel #19
0
        public static IEnumerable <WZProperty> PropertyList(WZReader reader, WZProperty parent)
        {
            if (reader.BaseStream.Position + 4 >= reader.BaseStream.Length)
            {
                return(new WZProperty[0]);
            }
            return(Enumerable.Range(0, reader.ReadWZInt()).Select(i =>
            {
                uint position = (uint)reader.BaseStream.Position;
                if (position >= reader.BaseStream.Length)
                {
                    return null;
                }
                string name = reader.ReadWZStringBlock(parent.Encrypted | parent.Container.Encrypted);
                byte type = reader.ReadByte();
                switch (type)
                {
                case 0:
                    return new WZProperty(name, Path.Combine(parent.Path, name), parent.FileContainer, PropertyType.Null, parent, 0, 0, position);

                case 0x10:
                    return new WZPropertyVal <sbyte>(reader.ReadSByte(), name, Path.Combine(parent.Path, name), parent.FileContainer, PropertyType.UInt16, parent, 1, 0, position);

                case 0x11:
                    return new WZPropertyVal <byte>(reader.ReadByte(), name, Path.Combine(parent.Path, name), parent.FileContainer, PropertyType.UInt16, parent, 1, 0, position);

                case 0x0B:
                case 2:
                case 0x12:
                    return new WZPropertyVal <UInt16>(reader.ReadUInt16(), name, Path.Combine(parent.Path, name), parent.FileContainer, PropertyType.UInt16, parent, 2, 0, position);

                case 3:
                    return new WZPropertyVal <Int32>(reader.ReadWZInt(), name, Path.Combine(parent.Path, name), parent.FileContainer, PropertyType.Int32, parent, 4, 0, position);

                case 19:
                    return new WZPropertyVal <Rgba32>(new Rgba32((uint)reader.ReadWZInt()), name, Path.Combine(parent.Path, name), parent.FileContainer, PropertyType.Int32, parent, 4, 0, position);

                case 4:
                    return new WZPropertyVal <Single>(reader.ReadWZSingle(), name, Path.Combine(parent.Path, name), parent.FileContainer, PropertyType.Single, parent, 4, 0, position);

                case 5:
                    return new WZPropertyVal <Double>(reader.ReadDouble(), name, Path.Combine(parent.Path, name), parent.FileContainer, PropertyType.Double, parent, 8, 0, position);

                case 8:
                    return new WZPropertyVal <string>(reader.ReadWZStringBlock(parent.Encrypted | parent.Container.Encrypted), name, Path.Combine(parent.Path, name), parent.FileContainer, PropertyType.String, parent, 0, 0, position);

                case 9:
                    uint blockLen = reader.ReadUInt32();
                    WZProperty result = reader.PeekFor(() => ParseExtendedProperty(reader, parent, name));
                    reader.BaseStream.Seek(blockLen, SeekOrigin.Current);
                    return result;

                case 20:
                    return new WZPropertyVal <long>(reader.ReadWZLong(), name, Path.Combine(parent.Path, name), parent.FileContainer, PropertyType.Int64, parent, 8, 0, position);

                case 21:
                    return new WZPropertyVal <ulong>((ulong)reader.ReadWZLong(), name, Path.Combine(parent.Path, name), parent.FileContainer, PropertyType.Int64, parent, 8, 0, position);

                default:
                    throw new Exception("Unknown property type at ParsePropertyList");
                }
            }));
        }
Beispiel #20
0
        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]);
                            }
                        }
                    }
                }
        }
Beispiel #21
0
 public static WZProperty Vector(WZReader reader, WZProperty self)
 => new WZPropertyVal <Point>(new Point(reader.ReadWZInt(), reader.ReadWZInt()), self);
Beispiel #22
0
 public static WZProperty UOL(WZReader reader, WZProperty self)
 => new WZPropertyVal <string>(reader.ReadWZStringBlock(self.Encrypted | self.Container.Encrypted), self);