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); }
public int Deserialize(Stream input) { _opFlags = input.ReadValueU16(); _opTargetNum = input.ReadValueU16(); _opFuncName = input.ReadValueEncodedS32(); return(8); }
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(); } }
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); } }
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); }
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; } }
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); } }
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); }
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); }
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)); }
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); }
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); }
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); }
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; }
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(); }
public static InstanceEntry Read(Stream input, Endian endian) { InstanceEntry instance; instance.TypeIndex = input.ReadValueU16(endian); instance.Count = input.ReadValueU16(endian); return(instance); }
public static FileHeader Read2(Stream input, Endian endian) { FileHeader instance; instance.DataBlockOffset = input.ReadValueU16(endian); instance.DataSize = input.ReadValueU16(endian); return(instance); }
public static InstanceEntry Read(Stream input, Endian endian) { InstanceEntry instance; instance.Unknown0 = input.ReadValueU16(endian); instance.TypeDefinitionIndex = input.ReadValueU16(endian); return(instance); }
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; }
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); }
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(); }
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); }
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)); }
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(); }
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); }
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); }
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"); }
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); }
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); } }
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); } } } }
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(); } } }
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; }
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; }
/// <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; }
/// <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; }
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(); } } } } } }
/// <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; }
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"); } }