Exemplo n.º 1
0
        public void Deserialize(Stream input)
        {
            var magic = input.ReadValueU32(Endian.Little);

            if (magic != 0x4643626E) // FCbn
            {
                throw new FormatException();
            }
            var endian = Endian.Little;

            var version = input.ReadValueU16(endian);

            if (version != 2)
            {
                throw new FormatException();
            }

            this.Flags = input.ReadValueU16(endian);
            if (this.Flags != 0)
            {
                throw new FormatException();
            }

            var totalObjectCount = input.ReadValueU32(endian);
            var totalValueCount  = input.ReadValueU32(endian);

            var pointers = new List <Object>();

            /*this.Root = new Object();
             * this.Root.Deserialize(input, pointers, endian);*/
            this.Root = Object.Deserialize(input, pointers, endian);
        }
Exemplo n.º 2
0
 public int Deserialize(Stream input)
 {
     _opFlags     = input.ReadValueU16();
     _opTargetNum = input.ReadValueU16();
     _opFuncName  = input.ReadValueEncodedS32();
     return(8);
 }
Exemplo n.º 3
0
        public override void Deserialize(Stream input, Endian endian)
        {
            base.Deserialize(input, endian);

            var previousPointer = input.ReadValueU64(endian);
            var nextPointer     = input.ReadValueU64(endian);

            this._ParentsOffset     = input.ReadOffset(endian);
            this._DataOffset        = input.ReadOffset(endian);
            this._DefaultBitsOffset = input.ReadOffset(endian);
            this._PropertiesOffset  = input.ReadOffset(endian);
            this._Name           = Symbol.Read(input, endian);
            this._ReferenceCount = input.ReadValueU16(endian);
            this._ParentCount    = input.ReadValueU16(endian);
            this._ParentMask     = input.ReadValueU32(endian);
            this._SchemaName     = Symbol.Read(input, endian);
            this._PropertyMask   = input.ReadValueU32(endian);
            this._DataSize       = input.ReadValueU16(endian);
            this._PropertyCount  = input.ReadValueU16(endian);

            if (previousPointer != 0 || nextPointer != 0)
            {
                throw new FormatException();
            }
        }
Exemplo n.º 4
0
        public override void Read(Stream s)
        {
            var numElems = s.ReadValueS32(Endianness);

            for (var i = 0; i < numElems; i++)
            {
                var str = new ItemData
                {
                    ItemId   = s.ReadValueU16(Endianness),
                    Unknown1 = s.ReadValueU16(Endianness),
                };

                var dataLength = s.ReadValueU32(Endianness);
                if (dataLength > 0)
                {
                    str.Data1 = ReadString(s, dataLength * 2, $"{str.ItemId:0000}-{str.Unknown1:X4}");
                }

                dataLength = s.ReadValueU32(Endianness);
                if (dataLength > 0)
                {
                    str.Data2 = ReadString(s, dataLength * 2, $"{str.ItemId:0000}-{str.Unknown1:X4}");
                }

                _strings.Add(str);
            }
        }
Exemplo n.º 5
0
        public void Deserialize(Stream input)
        {
            var magic = input.ReadValueU32();

            if (magic != 0xBEEFFEED)
            {
                throw new FormatException("not an asm file");
            }

            var endian = magic == 0xBEEFFEED ? Endian.Little : Endian.Big;

            var version = input.ReadValueU16(endian);

            if (version != 5)
            {
                throw new FormatException("unsupported asm version " + this._Version);
            }

            var containerCount = input.ReadValueU16();

            var containers = new Asm.ContainerEntry[containerCount];

            for (ushort i = 0; i < containerCount; i++)
            {
                var container = new Asm.ContainerEntry();
                container.Deserialize(input, this._Version, endian);
                containers[i] = container;
            }

            this._Endian  = endian;
            this._Version = version;
            this._Containers.Clear();
            this._Containers.AddRange(containers);
        }
Exemplo n.º 6
0
        public void Read(Stream input)
        {
            uint first  = input.ReadValueU16();
            uint second = input.ReadValueU16();

            uint whole = (first << 16) + second;

            delta_from_prev_id = second;
            if (whole >= 0x80000000)
            {
                size = input.ReadValueU16();
                if (((whole >> 30) & 1) != 0)
                {
                    uint extra = input.ReadValueU16();
                    delta_from_prev_id += (extra << 16);
                }
                max_id = first & 0x3FFF;
            }
            else
            {
                max_id              = first >> 7;
                size                = (whole >> 12) & 0x7FF;
                delta_from_prev_id &= 0xFFF;
            }
        }
Exemplo n.º 7
0
        public void Deserialize(Stream input, ushort version, Endian endian)
        {
            this.Name  = input.ReadStringU16(0x40, Encoding.ASCII, endian);
            this.Type  = input.ReadValueU8();
            this.Flags = input.ReadValueU16(endian);
            var primitiveCount = input.ReadValueU16(endian);

            this.DataOffset = input.ReadValueU32(endian);
            var sizeCount = input.ReadValueU32(endian);

            this.CompressedSize = input.ReadValueU32(endian);

            for (ushort i = 0; i < sizeCount; i++)
            {
                this.Sizes.Add(input.ReadValueS32(endian));
            }

            this.Primitives.Clear();
            for (ushort i = 0; i < primitiveCount; i++)
            {
                var primitive = new PrimitiveEntry();
                primitive.Deserialize(input, endian);
                this.Primitives.Add(primitive);
            }
        }
Exemplo n.º 8
0
 public void Deserialize(Stream input, Endian endian)
 {
     this.Size              = input.ReadValueU32(endian);
     this.pat               = input.ReadValueU16(endian);
     this.Flags             = input.ReadValueEnum <HeaderFlags>(endian);
     this.pat2              = input.ReadValueU16(endian);
     this.Height            = input.ReadValueS16(endian);
     this.pat3              = input.ReadValueU16(endian);
     this.Width             = input.ReadValueS16(endian);
     this.pat4              = input.ReadValueU16(endian);
     this.PitchOrLinearSize = input.ReadValueU32(endian);
     this.Depth             = input.ReadValueU32(endian);
     this.MipMapCount       = input.ReadValueU32(endian);
     if (input.Read(this.Reserved1, 0, this.Reserved1.Length) != this.Reserved1.Length)
     {
         throw new EndOfStreamException();
     }
     this.PixelFormat.Deserialize(input, endian);
     this.SurfaceFlags = input.ReadValueU32(endian);
     this.CubemapFlags = input.ReadValueU32(endian);
     if (input.Read(this.Reserved2, 0, this.Reserved2.Length) != this.Reserved2.Length)
     {
         throw new EndOfStreamException();
     }
 }
        public static List <string> Dump(Stream input)
        {
            var endian = Endian.Little;

            var magic = input.ReadValueU32(endian);

            if (magic != 0x4643626E) // FCbn
            {
                throw new FormatException();
            }

            if (input.ReadValueU16(endian) != 2)
            {
                throw new FormatException();
            }

            var flags = input.ReadValueU16(endian);

            if (flags != 0)
            {
                throw new FormatException();
            }

            input.Seek(4, SeekOrigin.Current);
            input.Seek(4, SeekOrigin.Current);

            var values = new List <string>();

            Object.Dump(input, values, endian);
            return(values);
        }
Exemplo n.º 10
0
        public static string Deserialize(Stream input, Endian endian)
        {
            if (input.ReadValueU16(endian) != 0x5842) // 'BX'
            {
                throw new FormatException();
            }

            if (input.ReadValueU16(endian) > 1)
            {
                throw new FormatException();
            }

            var root = (NodeEntry)DeserializeNodeEntry(input, endian);

            var settings = new XmlWriterSettings();

            settings.Indent = true;

            var output = new StringBuilder();
            var writer = XmlWriter.Create(output, settings);

            writer.WriteStartDocument();
            WriteXmlNode(writer, root);
            writer.WriteEndDocument();

            writer.Flush();
            return(output.ToString());
        }
        public static TextureHeader Read(Stream input)
        {
            const Endian endian = Endian.Little;

            TextureHeader instance;

            instance.Unknown00     = input.ReadValueU32(endian);
            instance.Unknown04     = input.ReadValueU32(endian);
            instance.Type          = (TextureType)input.ReadValueU32(endian);
            instance.Format        = (TextureFormat)input.ReadValueU32(endian);
            instance.Unknown10     = input.ReadValueU32(endian);
            instance.Unknown14     = input.ReadValueU16(endian);
            instance.Width         = input.ReadValueU16(endian);
            instance.Height        = input.ReadValueU16(endian);
            instance.Depth         = input.ReadValueU16(endian);
            instance.Unknown1C     = input.ReadValueU16(endian);
            instance.MipCount      = input.ReadValueU8();
            instance.FirstMipIndex = input.ReadValueU8();
            instance.DataChunkId   = input.ReadValueGuid(Endian.Big);
            instance.MipSizes      = new uint[15];
            for (int i = 0; i < 15; i++)
            {
                instance.MipSizes[i] = input.ReadValueU32(endian);
            }
            instance.TotalSize = input.ReadValueU32(endian);
            instance.Unknown70 = input.ReadBytes(16);
            instance.Unknown80 = input.ReadValueU32(endian);
            instance.Unknown84 = input.ReadString(16, true, Encoding.UTF8);
            return(instance);
        }
        public void Deserialize(Stream input, Endian endian)
        {
            var magic = input.ReadValueU64(endian);

            if (magic != Signature)
            {
                throw new SaveFormatException("invalid save metadata signature");
            }

            var version = input.ReadValueU16(endian);

            if (version != 1)
            {
                throw new SaveFormatException("unsupported save metadata version");
            }

            var count  = input.ReadValueU32(endian);
            var values = new List <KeyValuePair <uint, string> >();

            for (uint i = 0; i < count; i++)
            {
                var nameHash    = input.ReadValueU32(endian);
                var valueLength = input.ReadValueU16(endian);
                var value       = input.ReadString(valueLength, true, Encoding.UTF8);
                values.Add(new KeyValuePair <uint, string>(nameHash, value));
            }

            this._Values.Clear();
            this._Values.AddRange(values);
        }
Exemplo n.º 13
0
        public override void Read(Stream s)
        {
            _magic = s.ReadBytes(3);

            var stringGroupsCount       = s.ReadByte();
            var stringGroupStartPointer = s.ReadValueU32(Endianness);
            var table1Pointer           = s.ReadValueU32(Endianness);
            var table1Count             = s.ReadValueU16(Endianness);
            var titlesCount             = s.ReadValueU16(Endianness);
            var titlesPointer           = s.ReadValueU32(Endianness);
            var remainderPointer        = s.ReadValueU32(Endianness);

            for (var i = 0; i < stringGroupsCount; i++)
            {
                s.Seek(stringGroupStartPointer + i * 16, SeekOrigin.Begin);
                var strGroup = ReadStringGroup(s);
                _stringGroups.Add(strGroup);
            }

            s.Seek(table1Pointer, SeekOrigin.Begin);
            _table1 = s.ReadBytes(table1Count * 16);

            for (var i = 0; i < titlesCount; i++)
            {
                s.Seek(titlesPointer + i * 4, SeekOrigin.Begin);
                var title = ReadTitle(s);
                _tableTitles.Add(title);
            }

            s.Seek(remainderPointer, SeekOrigin.Begin);
            _remainder = s.ReadBytes((int)(s.Length - remainderPointer));
        }
Exemplo n.º 14
0
        public static ResourceHeader Read(Stream input, Endian endian, uint version)
        {
            ResourceHeader instance;

            instance.TypeId            = input.ReadValueU32(endian);
            instance.Size              = input.ReadValueU32(endian);
            instance.Version           = input.ReadValueU16(endian);
            instance.SlotRamRequired   = input.ReadValueU32(endian);
            instance.SlotVramRequired  = input.ReadValueU32(endian);
            instance.OtherRamRequired  = input.ReadValueU32(endian);
            instance.OtherVramRequired = input.ReadValueU32(endian);

            if (version == 20)
            {
                instance.Unk01 = input.ReadValueU16(endian);
                instance.Unk02 = input.ReadValueU32(endian);
                instance.Unk03 = input.ReadValueU16(endian);
            }
            else
            {
                instance.Unk01 = 0;
                instance.Unk02 = 0;
                instance.Unk03 = 0;
            }
            return(instance);
        }
Exemplo n.º 15
0
        public void Deserialize(Stream input)
        {
            if (input.Position + 32 > input.Length)
            {
                throw new EndOfStreamException("not enough data for mesh header");
            }

            if (input.ReadValueU32(Endian.Little) != _Signature)
            {
                throw new FormatException();
            }
            var endian = Endian.Little;

            this.MajorVersion = input.ReadValueU16(endian);
            if (this.MajorVersion != 52)
            {
                throw new FormatException();
            }

            this.MinorVersion = input.ReadValueU16(endian);
            this.Unknown08    = input.ReadValueU32(endian);

            this.Root = (Chunks.RootChunk)DeserializeBlock(null, this, input, endian);

            this.ReadMetadata(input, endian);
        }
Exemplo n.º 16
0
            internal static RawEntry Read(Stream input, Endian endian)
            {
                RawEntry instance;

                instance.NameHash          = input.ReadValueU32(endian);
                instance.Type              = input.ReadValueU32(endian);
                instance.DirectoryNameHash = input.ReadValueU32(endian);
                instance.Unknown0C         = input.ReadValueU8();
                var entryCount = input.ReadValueU8();
                var entrySize  = input.ReadValueU16(endian);

                instance.Height      = input.ReadValueU16(endian);
                instance.Width       = input.ReadValueU16(endian);
                instance.MipMapCount = input.ReadValueU8();
                instance.Format      = input.ReadValueU8();
                instance.Unknown16   = input.ReadValueU8();
                instance.Unknown17   = input.ReadValueU8();

                if (entrySize != 24)
                {
                    throw new FormatException();
                }

                var entries = new RawMipMap[entryCount];

                for (int i = 0; i < entryCount; i++)
                {
                    entries[i] = RawMipMap.Read(input, endian);
                }

                instance.MipMaps = entries;
                return(instance);
            }
Exemplo n.º 17
0
        public void Deserialize(Stream input)
        {
            var magic = input.ReadValueU32(Endian.Little);

            if (magic != 0x434F4E44 && // COND
                magic.Swap() != 0x434F4E44)
            {
                throw new FormatException();
            }
            var endian = magic == 0x434F4E44 ? Endian.Little : Endian.Big;

            var version = input.ReadValueU32(endian);

            if (version != 1)
            {
                throw new FormatException();
            }
            this.Version = version;

            var unknown08 = input.ReadValueU16(endian);
            var count     = input.ReadValueU16(endian);

            var ids     = new int[count];
            var offsets = new uint[count];

            for (ushort i = 0; i < count; i++)
            {
                ids[i]     = input.ReadValueS32(endian);
                offsets[i] = input.ReadValueU32(endian);
            }

            for (ushort i = 0; i < count; i++)
            {
                var id     = ids[i];
                var offset = offsets[i];

                input.Seek(offset, SeekOrigin.Begin);

                var flags = input.ReadValueU8();

                var valueType = (Conditionals.ValueType)((flags & 0x0F) >> 0);
                var opType    = (Conditionals.OpType)((flags & 0xF0) >> 4);

                if (valueType == Conditionals.ValueType.Bool)
                {
                    switch (opType)
                    {
                    default:
                    {
                        throw new NotSupportedException();
                    }
                    }
                }
            }

            //throw new NotImplementedException();

            this.Endian = endian;
        }
Exemplo n.º 18
0
 public void Deserialize(Stream input)
 {
     this.Hash        = input.ReadValueU32();
     this.ValueIndex  = input.ReadValueU16();
     this.FirstChild  = input.ReadValueU16();
     this.NextSibling = input.ReadValueU16();
     this.ChildCount  = input.ReadValueU16();
 }
Exemplo n.º 19
0
        public static InstanceEntry Read(Stream input, Endian endian)
        {
            InstanceEntry instance;

            instance.TypeIndex = input.ReadValueU16(endian);
            instance.Count     = input.ReadValueU16(endian);
            return(instance);
        }
Exemplo n.º 20
0
        public static FileHeader Read2(Stream input, Endian endian)
        {
            FileHeader instance;

            instance.DataBlockOffset = input.ReadValueU16(endian);
            instance.DataSize        = input.ReadValueU16(endian);
            return(instance);
        }
Exemplo n.º 21
0
        public static InstanceEntry Read(Stream input, Endian endian)
        {
            InstanceEntry instance;

            instance.Unknown0            = input.ReadValueU16(endian);
            instance.TypeDefinitionIndex = input.ReadValueU16(endian);
            return(instance);
        }
Exemplo n.º 22
0
        public void Deserialize(Stream input)
        {
            const uint signature = 0x81000012;

            var unknown0000 = input.ReadValueU32(Endian.Little);

            if (unknown0000 != signature && unknown0000.Swap() != signature)
            {
                throw new FormatException();
            }
            var endian = unknown0000 == signature ? Endian.Little : Endian.Big;

            var unknown0004      = input.ReadValueU32(endian);
            var unknown0008      = input.ReadValueU32(endian);
            var unknown000C      = input.ReadValueU32(endian);
            var unknown0010      = input.ReadValueU32(endian);
            var dataSize         = input.ReadValueU32(endian);
            var battlefield      = input.ReadValueU16(endian);
            var unknown001A      = input.ReadValueU16(endian);
            var rankLimitEnabled = input.ReadValueB8();
            var unknown001D      = input.ReadValueU8();
            var mapNameId        = input.ReadValueU16(endian);
            var unknown0020      = input.ReadValueU32(endian);
            var unknown0024      = input.ReadValueU32(endian);

            if (unknown0004 != 0 ||
                unknown0008 != 0x14EF9 ||
                unknown000C != 0 ||
                unknown0010 != 0x80 ||
                dataSize != 11472 ||
                unknown001A != 0 ||
                unknown001D != 0 ||
                unknown0020 != 0)
            {
                throw new FormatException();
            }

            if (unknown0024 != unknown0000)
            {
                throw new FormatException();
            }

            var party = Party.Read(input, endian);

            var unknown2CE8 = input.ReadValueU32(endian);
            var unknown2CEC = input.ReadValueU32(endian);

            if (unknown2CE8 != 0xFFFF || unknown2CEC != 0)
            {
                throw new FormatException();
            }

            this.Endian           = endian;
            this.BattlefieldId    = battlefield;
            this.RankLimitEnabled = rankLimitEnabled;
            this.MapNameId        = mapNameId;
            this.Party            = party;
        }
Exemplo n.º 23
0
        public void Deserialize(Stream input)
        {
            var magic = input.ReadValueU32(Endian.Little);

            if (magic != Signature && magic.Swap() != Signature)
            {
                throw new FormatException();
            }
            var endian = magic == Signature ? Endian.Little : Endian.Big;

            var majorVersion = input.ReadValueU16(endian);
            var minorVersion = input.ReadValueU16(endian);

            if (majorVersion != 2 || minorVersion != 1)
            {
                throw new FormatException();
            }

            var alignment = input.ReadValueU32(endian);
            var unknown0C = input.ReadValueU32(endian);
            var unknown10 = input.ReadValueU32(endian);
            var unknown14 = input.ReadValueU32(endian);

            if (alignment != 0x1000 || unknown0C != 0)
            {
                throw new FormatException();
            }

            var unknownCount = input.ReadValueU32(endian);
            var unknowns     = new KeyValuePair <uint, uint> [unknownCount];

            for (uint i = 0; i < unknownCount; i++)
            {
                var unknown00 = input.ReadValueU32(endian);
                var unknown04 = input.ReadValueU32(endian);
                unknowns[i] = new KeyValuePair <uint, uint>(unknown00, unknown04);
            }

            var entries = new List <EntryInfo>();

            while (input.Position + 20 <= input.Length)
            {
                RawEntryInfo entryInfo;
                entryInfo.NameHash         = input.ReadValueU32(endian);
                entryInfo.Offset           = input.ReadValueU32(endian);
                entryInfo.CompressedSize   = input.ReadValueU32(endian);
                entryInfo.UncompressedSize = input.ReadValueU32(endian);
                entryInfo.Unknown          = input.ReadValueU32(endian);
                entries.Add(new EntryInfo(entryInfo));
            }

            this._Endian    = endian;
            this._Alignment = alignment;
            this._Unknowns.Clear();
            this._Unknowns.AddRange(unknowns);
            this._Entries.Clear();
            this._Entries.AddRange(entries);
        }
Exemplo n.º 24
0
        public static NameHeader Read(Stream input, Endian endian)
        {
            NameHeader instance;

            instance.NameHash    = input.ReadValueU32(endian);
            instance.DirectoryId = input.ReadValueU16(endian);
            instance.FileId      = input.ReadValueU16(endian);
            return(instance);
        }
 public override void Deserialize(Stream input)
 {
     this.LongName  = input.ReadStringAlignedU8();
     this.ShortName = input.ReadStringAlignedU8();
     this.TypeName  = input.ReadStringAlignedU8();
     this.Unknown4  = input.ReadValueU16();
     this.Unknown5  = input.ReadValueU16();
     this.Unknown6  = input.ReadValueU32();
 }
Exemplo n.º 26
0
        public static UnitPoints Read(Stream input, Endian endian)
        {
            UnitPoints instance;

            instance.Health   = input.ReadValueU16(endian);
            instance.Magic    = input.ReadValueU16(endian);
            instance.Tactical = input.ReadValueU16(endian);
            return(instance);
        }
Exemplo n.º 27
0
            public static RawNode Read(Stream input, Endian endian)
            {
                var nameHash      = input.ReadValueU32(endian);
                var dataOffset    = input.ReadValueU32(endian);
                var propertyCount = input.ReadValueU16(endian);
                var instanceCount = input.ReadValueU16(endian);

                return(new RawNode(nameHash, dataOffset, propertyCount, instanceCount));
            }
Exemplo n.º 28
0
 public void Deserialize(Stream input)
 {
     this.Id             = input.ReadValueS16();
     this.Unknown2       = input.ReadValueU16();
     this.Unknown4       = input.ReadValueU16();
     this.Unknown6       = input.ReadValueU16();
     this.Unknown8       = input.ReadValueS32();
     this.VisibilityFlag = input.ReadValueU32();
 }
Exemplo n.º 29
0
        public void Deserialize(Stream input)
        {
            var magic = input.ReadValueU32(Endian.Little);
            if (magic != 0x434F4E44 && // COND
                magic.Swap() != 0x434F4E44)
            {
                throw new FormatException();
            }
            var endian = magic == 0x434F4E44 ? Endian.Little : Endian.Big;

            var version = input.ReadValueU32(endian);
            if (version != 1)
            {
                throw new FormatException();
            }
            this.Version = version;

            var unknown08 = input.ReadValueU16(endian);
            var count = input.ReadValueU16(endian);

            var ids = new int[count];
            var offsets = new uint[count];
            for (ushort i = 0; i < count; i++)
            {
                ids[i] = input.ReadValueS32(endian);
                offsets[i] = input.ReadValueU32(endian);
            }

            for (ushort i = 0; i < count; i++)
            {
                var id = ids[i];
                var offset = offsets[i];

                input.Seek(offset, SeekOrigin.Begin);

                var flags = input.ReadValueU8();

                var valueType = (Conditionals.ValueType)((flags & 0x0F) >> 0);
                var opType = (Conditionals.OpType)((flags & 0xF0) >> 4);

                if (valueType == Conditionals.ValueType.Bool)
                {
                    switch (opType)
                    {
                        default:
                        {
                            throw new NotSupportedException();
                        }
                    }
                }
            }

            //throw new NotImplementedException();

            this.Endian = endian;
        }
Exemplo n.º 30
0
        public static UnitAssignedSkill Read(Stream input, Endian endian)
        {
            UnitAssignedSkill instance;

            instance.Id         = input.ReadValueU16(endian);
            instance.Rank       = input.ReadValueU8();
            instance.Unknown    = input.ReadValueU8();
            instance.Experience = input.ReadValueU16(endian);
            return(instance);
        }
Exemplo n.º 31
0
 public void Read(Stream input, Endian endian = Endian.Little)
 {
     _roadGraphEdgeTypeAndLink = input.ReadValueU16(endian);
     if (endian == Endian.Big)
     {
         _roadGraphEdgeTypeAndLink =
             (ushort)(((_roadGraphEdgeTypeAndLink & 0x8000) >> 15) | ((_roadGraphEdgeTypeAndLink & 0x7FFF) << 1));
     }
     Cost = input.ReadValueU16(endian);
 }
Exemplo n.º 32
0
        public static object Deserialize(Stream input, FieldType type, bool littleEndian)
        {
            switch (type)
            {
                case FieldType.UInt8: return input.ReadValueU8();
                case FieldType.Int8: return input.ReadValueS8();
                case FieldType.UInt16: return input.ReadValueU16(littleEndian);
                case FieldType.Int16: return input.ReadValueS16(littleEndian);
                case FieldType.UInt32: return input.ReadValueU32(littleEndian);
                case FieldType.Int32: return input.ReadValueS32(littleEndian);
                case FieldType.UInt64: return input.ReadValueU64(littleEndian);
                case FieldType.Int64: return input.ReadValueS64(littleEndian);
                case FieldType.Single: return input.ReadValueF32(littleEndian);
                case FieldType.Double: return input.ReadValueF64(littleEndian);
                case FieldType.Vector3:
                {
                    var value = new Builtins.Vector3();
                    value.Deserialize(input, littleEndian);
                    return value;
                }
                case FieldType.Vector4:
                {
                    var value = new Builtins.Vector4();
                    value.Deserialize(input, littleEndian);
                    return value;
                }
                case FieldType.Quaternion:
                {
                    var value = new Builtins.Quaternion();
                    value.Deserialize(input, littleEndian);
                    return value;
                }
                case FieldType.String:
                {
                    throw new NotSupportedException("cannot deserialize strings via Builtin");
                }
                case FieldType.Color:
                {
                    var value = new Builtins.Color();
                    value.Deserialize(input, littleEndian);
                    return value;
                }
                case FieldType.Matrix4x4:
                {
                    var value = new Builtins.Matrix4x4();
                    value.Deserialize(input, littleEndian);
                    return value;
                }
            }

            throw new NotSupportedException("unsupported builtin type");
        }
Exemplo n.º 33
0
        public void Deserialize(Stream input, Endian endianness)
        {
            this.DataSize = input.ReadValueU32(endianness);

            var type = input.ReadValueU8();
            if (ValidSectionTypes.ContainsKey(type) == false)
            {
                throw new FormatException("unknown section type");
            }
            this.Type = (SectionType)type;

            this.Unknown05 = input.ReadValueU8();
            this.Unknown06 = input.ReadValueU16(endianness);
            this.Flags = input.ReadValueU32(endianness);
            this.Id = input.ReadValueU32(endianness);
            this.Unknown10 = input.ReadValueU32(endianness);
        }
Exemplo n.º 34
0
        public void Deserialize(Stream input)
        {
            var magic = input.ReadValueU32(Endian.Little);
            if (magic != 0x53464152 && // SFAR
                magic.Swap() != 0x53464152)
            {
                throw new FormatException();
            }
            var endian = magic == 0x53464152 ? Endian.Little : Endian.Big;

            var version = input.ReadValueU32(endian);
            if (version != 0x00010000)
            {
                throw new FormatException();
            }

            var dataOffset = input.ReadValueU32(endian);
            var fileTableOffset = input.ReadValueU32(endian);
            var fileTableCount = input.ReadValueU32(endian);
            var blockSizeTableOffset = input.ReadValueU32(endian);
            this.MaximumBlockSize = input.ReadValueU32(endian);
            this.CompressionScheme = input
                .ReadValueEnum<SFXArchive.CompressionScheme>(endian);

            if (fileTableOffset != 0x20)
            {
                throw new FormatException();
            }

            if (this.MaximumBlockSize != 0x010000)
            {
                throw new FormatException();
            }

            /*
            if (this.CompressionScheme != SFXArchive.CompressionScheme.None &&
                this.CompressionScheme != SFXArchive.CompressionScheme.LZMA &&
                this.CompressionScheme != SFXArchive.CompressionScheme.LZX)
            {
                throw new FormatException();
            }
            */

            input.Seek(blockSizeTableOffset, SeekOrigin.Begin);

            var blockSizeTableSize = dataOffset - fileTableOffset;
            var blockSizeTableCount = blockSizeTableSize / 2;
            this.BlockSizes.Clear();
            for (uint i = 0; i < blockSizeTableCount; i++)
            {
                this.BlockSizes.Add(input.ReadValueU16(endian));
            }

            input.Seek(fileTableOffset, SeekOrigin.Begin);
            for (uint i = 0; i < fileTableCount; i++)
            {
// ReSharper disable UseObjectOrCollectionInitializer
                var entry = new SFXArchive.Entry();
// ReSharper restore UseObjectOrCollectionInitializer
                entry.NameHash = input.ReadFileNameHash();
                entry.BlockSizeIndex = input.ReadValueS32(endian);
                entry.UncompressedSize = input.ReadValueU32(endian);
                entry.UncompressedSize |= ((long)input.ReadValueU8()) << 32;
                entry.Offset = input.ReadValueU32(endian);
                entry.Offset |= ((long)input.ReadValueU8()) << 32;
                this.Entries.Add(entry);
            }
        }
Exemplo n.º 35
0
        public void Deserialize(Stream input)
        {
            var version = input.ReadValueU16();
            if (version < 2 || version > 5)
            {
                throw new FormatException("unsupported cfs version");
            }

            var header = new Sprite.Header();

            if (version >= 5)
            {
                header = input.ReadStructure<Sprite.Header>();
            }
            else if (version >= 4)
            {
                var oldHeader = input.ReadStructure<Sprite.OldHeader4>();
                header.FrameCount = oldHeader.FrameCount;
                header.AnimationTime = oldHeader.AnimationTime;
                header.Width = oldHeader.Width;
                header.Height = oldHeader.Height;
                header.RowCount = oldHeader.RowCount;
                header.ColumnCount = oldHeader.ColumnCount;
                header.ShadowCount = oldHeader.ShadowCount;
                header.LightCount = oldHeader.LightCount;
                header.UserDataSize = oldHeader.UserDataSize;
                header.CompressionFlags = (Sprite.CompressionFlags)oldHeader.CompressionFlags;
                header.MaxSolidIndex = oldHeader.MaxSolidIndex;
                header.DataSize = oldHeader.DataSize;
                header.Category = oldHeader.Category;
                header.BlitMode = oldHeader.BlitMode;
                header.RowMeaning = oldHeader.RowMeaning;
                header.YSortAdjust = oldHeader.YSortAdjust;
                header.SortTransform = oldHeader.SortTransform;
                header.UserPaletteStart = oldHeader.UserPaletteStart;
                header.UserPalette = oldHeader.UserPalette;
                header.Description = oldHeader.Description;
            }
            else if (version >= 3)
            {
                var oldHeader = input.ReadStructure<Sprite.OldHeader3>();
                header.FrameCount = oldHeader.FrameCount;
                header.AnimationTime = oldHeader.AnimationTime;
                header.Width = oldHeader.Width;
                header.Height = oldHeader.Height;
                header.RowCount = oldHeader.RowCount;
                header.ColumnCount = oldHeader.ColumnCount;
                header.ShadowCount = oldHeader.ShadowCount;
                header.LightCount = oldHeader.LightCount;
                header.UserDataSize = oldHeader.UserDataSize;
                header.CompressionFlags = (Sprite.CompressionFlags)oldHeader.CompressionFlags;
                header.MaxSolidIndex = oldHeader.MaxSolidIndex;
                header.DataSize = oldHeader.DataSize;
                header.Category = oldHeader.Category;
                header.BlitMode = oldHeader.BlitMode;
                header.RowMeaning = oldHeader.RowMeaning;
                header.YSortAdjust = oldHeader.YSortAdjust;
                header.SortTransform = oldHeader.SortTransform;
                header.UserPaletteStart = oldHeader.UserPaletteStart;
                header.UserPalette = oldHeader.UserPalette;
            }
            else if (version >= 1)
            {
                var oldHeader = input.ReadStructure<Sprite.OldHeader2>();
                header.FrameCount = oldHeader.FrameCount;
                header.AnimationTime = oldHeader.AnimationTime;
                header.Width = oldHeader.Width;
                header.Height = oldHeader.Height;
                header.RowCount = oldHeader.RowCount;
                header.ColumnCount = oldHeader.ColumnCount;
                header.ShadowCount = oldHeader.ShadowCount;
                header.LightCount = oldHeader.LightCount;
                header.UserDataSize = oldHeader.UserDataSize;
                header.CompressionFlags = (Sprite.CompressionFlags)oldHeader.CompressionFlags;
                header.MaxSolidIndex = oldHeader.MaxSolidIndex;
                header.DataSize = oldHeader.DataSize;
            }

            if (header.LightCount != 0 &&
                header.LightCount != 32)
            {
                throw new FormatException();
            }

            if (header.ShadowCount != 0 &&
                header.ShadowCount != 8)
            {
                throw new FormatException();
            }

            this.AnimationTime = header.AnimationTime;
            this.Width = header.Width;
            this.Height = header.Height;
            this.RowCount = header.RowCount;
            this.ColumnCount = header.ColumnCount;
            this.ShadowCount = header.ShadowCount;
            this.LightCount = header.LightCount;
            this.MaxSolidIndex = header.MaxSolidIndex;
            this.CompressionFlags = header.CompressionFlags;

            for (int i = 0; i < this.Palette.Length; i++)
            {
                this.Palette[i] = input.ReadValueU32();
            }

            this.UserData = new byte[header.UserDataSize];
            if (input.Read(this.UserData, 0, this.UserData.Length) != this.UserData.Length)
            {
                throw new FormatException();
            }

            var infos = new Sprite.FrameInfo[header.FrameCount];
            for (int i = 0; i < infos.Length; i++)
            {
                infos[i] = input.ReadStructure<Sprite.FrameInfo>();
            }

            var compressionFlags = (uint)header.CompressionFlags;
            if ((compressionFlags & ~0x1FFu) != 0)
            {
                throw new FormatException("unknown compression flags");
            }

            if (header.Unknown20 != 0 &&
                header.Unknown20 != 3)
            {
                // WHAT DOES THIS VALUE MEAN AUGH
                throw new NotSupportedException();
            }

            if ((header.CompressionFlags &
                 Sprite.CompressionFlags.NoCompression) != 0)
            {
                if ((header.CompressionFlags &
                     ~(Sprite.CompressionFlags.NoPixels | Sprite.CompressionFlags.NoCompression)) != 0)
                {
                    throw new FormatException("other compression flags set with NoCompression flag");
                }
            }

            using (var data = input.ReadToMemoryStream(header.DataSize))
            {
                this.Frames = new Sprite.Frame[header.FrameCount];
                for (int i = 0; i < header.FrameCount; i++)
                {
                    var info = infos[i];
                    data.Seek(info.Offset, SeekOrigin.Begin);

                    var frame = this.Frames[i] = new Sprite.Frame();

                    frame.X = info.X;
                    frame.Y = info.Y;
                    frame.Width = Math.Abs(info.Width);
                    frame.Height = Math.Abs(info.Height);
                    frame.Pixels = new byte[frame.Width * frame.Height];

                    if ((header.CompressionFlags &
                         Sprite.CompressionFlags.NoCompression) != 0)
                    {
                        // uncompressed data
                        data.Read(frame.Pixels, 0, frame.Pixels.Length);
                    }
                    else
                    {
                        // compressed data

                        var lengths = new int[frame.Height];
                        var max = 0;
                        for (int y = 0; y < frame.Height; y++)
                        {
                            int length = data.ReadValueU8();
                            if (length == 0xFF)
                            {
                                length = data.ReadValueU16();
                            }
                            lengths[y] = length;
                            max = Math.Max(max, length);
                        }

                        var scanline = new byte[max];
                        for (int y = 0, offset = 0; y < frame.Height; y++, offset = y * frame.Width)
                        {
                            var length = lengths[y];
                            if (data.Read(scanline, 0, length) != length)
                            {
                                throw new FormatException();
                            }

                            for (int x = 0; x < length;)
                            {
                                offset += (scanline[x] >> 4) & 0xF; // transparent
                                var literalCount = scanline[x] & 0xF;
                                if (literalCount > 0)
                                {
                                    Array.Copy(scanline, x + 1, frame.Pixels, offset, literalCount);
                                }
                                offset += literalCount;
                                x += 1 + literalCount;
                            }
                        }
                    }

                    // flip horizontal
                    if (info.Width < 0)
                    {
                        for (int y = 0, offset = 0; y < frame.Height; y++, offset += frame.Width)
                        {
                            Array.Reverse(frame.Pixels, offset, frame.Width);
                        }
                    }

                    // flip vertical
                    if (info.Height < 0)
                    {
                        var scanline = new byte[frame.Height];

                        for (int x = 0; x < frame.Width; x++)
                        {
                            for (int y = 0, offset = x; y < frame.Height; y++, offset += frame.Width)
                            {
                                scanline[y] = frame.Pixels[offset];
                            }

                            for (int y = 0, offset = x; y < frame.Height; y++, offset += frame.Width)
                            {
                                frame.Pixels[offset] = scanline[frame.Height - 1 - y];
                            }
                        }
                    }
                }
            }
        }
        public void Deserialize(Stream input)
        {
            var magic = input.ReadValueU32(Endian.Little);
            if (magic != 0x434F4E44 && // COND
                magic.Swap() != 0x434F4E44)
            {
                throw new FormatException();
            }
            var endian = magic == 0x434F4E44 ? Endian.Little : Endian.Big;

            var version = input.ReadValueU32(endian);
            if (version != 1)
            {
                throw new FormatException();
            }
            this.Version = version;

            var unknown08 = input.ReadValueU16(endian);
            var count = input.ReadValueU16(endian);

            var ids = new int[count];
            var offsets = new uint[count];
            for (ushort i = 0; i < count; i++)
            {
                ids[i] = input.ReadValueS32(endian);
                offsets[i] = input.ReadValueU32(endian);
            }

            var sortedOffsets = offsets
                .OrderBy(o => o)
                .Distinct()
                .ToArray();

            this._Buffers.Clear();
            for (int i = 0; i < sortedOffsets.Length; i++)
            {
                var offset = sortedOffsets[i];
                if (offset == 0)
                {
                    continue;
                }

                var nextOffset = i + 1 < sortedOffsets.Length
                                     ? sortedOffsets[i + 1]
                                     : input.Length;

                input.Seek(offset, SeekOrigin.Begin);

                var length = (int)(nextOffset - offset);

                var bytes = input.ReadBytes(length);
                this._Buffers.Add(offset, bytes);
            }

            this._Conditionals.Clear();
            for (int i = 0; i < count; i++)
            {
                this._Conditionals.Add(ids[i], offsets[i]);
            }

            this.Endian = endian;
        }
        public void Deserialize(Stream input)
        {
            this.DosHeader = input.ReadStructure<Image.DosHeader>();
            if (this.DosHeader.Magic != 0x5A4D) // MZ
            {
                throw new FormatException("dos header has bad magic");
            }

            input.Seek(this.DosHeader.NewExeOffset, SeekOrigin.Begin);
            this.NTHeaders32 = input.ReadStructure<Image.NTHeaders32>();
            if (this.NTHeaders32.Signature != 0x4550 || this.NTHeaders32.FileHeader.SizeOfOptionalHeader != 0xE0) // PE
            {
                throw new FormatException("nt header has bad signature");
            }
            else if (this.NTHeaders32.OptionalHeader.Magic != 0x10B) // IMAGE_NT_OPTIONAL_HDR32_MAGIC
            {
                throw new FormatException("optional header has bad magic");
            }

            this.Directories = new List<Image.DataDirectory>();
            for (int i = 0; i < this.NTHeaders32.OptionalHeader.NumberOfRvaAndSizes; i++)
            {
                this.Directories.Add(input.ReadStructure<Image.DataDirectory>());
            }

            this.Sections = new List<Image.SectionHeader>();
            for (int i = 0; i < this.NTHeaders32.FileHeader.NumberOfSections; i++)
            {
                this.Sections.Add(input.ReadStructure<Image.SectionHeader>());
            }

            this.Exports = new Dictionary<UInt32, UInt32>();
            this.ExportNames = new Dictionary<string, UInt32>();

            if (
                this.Directories.Count >= 1 &&
                this.Directories[0].VirtualAddress != 0 &&
                this.Directories[0].Size != 0)
            {
                var fileOffset = this.GetFileOffset(this.Directories[0].VirtualAddress, true);

                input.Seek(fileOffset, SeekOrigin.Begin);
                Image.ExportDirectory exportDirectory = input.ReadStructure<Image.ExportDirectory>();

                if (exportDirectory.NumberOfNames > 0)
                {
                    var nameOffsets = new UInt32[exportDirectory.NumberOfNames];
                    var names = new string[exportDirectory.NumberOfNames];
                    var ordinals = new UInt16[exportDirectory.NumberOfNames];

                    input.Seek(this.GetFileOffset(exportDirectory.AddressOfNames, true), SeekOrigin.Begin);
                    for (uint i = 0; i < exportDirectory.NumberOfNames; i++)
                    {
                        nameOffsets[i] = input.ReadValueU32();
                    }

                    input.Seek(this.GetFileOffset(exportDirectory.AddressOfNameOrdinals, true), SeekOrigin.Begin);
                    for (uint i = 0; i < exportDirectory.NumberOfNames; i++)
                    {
                        ordinals[i] = input.ReadValueU16();
                    }

                    for (uint i = 0; i < exportDirectory.NumberOfNames; i++)
                    {
                        input.Seek(this.GetFileOffset(nameOffsets[i], true), SeekOrigin.Begin);
                        var name = input.ReadStringZ(Encoding.ASCII);
                        this.ExportNames.Add(name, exportDirectory.Base + ordinals[i]);
                    }
                }

                if (exportDirectory.NumberOfFunctions > 0)
                {
                    input.Seek(this.GetFileOffset(exportDirectory.AddressOfFunctions, true), SeekOrigin.Begin);

                    for (uint i = 0; i < exportDirectory.NumberOfFunctions; i++)
                    {
                        var address = input.ReadValueU32();
                        if (address == 0)
                        {
                            continue;
                        }

                        this.Exports.Add(exportDirectory.Base + i, address);
                    }
                }
            }
        }
Exemplo n.º 38
0
        public void Deserialize(Stream input)
        {
            if (input.ReadValueU32() != 0x39444350)
            {
                throw new FormatException();
            }

            this.Format = input.ReadValueEnum<PCD9.Format>();
            var dataSize = input.ReadValueU32();
            this.Unknown0C = input.ReadValueU32();
            this.Width = input.ReadValueU16();
            this.Height = input.ReadValueU16();
            this.BPP = input.ReadValueU8();
            var mipMapCount = 1 + input.ReadValueU8();
            this.Unknown16 = input.ReadValueU16();
            if ((this.Unknown16 & 0x8000) != 0)
            {
                throw new NotSupportedException();
                this.unknownFlag = true;
            }

            this.Mipmaps.Clear();
            using (var data = input.ReadToMemoryStream(dataSize))
            {
                var mipWidth = this.Width;
                var mipHeight = this.Height;

                for (int i = 0; i < mipMapCount; i++)
                {
                    if (mipWidth == 0)
                    {
                        mipWidth = 1;
                    }

                    if (mipHeight == 0)
                    {
                        mipHeight = 1;
                    }

                    int size;
                    switch (this.Format)
                    {
                        case PCD9.Format.A8R8G8B8:
                        {
                            size = mipWidth * mipHeight * 4;
                            break;
                        }

                        case PCD9.Format.DXT1:
                        case PCD9.Format.DXT3:
                        case PCD9.Format.DXT5:
                        {
                            int blockCount = ((mipWidth + 3) / 4) * ((mipHeight + 3) / 4);
                            int blockSize = this.Format == PCD9.Format.DXT1 ? 8 : 16;
                            size = blockCount * blockSize;
                            break;
                        }

                        default:
                        {
                            throw new NotSupportedException();
                        }
                    }

                    var buffer = new byte[size];
                    if (data.Read(buffer, 0, buffer.Length) != buffer.Length)
                    {
                        throw new EndOfStreamException();
                    }

                    this.Mipmaps.Add(new PCD9.Mipmap()
                        {
                            Width = mipWidth,
                            Height = mipHeight,
                            Data = buffer,
                        });

                    mipWidth >>= 1;
                    mipHeight >>= 1;
                }

                if (data.Position != data.Length)
                {
                    throw new InvalidOperationException();
                }
            }
        }
Exemplo n.º 39
0
        private static Stream ReadPackage(Stream input)
        {
            var magic = input.ReadValueU32(Endian.Little);
            if (magic != 0x9E2A83C1 &&
                magic.Swap() != 0x9E2A83C1)
            {
                throw new FormatException("not a package");
            }
            var endian = magic == 0x9E2A83C1
                             ? Endian.Little
                             : Endian.Big;

            var versionLo = input.ReadValueU16(endian);
            var versionHi = input.ReadValueU16(endian);

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

            input.Seek(4, SeekOrigin.Current);

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

            /*var packageFlagsOffset = input.Position;*/
            var packageFlags = input.ReadValueU32(endian);

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

            input.Seek(24, SeekOrigin.Current);

            if ((packageFlags & 0x02000000) == 0)
            {
                return input;
            }

            input.Seek(36, SeekOrigin.Current);

            var generationsCount = input.ReadValueU32(endian);
            input.Seek(generationsCount * 12, SeekOrigin.Current);

            input.Seek(20, SeekOrigin.Current);

            var blockCount = input.ReadValueU32(endian);

            var blockStream = new BlockStream(input);
            for (int i = 0; i < blockCount; i++)
            {
                var uncompressedOffset = input.ReadValueU32(endian);
                var uncompressedSize = input.ReadValueU32(endian);
                var compressedOffset = input.ReadValueU32(endian);
                var compressedSize = input.ReadValueU32(endian);
                blockStream.AddBlock(
                    uncompressedOffset,
                    uncompressedSize,
                    compressedOffset,
                    compressedSize);
            }

            return blockStream;
        }
Exemplo n.º 40
0
        public void Deserialize(Stream input)
        {
            var magic = input.ReadValueU32(Endian.Little);
            if (magic != 0x53464152 && // SFAR
                magic.Swap() != 0x53464152)
            {
                throw new FormatException();
            }
            var endian = magic == 0x53464152 ? Endian.Little : Endian.Big;

            var version = input.ReadValueU32(endian);
            if (version != 0x00010000)
            {
                throw new FormatException();
            }

            var dataOffset = input.ReadValueU32(endian);
            bool firstDataOffset = true;
            uint minDataOffset = dataOffset;
            //Console.WriteLine("Data Offset: {0:X8}",dataOffset);
            var fileTableOffset = input.ReadValueU32(endian);
            //Console.WriteLine("File Table Offset: {0:X8}",fileTableOffset);
            var fileTableCount = input.ReadValueU32(endian);
            //Console.WriteLine("File Table Count: {0:X8}",fileTableCount);
            var blockSizeTableOffset = input.ReadValueU32(endian);
            //Console.WriteLine("Block Size Table Offset: {0:X8}",blockSizeTableOffset);
            this.MaximumBlockSize = input.ReadValueU32(endian);
            this.CompressionScheme = input
                .ReadValueEnum<SFXArchive.CompressionScheme>(endian);

            if (fileTableOffset != 0x20)
            {
                throw new FormatException();
            }

            if (this.MaximumBlockSize != 0x010000)
            {
                throw new FormatException();
            }

            /*
            if (this.CompressionScheme != SFXArchive.CompressionScheme.None &&
                this.CompressionScheme != SFXArchive.CompressionScheme.LZMA &&
                this.CompressionScheme != SFXArchive.CompressionScheme.LZX)
            {
                throw new FormatException();
            }
            */
            input.Seek(fileTableOffset, SeekOrigin.Begin);
            for (uint i = 0; i < fileTableCount; i++)
            {
            // ReSharper disable UseObjectOrCollectionInitializer
                var entry = new SFXArchive.Entry();
                entry.entryOffset = input.Position;
            // ReSharper restore UseObjectOrCollectionInitializer
                entry.nameHash = input.ReadFileNameHash();
                //Console.WriteLine("FileNameHash: {0}",entry.NameHash.ToString());
                entry.blockSizeIndex = input.ReadValueS32(endian);
                //Console.WriteLine("Begin position: {0:X8}",input.Position);
                entry.uncompressedSize = input.ReadValueU32(endian);
                entry.uncompressedSize |= ((long)input.ReadValueU8()) << 32;
                //Console.WriteLine("  End position: {0:X8}",input.Position);
                entry.dataOffset = input.ReadValueU32(endian);
                entry.dataOffset |= ((long)input.ReadValueU8()) << 32;
                if(firstDataOffset)
                {
                    minDataOffset = (uint)entry.dataOffset;
                    firstDataOffset = false;
                }
                else
                {
                    if(minDataOffset > entry.dataOffset)
                        minDataOffset = (uint)entry.dataOffset;
                }
                //if(entry.NameHash.Equals (fileNameListNameHash))Console.WriteLine("Offset: {0:X10}, UncSize {1:X10}",entry.Offset,entry.UncompressedSize);
                this.Entries.Add(entry);
            }
            if(minDataOffset > dataOffset)
                dataOffset = minDataOffset;

            input.Seek(blockSizeTableOffset, SeekOrigin.Begin);

            var blockSizeTableSize = dataOffset - blockSizeTableOffset;
            var blockSizeTableCount = blockSizeTableSize / 2;
            //ushort aux;
            //Console.WriteLine("dataOffset: {0:X8}\nfileTableOffset: {1:X8}\nBlockSizeTableSize: {2:X8}\nblockSizeTableOffset: {3:X8}", dataOffset,fileTableOffset,blockSizeTableSize,blockSizeTableOffset);
            this.BlockSizes.Clear();
            //Console.WriteLine("initial position: {0:X8}",input.Position);
            //Console.WriteLine("blockSizeTableCount: {0}",blockSizeTableCount);
            for (uint i = 0; i < blockSizeTableCount; i++)
            {
                this.BlockSizes.Add(input.ReadValueU16(endian));
            }
            //Console.WriteLine("final position: {0:X8}",input.Position);
            //Console.WriteLine("number of repetitions: {0}",blockSizeTableCount);
            //var fileNameListNameHash = new FileNameHash(
            //        new byte[] { 0xB5, 0x50, 0x19, 0xCB, 0xF9, 0xD3, 0xDA, 0x65, 0xD5, 0x5B, 0x32, 0x1C, 0x00, 0x19, 0x69, 0x7C, });
        }
        public void Deserialize(Stream input)
        {
            if (input.ReadValueU32() != 0x55AA1234)
            {
                input.Seek(-4, SeekOrigin.Current);
            }
            else
            {
                uint version = input.ReadValueU32();
                uint indexSize = input.ReadValueU32();

                if (version != 1)
                {
                    throw new FormatException("unexpected version " + version.ToString());
                }
            }

            List<PackageEntry> entries = new List<PackageEntry>();

            // Types
            while (true)
            {
                string typeName = input.ReadStringASCIIZ();
                if (typeName == "")
                {
                    break;
                }

                // Directories
                while (true)
                {
                    string directoryName = input.ReadStringASCIIZ();
                    if (directoryName == "")
                    {
                        break;
                    }

                    // Files
                    while (true)
                    {
                        string fileName = input.ReadStringASCIIZ();
                        if (fileName == "")
                        {
                            break;
                        }

                        PackageEntry entry = new PackageEntry();
                        entry.FileName = fileName;
                        entry.DirectoryName = directoryName.Replace("/", "\\");
                        entry.TypeName = typeName;
                        entry.CRC32 = input.ReadValueU32();
                        entry.SmallData = new byte[input.ReadValueU16()];
                        entry.ArchiveIndex = input.ReadValueU16();
                        entry.Offset = input.ReadValueU32();
                        entry.Size = input.ReadValueU32();
                        
                        UInt16 terminator = input.ReadValueU16();
                        if (terminator != 0xFFFF)
                        {
                            throw new FormatException("invalid terminator");
                        }

                        if (entry.SmallData.Length > 0)
                        {
                            input.Read(entry.SmallData, 0, entry.SmallData.Length);
                        }

                        entries.Add(entry);
                    }
                }
            }

            this.Entries = entries;
        }
Exemplo n.º 42
0
        /// <summary>
        ///     compress an entire ME3 pcc into a byte array.
        /// </summary>
        /// <param name="uncompressedPcc">uncompressed pcc stream.</param>
        /// <returns>a compressed array of bytes.</returns>
        public static Stream Compress(Stream uncompressedPcc)
        {
            uncompressedPcc.Position = 0;

            var magic = uncompressedPcc.ReadValueU32(Endian.Little);
            if (magic != 0x9E2A83C1 &&
                magic.Swap() != 0x9E2A83C1)
            {
                throw new FormatException("not a pcc package");
            }
            var endian = magic == 0x9E2A83C1 ?
                Endian.Little : Endian.Big;
            var encoding = endian == Endian.Little ?
                Encoding.Unicode : Encoding.BigEndianUnicode;

            var versionLo = uncompressedPcc.ReadValueU16(endian);
            var versionHi = uncompressedPcc.ReadValueU16(endian);

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

            uncompressedPcc.Seek(4, SeekOrigin.Current);

            var folderNameLength = uncompressedPcc.ReadValueS32(endian);
            var folderNameByteLength =
                folderNameLength >= 0 ? folderNameLength : (-folderNameLength * 2);
            uncompressedPcc.Seek(folderNameByteLength, SeekOrigin.Current);

            var packageFlagsOffset = uncompressedPcc.Position;
            var packageFlags = uncompressedPcc.ReadValueU32(endian);

            if ((packageFlags & 8) != 0)
            {
                uncompressedPcc.Seek(4, SeekOrigin.Current);
            }

            var nameCount = uncompressedPcc.ReadValueU32(endian);
            var namesOffset = uncompressedPcc.ReadValueU32(endian);
            var exportCount = uncompressedPcc.ReadValueU32(endian);
            var exportInfosOffset = uncompressedPcc.ReadValueU32(endian);
            SortedDictionary<uint, uint> exportDataOffsets = new SortedDictionary<uint, uint>();

            Stream data;
            if ((packageFlags & 0x02000000) == 0)
            {
                data = uncompressedPcc;
            }
            else
            {
                throw new FormatException("pcc data is compressed");
            }

            // get info about export data, sizes and offsets
            data.Seek(exportInfosOffset, SeekOrigin.Begin);
            for (uint i = 0; i < exportCount; i++)
            {
                var classIndex = data.ReadValueS32(endian);
                data.Seek(4, SeekOrigin.Current);
                var outerIndex = data.ReadValueS32(endian);
                var objectNameIndex = data.ReadValueS32(endian);
                data.Seek(16, SeekOrigin.Current);

                uint exportDataSize = data.ReadValueU32(endian);
                uint exportDataOffset = data.ReadValueU32(endian);
                exportDataOffsets.Add(exportDataOffset, exportDataSize);

                data.Seek(4, SeekOrigin.Current);
                var count = data.ReadValueU32(endian);
                data.Seek(count * 4, SeekOrigin.Current);
                data.Seek(20, SeekOrigin.Current);
            }

            const uint maxBlockSize = 0x100000;
            Stream outputStream = new MemoryStream();
            // copying pcc header
            byte[] buffer = new byte[130];
            uncompressedPcc.Seek(0, SeekOrigin.Begin);
            uncompressedPcc.Read(buffer, 0, 130);
            outputStream.Write(buffer, 0, buffer.Length);

            //add compressed pcc flag
            uncompressedPcc.Seek(12, SeekOrigin.Begin);
            folderNameLength = uncompressedPcc.ReadValueS32();
            folderNameByteLength =
                folderNameLength >= 0 ? folderNameLength : (-folderNameLength * 2);
            uncompressedPcc.Seek(folderNameByteLength, SeekOrigin.Current);
            outputStream.Seek(uncompressedPcc.Position, SeekOrigin.Begin);

            packageFlags = uncompressedPcc.ReadValueU32();
            packageFlags |= 0x02000000; // add compression flag
            outputStream.WriteValueU32(packageFlags);

            outputStream.Seek(buffer.Length, SeekOrigin.Begin);

            long outOffsetData;
            long outOffsetBlockInfo;
            long inOffsetData = namesOffset;
            List<int> blockSizes = new List<int>();
            int countSize = (int)(exportDataOffsets.Min(obj => obj.Key) - namesOffset);

            //count the number of blocks and relative sizes
            uint lastOffset = exportDataOffsets.Min(obj => obj.Key);
            foreach (KeyValuePair<uint, uint> exportInfo in exportDataOffsets)
            {
                // part that adds empty spaces (leaved when editing export data and moved to the end of pcc) into the count
                if (exportInfo.Key != lastOffset)
                {
                    int emptySpace = (int)(exportInfo.Key - lastOffset);
                    if (countSize + emptySpace > maxBlockSize)
                    {
                        blockSizes.Add(countSize);
                        countSize = 0;
                    }
                    else
                        countSize += emptySpace;
                }

                // adds export data into the count
                if (countSize + exportInfo.Value > maxBlockSize)
                {
                    blockSizes.Add(countSize);
                    countSize = (int)exportInfo.Value;
                }
                else
                {
                    countSize += (int)exportInfo.Value;
                }

                lastOffset = exportInfo.Key + exportInfo.Value;
            }
            blockSizes.Add(countSize);

            outputStream.WriteValueS32(blockSizes.Count);
            outOffsetBlockInfo = outputStream.Position;
            outOffsetData = namesOffset + (blockSizes.Count * 16);

            uncompressedPcc.Seek(namesOffset, SeekOrigin.Begin);
            //divide the block in segments
            for (int i = 0; i < blockSizes.Count; i++)
            {
                int currentUncBlockSize = blockSizes[i];

                outputStream.Seek(outOffsetBlockInfo, SeekOrigin.Begin);
                outputStream.WriteValueU32((uint)uncompressedPcc.Position);
                outputStream.WriteValueS32(currentUncBlockSize);
                outputStream.WriteValueU32((uint)outOffsetData);

                byte[] inputBlock = new byte[currentUncBlockSize];
                uncompressedPcc.Read(inputBlock, 0, currentUncBlockSize);
                byte[] compressedBlock = ZBlock.Compress(inputBlock, 0, inputBlock.Length);

                outputStream.WriteValueS32(compressedBlock.Length);
                outOffsetBlockInfo = outputStream.Position;

                outputStream.Seek(outOffsetData, SeekOrigin.Begin);
                outputStream.Write(compressedBlock, 0, compressedBlock.Length);
                outOffsetData = outputStream.Position;
            }

            //copying some unknown values + extra names list
            int bufferSize = (int)namesOffset - 0x86;
            buffer = new byte[bufferSize];
            uncompressedPcc.Seek(0x86, SeekOrigin.Begin);
            uncompressedPcc.Read(buffer, 0, buffer.Length);
            outputStream.Seek(outOffsetBlockInfo, SeekOrigin.Begin);
            outputStream.Write(buffer, 0, buffer.Length);

            outputStream.Seek(0, SeekOrigin.Begin);

            return outputStream;
        }
Exemplo n.º 43
0
        /// <summary>
        ///     decompress an entire ME3 pcc file into a new stream
        /// </summary>
        /// <param name="input">pcc file passed in stream format</param>
        /// <returns>a decompressed array of bytes</returns>
        public static MemoryStream DecompressME3(Stream input)
        {
            input.Seek(0, SeekOrigin.Begin);
            var magic = input.ReadValueU32(Endian.Little);
            if (magic != 0x9E2A83C1 &&
                magic.Swap() != 0x9E2A83C1)
            {
                throw new FormatException("not a pcc file");
            }
            var endian = magic == 0x9E2A83C1 ? Endian.Little : Endian.Big;

            var versionLo = input.ReadValueU16(endian);
            var versionHi = input.ReadValueU16(endian);

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

            long headerSize = 8;

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

            var folderNameLength = input.ReadValueS32(endian);
            headerSize += 4;

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

            var packageFlagsOffset = input.Position;
            var packageFlags = input.ReadValueU32(endian);
            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.ReadValueU32(endian);
            uint nameOffset = input.ReadValueU32(endian);

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

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

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

            var blockCount = input.ReadValueU32(endian);
            int headBlockOff = (int)input.Position;
            var afterBlockTableOffset = headBlockOff + (blockCount * 16);
            var indataOffset = afterBlockTableOffset + 8;
            byte[] buff;

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

            output.WriteFromStream(input, headerSize);
            output.WriteValueU32(0, endian); // block count

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

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

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

                buff = new byte[compressedSize];
                input.Seek(compressedOffset, SeekOrigin.Begin);
                input.Read(buff, 0, buff.Length);

                tasks[i] = ZBlock.DecompressAsync(buff);
            }
            Task.WaitAll(tasks);
            for (int i = 0; i < blockCount; i++)
            {
                output.Seek(uncompressedOffsets[i], SeekOrigin.Begin);
                output.WriteBytes(tasks[i].Result);
            }

            output.Seek(packageFlagsOffset, SeekOrigin.Begin);
            output.WriteValueU32(packageFlags & ~0x02000000u, endian);
            return output;
        }
Exemplo n.º 44
0
        public void Deserialize(Stream input)
        {
            if (input.ReadValueU32() != 0x57325243) // 'W2RC' -> Witcher 2 Resource?
            {
                throw new FormatException();
            }

            this.Version = input.ReadValueU32();
            if (this.Version < 83 || this.Version > 115)
            {
                throw new FormatException();
            }

            var flags = input.ReadValueU32();

            var nameDataOffset = input.ReadValueU32();
            var nameCount = input.ReadValueU32();
            var objectDataOffset = input.ReadValueU32();
            var objectCount = input.ReadValueU32();
            var linkDataOffset = input.ReadValueU32();
            var linkCount = input.ReadValueU32();
            uint dependencyDataOffset = 0;
            uint dependencyCount = 0;

            if (this.Version >= 46)
            {
                dependencyDataOffset = input.ReadValueU32();
                dependencyCount = input.ReadValueU32();
            }

            var info = new Resource.Info();
            
            info.Names = new string[nameCount];
            if (nameCount > 0)
            {
                input.Seek(nameDataOffset, SeekOrigin.Begin);
                for (uint i = 0; i < nameCount; i++)
                {
                    info.Names[i] = input.ReadEncodedString();
                }
            }

            info.Links = new Resource.LinkInfo[linkCount];
            if (linkCount > 0)
            {
                input.Seek(linkDataOffset, SeekOrigin.Begin);

                for (uint i = 0; i < linkCount; i++)
                {
                    var link = new Resource.LinkInfo();
                    link.FileName = input.ReadEncodedStringW();
                    link.Unknown1 = input.ReadValueU16();
                    link.Unknown2 = input.ReadValueU16();
                    info.Links[i] = link;
                }
            }

            this.Dependencies.Clear();
            if (dependencyCount > 1)
            {
                input.Seek(dependencyDataOffset, SeekOrigin.Begin);

                info.Dependencies = new string[dependencyCount];
                for (uint i = 1; i < dependencyCount; i++)
                {
                    var path = input.ReadEncodedString();
                    info.Dependencies[i] = path;
                    this.Dependencies.Add(path);
                }
            }

            this.Objects = new List<Resource.ObjectInfo>();
            info.Objects = new Resource.ObjectInfo[objectCount];
            if (objectCount > 0)
            {
                input.Seek(objectDataOffset, SeekOrigin.Begin);

                var offsets = new Dictionary<Resource.ObjectInfo, ObjectLocation>();

                for (uint i = 0; i < objectCount; i++)
                {
                    var typeNameIndex = input.ReadValueS16();
                    if (typeNameIndex < 1 ||
                        typeNameIndex > info.Names.Length)
                    {
                        throw new FormatException();
                    }

                    var obj = new Resource.ObjectInfo();
                    obj.TypeName = info.Names[typeNameIndex - 1];

                    var parentIndex = input.ReadValueS32();

                    var location = new ObjectLocation();
                    location.Size = input.ReadValueU32();
                    location.Offset = input.ReadValueU32();

                    obj.Flags = input.ReadValueU32();
                    obj.Unknown5 = input.ReadValueU32();
                    obj.Link = this.Version < 102 ? null : input.ReadEncodedString();

                    if (TypeCache.Supports(obj.TypeName) == false)
                    {
                        obj.Data = new GenericObject(obj.TypeName);
                    }
                    else
                    {
                        obj.Data = TypeCache.Instantiate(obj.TypeName);
                    }

                    info.Objects[i] = obj;
                    offsets.Add(obj, location);

                    if (obj.Unknown5 != 0)
                    {
                        throw new FormatException();
                    }

                    if (parentIndex > 0)
                    {
                        var parent = info.Objects[parentIndex - 1];
                        if (parent.Children == null)
                        {
                            parent.Children = new List<Resource.ObjectInfo>();
                        }
                        parent.Children.Add(obj);
                        obj.Parent = parent;
                    }
                    else
                    {
                        obj.Parent = null;
                        this.Objects.Add(obj);
                    }
                }

                foreach (var obj in info.Objects)
                {
                    var location = offsets[obj];

                    input.Seek(location.Offset, SeekOrigin.Begin);
                    
                    var data = new byte[location.Size];
                    input.Read(data, 0, data.Length);

                    using (var reader = new Resource.ResourceReader(info, data))
                    {
                        obj.Data.Serialize(reader);

                        var bytesRemaining = reader.Length - reader.Position;
                        if (bytesRemaining > 0)
                        {
                            if (obj.Data is GenericObject)
                            {
                                byte[] undecodedData = new byte[bytesRemaining];
                                Array.Copy(data, reader.Position, undecodedData, 0, bytesRemaining);
                                ((GenericObject) obj.Data).UndecodedData = undecodedData;
                            }
                            else
                            {
                                throw new FormatException();
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 45
0
        /// <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.ReadValueU16();
            ushort versionHi = raw.ReadValueU16();
            raw.Seek(12, SeekOrigin.Begin);
            int tempNameSize = raw.ReadValueS32();
            raw.Seek(64 + tempNameSize, SeekOrigin.Begin);
            int tempGenerations = raw.ReadValueS32();
            raw.Seek(36 + tempGenerations * 12, SeekOrigin.Current);

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

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

            //DebugOutput.PrintLn("Reading chunk headers...");
            for (int i = 0; i < NumChunks; i++)
            {
                Chunk c = new Chunk();
                c.uncompressedOffset = raw.ReadValueS32();
                c.uncompressedSize = raw.ReadValueS32();
                c.compressedOffset = raw.ReadValueS32();
                c.compressedSize = raw.ReadValueS32();
                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.ReadBytes(c.compressedSize);

                ChunkHeader h = new ChunkHeader();
                h.magic = BitConverter.ToInt32(c.Compressed, 0);
                if (h.magic != -1641380927)
                    throw new FormatException("Chunk magic number incorrect");
                h.blocksize = BitConverter.ToInt32(c.Compressed, 4);
                h.compressedsize = BitConverter.ToInt32(c.Compressed, 8);
                h.uncompressedsize = BitConverter.ToInt32(c.Compressed, 12);
                //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;
                List<Block> BlockList = new List<Block>();
                //DebugOutput.PrintLn("\t\t" + count + " Read Blockheaders...");
                for (int j = 0; j < blockCount; j++)
                {
                    Block b = new Block();
                    b.compressedsize = BitConverter.ToInt32(c.Compressed, pos);
                    b.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)
                {
                    byte[] datain = new byte[b.compressedsize];
                    byte[] dataout = new byte[b.uncompressedsize];
                    for (int j = 0; j < b.compressedsize; j++)
                        datain[j] = c.Compressed[pos + j];
                    pos += b.compressedsize;

                    try
                    {
                        LZO1X.Decompress(datain, dataout);
                    }
                    catch
                    {
                        throw new Exception("LZO decompression failed!");
                    }
                    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.WriteBytes(c.Uncompressed);
            }
            
            return result;
        }
Exemplo n.º 46
0
        public void Deserialize(Stream input)
        {
            this.Version = input.ReadValueU32();
            this.EncryptionKey = 0;

            if (this.Version >= 114)
            {
                this.EncryptionKey |= (uint)(input.ReadValueU16() << 16);
            }

            var keyCount = input.ReadValueEncodedS32();
            this.Keys.Clear();
            for (int i = 0; i < keyCount; i++)
            {
                var key = input.ReadEncodedString();
                var index = input.ReadValueU32();
                this.Keys.Add(key, index);
            }

            if (this.Version >= 114)
            {
                this.EncryptionKey |= (uint)(input.ReadValueU16() << 0);
            }

            var magic = GetRealKey(this.EncryptionKey);

            uint fileStringsHash = 0;

            if (this.Version >= 200)
            {
                fileStringsHash = input.ReadValueU32();
                fileStringsHash ^= magic;
            }

            foreach (var key in this.Keys.Keys.ToArray())
            {
                this.Keys[key] ^= magic;
            }

            uint actualStringsHash = 0;
            var stringCount = input.ReadValueEncodedS32();
            for (int i = 0; i < stringCount; i++)
            {
                var index = input.ReadValueU32();
                index ^= magic;

                var buffer = input.ReadEncodedStringBuffer();

                ushort stringKey = (ushort)(magic >> 8);

                uint hash = 0;

                for (int j = 0; j < buffer.Length; j += 2)
                {
                    hash += BitConverter.ToUInt16(buffer, j);

                    if (this.Version >= 200)
                    {
                        var charKey = (ushort)(((buffer.Length / 2) + 1) * stringKey);
                        buffer[j + 0] ^= (byte)((charKey >> 0) & 0xFF);
                        buffer[j + 1] ^= (byte)((charKey >> 8) & 0xFF);
                        stringKey = stringKey.RotateLeft(1);
                    }
                    else
                    {
                        throw new NotImplementedException("string obfuscation for old strings files is untested");

                        // untested
                        buffer[j + 0] ^= (byte)((stringKey >> 0) & 0xFF);
                        buffer[j + 1] ^= (byte)((stringKey >> 8) & 0xFF);
                        stringKey++;
                    }
                }

                actualStringsHash += hash;

                if (index == 65434 &&
                    hash == 83394453)
                {
                    // hack to fix this dumb corrupted string in en0.w2strings
                    this.Texts.Add(index, Encoding.Unicode.GetString(buffer, 0, 104));
                }
                else
                {
                    this.Texts.Add(index, Encoding.Unicode.GetString(buffer));
                }
            }

            if (this.Version >= 114 && this.Version < 200)
            {
                fileStringsHash = input.ReadValueU32();
            }

            if (this.Version >= 114 && fileStringsHash != actualStringsHash)
            {
                throw new FormatException("hash for strings does not match");
            }
        }