private void ReadDataItems(Stream s) { _signature = s.ReadValueS32(Endianness); var elementCount = s.ReadValueS32(Endianness); var indexBase = 16; var stringBase = indexBase + elementCount * 0x1C; _dataList = new List <DataItem>(); var i = 0; while (i < elementCount) { s.Seek(indexBase + i * 0x1C, SeekOrigin.Begin); var item = new DataItem(); item.Index.Id = s.ReadBytes(0xC); item.Index.Id2 = s.ReadBytes(0xC); item.Index.StringOffset = s.ReadValueS32(Endianness); s.Seek(stringBase + item.Index.StringOffset, SeekOrigin.Begin); item.Data = ReadString(s); _dataList.Add(item); i++; } }
public override void Read(Stream s) { _dataList = new List <TFString>(); s.Seek(0x24, SeekOrigin.Begin); var pointer1 = s.ReadValueS32(Endianness); if (pointer1 != -1) { s.Seek(pointer1, SeekOrigin.Begin); var pointer2 = s.ReadValueS32(Endianness); s.Seek(pointer2, SeekOrigin.Begin); var str = s.ReadStringZ(Encoding); if (!string.IsNullOrEmpty(str.TrimEnd('\0'))) { str = Yakuza0Project.ReadingReplacements(str); } var item = new TFString { FileId = Id, Offset = pointer2, Section = pointer1.ToString("X8"), Original = str, Translation = str, Visible = !string.IsNullOrEmpty(str.TrimEnd('\0')) }; _dataList.Add(item); } }
void IChunk.Deserialize(IChunk parent, Stream input, Endian endian) { var count = input.ReadValueU32(endian); this.Items.Clear(); for (uint i = 0; i < count; i++) { var node = new Node(); node.NameHash = input.ReadValueU32(endian); node.NextSiblingIndex = input.ReadValueS32(endian); node.FirstChildIndex = input.ReadValueS32(endian); node.PreviousSiblingIndex = input.ReadValueS32(endian); node.Unknown10 = input.ReadValueF32(endian); node.Unknown14 = input.ReadValueF32(endian); node.Unknown18 = input.ReadValueF32(endian); node.Unknown1C = input.ReadValueF32(endian); node.Unknown20 = input.ReadValueF32(endian); node.Unknown24 = input.ReadValueF32(endian); node.Unknown28 = input.ReadValueF32(endian); node.Unknown2C = input.ReadValueF32(endian); node.Unknown30 = input.ReadValueF32(endian); node.Unknown34 = input.ReadValueF32(endian); node.O2BMIndex = input.ReadValueS32(endian); node.Unknown3C = input.ReadValueF32(endian); node.Unknown40 = input.ReadValueF32(endian); var length = input.ReadValueU32(endian); node.Name = input.ReadString(length); input.Seek(1, SeekOrigin.Current); // skip null this.Items.Add(node); } }
public void Read(Stream input, long debugOffset) { this.DebugOffset = debugOffset + input.Position; this.Version = input.ReadValueS16(); if (this.Version < 1 || this.Version > 2) { throw new Exception(); } int size = input.ReadValueS32(); this.Data = new MemoryStream(); this.Data.WriteValueS16(this.Version); this.Data.WriteValueS32(size); byte[] data = new byte[size - (4 + 2)]; input.Read(data, 0, data.Length); this.Data.Write(data, 0, data.Length); this.Items = new Dictionary <UInt32, int>(); short count = input.ReadValueS16(); for (short i = 0; i < count; i++) { UInt32 hash = input.ReadValueU32(); int offset = input.ReadValueS32(); this.Items.Add(hash, offset); } }
private void ReadFields(Stream s) { _dataList = new List <DataItem>(_itemCount); for (var i = 0; i < _itemCount; i++) { var pos = s.Position; var field = new DataItem { Name = s.ReadStringZ(Encoding) }; s.Seek(pos + 48, SeekOrigin.Begin); field.DataType = s.ReadValueS32(Endianness); field.DataCount = s.ReadValueS32(Endianness); field.DataLength = s.ReadValueS32(Endianness); s.ReadValueS32(Endianness); // Leemos el 0 que hay al final field.Data = new List <TFString>(); field.AdditionalValues = new List <short>(); _dataList.Add(field); } }
public override void Read(Stream s) { s.Seek(8, SeekOrigin.Begin); _firstStringOffset = s.ReadValueS32(Endianness); var currentIndex = s.FindPattern(PATTERN); while (currentIndex != -1) { var localOffset = s.ReadValueS32(Endianness); var control = s.ReadValueS16(Endianness); if (control == 0 || control == 8) { // Es un texto que hay que añadir var item = new DataItem { RelativeOffset = localOffset, RelativeOffsetPosition = (int)(s.Position - 6) }; var pos = s.Position; s.Seek(_firstStringOffset + localOffset, SeekOrigin.Begin); item.Data = ReadString(s); s.Seek(currentIndex + 4, SeekOrigin.Begin); _strings.Add(item); } currentIndex = s.FindPattern(PATTERN); } }
private void ReadHeader(Stream s) { _unknown1 = s.ReadValueS32(Endianness); _itemCount = s.ReadValueS32(Endianness); _unknown2 = s.ReadValueS32(Endianness); _unknown3 = s.ReadValueS32(Endianness); }
private void ReadHeader(Stream s) { _signature = s.ReadValueS32(Endianness); // 20 07 03 19 _itemCount = s.ReadValueS32(Endianness); _unknown1 = s.ReadValueS32(Endianness); _unknown2 = s.ReadValueS32(Endianness); // 0 }
public ME2ExportEntry(ME2Package pccFile, Stream stream) : base(pccFile) { //determine header length long start = stream.Position; stream.Seek(40, SeekOrigin.Current); int count = stream.ReadValueS32(); stream.Seek(4 + count * 12, SeekOrigin.Current); count = stream.ReadValueS32(); stream.Seek(16, SeekOrigin.Current); stream.Seek(4 + count * 4, SeekOrigin.Current); long end = stream.Position; stream.Seek(start, SeekOrigin.Begin); //read header Header = stream.ReadBytes((int)(end - start)); headerOffset = (uint)start; OriginalDataSize = DataSize; //read data stream.Seek(DataOffset, SeekOrigin.Begin); _data = stream.ReadBytes(DataSize); stream.Seek(end, SeekOrigin.Begin); if ((ObjectFlags & (ulong)UnrealFlags.EObjectFlags.HasStack) != 0) { ReadsFromConfig = (Data[25] & 64) != 0; } else { ReadsFromConfig = false; } }
public ME1ExportEntry(ME1Package pccFile, Stream stream) : base(pccFile) { //determine header length long start = stream.Position; stream.Seek(40, SeekOrigin.Current); int count = stream.ReadValueS32(); stream.Seek(4 + count * 12, SeekOrigin.Current); count = stream.ReadValueS32(); stream.Seek(16, SeekOrigin.Current); stream.Seek(4 + count * 4, SeekOrigin.Current); long end = stream.Position; stream.Seek(start, SeekOrigin.Begin); //read header Header = stream.ReadBytes((int)(end - start)); headerOffset = (uint)start; OriginalDataSize = DataSize; //read data stream.Seek(DataOffset, SeekOrigin.Begin); _data = stream.ReadBytes(DataSize); stream.Seek(end, SeekOrigin.Begin); if (ClassName.Contains("Property")) { ReadsFromConfig = Data.Length > 25 && (Data[25] & 64) != 0; } else { ReadsFromConfig = false; } }
public void Deserialize(Stream input) { this.Unknown00 = input.ReadValueU32(); this.Comment = input.ReadString(16, true, Encoding.GetEncoding(932)); this.TextureIndex = input.ReadValueS32(); this.Unknown18 = input.ReadValueU32(); this.Unknown1C = new byte[16]; input.Read(this.Unknown1C, 0, this.Unknown1C.Length); this.Unknown2C = input.ReadValueU32(); this.Unknown30 = new byte[12]; input.Read(this.Unknown30, 0, this.Unknown30.Length); this.Unknown3C = input.ReadValueU32(); this.Unknown40 = input.ReadValueU32(); this.Unknown44 = input.ReadValueU32(); this.Unknown48 = input.ReadValueU32(); this.Unknown4C = new byte[8]; input.Read(this.Unknown4C, 0, this.Unknown4C.Length); this.Left = input.ReadValueS32(); this.Top = input.ReadValueS32(); this.Right = input.ReadValueS32(); this.Bottom = input.ReadValueS32(); this.Unknown64 = new byte[16]; input.Read(this.Unknown64, 0, this.Unknown64.Length); this.Unknown74 = input.ReadValueS16(); this.Unknown76 = input.ReadValueS16(); this.Unknown78 = new byte[8]; input.Read(this.Unknown78, 0, this.Unknown78.Length); foreach (var u1C in this.Unknown1C) { if (u1C != 0) { throw new FormatException(); } } foreach (var u4C in this.Unknown4C) { if (u4C != 0) { throw new FormatException(); } } foreach (var u64 in this.Unknown64) { if (u64 != 128 && u64 != 255) { //throw new FormatException(); } } foreach (var u78 in this.Unknown78) { if (u78 != 0) { throw new FormatException(); } } }
protected override DataFormats.Ranged <int> Read(Stream input, Endian endian) { var range = input.ReadValueS32(endian); var value = input.ReadValueS32(endian); return(new DataFormats.Ranged <int>(range, value)); }
public static RawItem Read(Stream input, Endian endian) { var instance = new RawItem(); instance.Name = input.ReadValueU32(endian); instance.BaseName = input.ReadValueU32(endian); instance.Type = input.ReadValueS32(endian); instance.Purchasable = input.ReadValueS32(endian); instance.Consumable = input.ReadValueS32(endian); instance.Rewardable = input.ReadValueS32(endian); instance.Collectable = input.ReadValueS32(endian); input.Seek(4, SeekOrigin.Current); instance.FeatOffset = input.ReadValueS64(endian); instance.FeatCount = input.ReadValueS64(endian); instance.Region = input.ReadValueU32(endian); instance.RebelDropTimer = input.ReadValueS32(endian); instance.MaxInventory = input.ReadValueS32(endian); instance.UIType = input.ReadValueS32(endian); instance.UIFlag = input.ReadValueS32(endian); instance.UIDisplayOrder = input.ReadValueS32(endian); instance.UIName = input.ReadValueU32(endian); instance.UIDescription = input.ReadValueU32(endian); instance.UITypeDescription = input.ReadValueU32(endian); instance.UIFlagDescription = input.ReadValueU32(endian); instance.UIImagePathOffset = input.ReadValueS64(endian); instance.UIVideoPathOffset = input.ReadValueS64(endian); instance.UIPar0 = input.ReadValueF32(endian); instance.UIPar1 = input.ReadValueF32(endian); instance.UIPar2 = input.ReadValueF32(endian); instance.UIPar3 = input.ReadValueF32(endian); instance.UIPar4 = input.ReadValueF32(endian); input.Seek(4, SeekOrigin.Current); return(instance); }
private void ReadHeader(Stream s) { _signature = s.ReadValueS32(Endianness); _unknown1 = s.ReadValueS32(Endianness); // 65536 _unknown2 = s.ReadValueS32(Endianness); // 1 _unknown3 = s.ReadValueS32(Endianness); // 0 _itemCount = s.ReadValueS32(Endianness); }
public static ArrayEntry Read(Stream input, Endian endian) { ArrayEntry instance; instance.DataOffset = input.ReadValueU32(endian); instance.ItemCount = input.ReadValueS32(endian); instance.TypeIndex = input.ReadValueS32(endian); return(instance); }
public void Deserialize(Stream input, Endian endian) { this.Name = input.ReadStringU16(0x40, Encoding.ASCII, endian); this.Type = input.ReadValueU8(); this.Allocator = input.ReadValueU8(); this.Unknown3 = input.ReadValueU8(); this.Unknown4 = input.ReadValueU8(); this.HeaderSize = input.ReadValueS32(endian); this.DataSize = input.ReadValueS32(endian); }
public void Deserialize(Stream input, Endian endian) { this.Name = input.ReadStringU16(0x40, Encoding.ASCII, endian); this.Type = input.ReadValueU8(); this.Allocator = input.ReadValueU8(); this.Flags = (PrimitiveFlags)input.ReadValueU8(); this.SplitIndex = input.ReadValueU8(); this.CPUSize = input.ReadValueS32(endian); this.GPUSize = input.ReadValueS32(endian); this.Unknown7 = input.ReadValueU8(); }
public override void Deserialize(Stream input) { this.Name = input.ReadStringAlignedU8(); this.Language = (byte)input.ReadValueS32(); this.Modulo = input.ReadValueU32(); this.SizeOfBuffer = input.ReadValueU32(); var length = input.ReadValueS32(); this.Buffer = new byte[length]; input.Read(this.Buffer, 0, this.Buffer.Length); }
internal static ItemReward Read(Stream input, Endian endian) { var instance = new ItemReward(); instance.Item = input.ReadValueU32(endian); instance.Permanent = input.ReadValueS32(endian); instance.Duration = input.ReadValueS32(endian); instance.Quantity = input.ReadValueS32(endian); instance.Delivery = input.ReadValueS32(endian); return(instance); }
void PropertyContainerFile.IRawVariant.Deserialize(Stream input, Endian endian) { int count = input.ReadValueS32(endian); var values = new int[count]; for (int i = 0; i < count; i++) { values[i] = input.ReadValueS32(endian); } this._Values.Clear(); this._Values.AddRange(values); }
public static RawReward Read(Stream input, Endian endian) { var instance = new RawReward(); instance.Skillpoints = input.ReadValueS32(endian); instance.Chaos = input.ReadValueS32(endian); instance.ItemRewardSemantics = input.ReadValueS32(endian); input.Seek(4, SeekOrigin.Current); instance.ItemOffset = input.ReadValueS64(endian); instance.ItemCount = input.ReadValueS64(endian); return(instance); }
public void Deserialize(Stream input) { var directoryCount = input.ReadValueS32(); if (input.Position + (directoryCount * 8) > input.Length) { throw new EndOfStreamException(); } // don't need to load this information for our uses :) /* * for (int i = 0; i < directoryCount; i++) * { * var directoryId = input.ReadValueU32(); * var firstFileIndex = input.ReadValueU32(); * } */ input.Seek(directoryCount * 8, SeekOrigin.Current); var fileCount = input.ReadValueS32(); if (input.Position + (fileCount * 12) > input.Length) { throw new EndOfStreamException(); } byte[] fileData = new byte[fileCount * 12]; input.Read(fileData, 0, fileData.Length); var directoryNameSize = input.ReadValueU32(); var fileNameSize = input.ReadValueU32(); input.Seek(directoryNameSize, SeekOrigin.Current); // don't need to load directory names var fileNames = input.ReadToMemoryStream(fileNameSize); this.Entries.Clear(); for (int i = 0; i < fileCount; i++) { if (fileNames.Position >= fileNames.Length) { throw new EndOfStreamException(); } this.Entries.Add(new Entry() { Path = fileNames.ReadStringZ().Replace('/', '\\'), Offset = BitConverter.ToUInt32(fileData, (i * 12) + 0), Size = BitConverter.ToUInt32(fileData, (i * 12) + 4), }); } }
public static RawDirectoryEntry Read(Stream input, Endian endian) { RawDirectoryEntry instance; instance.DirectoryCount = input.ReadValueS32(endian); instance.DirectoryIndex = input.ReadValueS32(endian); instance.FileCount = input.ReadValueS32(endian); instance.FileIndex = input.ReadValueS32(endian); instance.Unknown10 = input.ReadValueU32(endian); instance.Unknown14 = input.ReadValueU32(endian); instance.Unknown18 = input.ReadValueU32(endian); instance.Unknown1C = input.ReadValueU32(endian); return instance; }
public override void Read(Stream s) { _unknown1 = s.ReadValueS32(Endianness); _unknown2 = s.ReadValueS16(Endianness); _num = s.ReadValueS16(Endianness); _unknown3 = s.ReadValueS32(Endianness); _table2Offset = s.ReadValueS32(Endianness); _dataList1 = new List <TFString>(); _dataList2 = new List <ItemData>(); var firstString = -1; for (var i = 0; i < 43; i++) { var str = ReadString(s); _dataList1.Add(str); if (firstString == -1) { firstString = str.Offset; } } _remainder1 = s.ReadBytes(0x54); for (var i = 0; i < _num; i++) { var item = new ItemData(); for (var j = 0; j < 12; j++) { item.Unknown[j] = s.ReadValueS32(Endianness); } if (firstString == -1) { firstString = item.Unknown[8]; } item.Data = ReadString(s, item.Unknown[8]); _dataList2.Add(item); } var remainderSize = (int)(firstString - s.Position); if (remainderSize > 0) { _remainder2 = ReadRemainder(s, remainderSize); } }
private void ReadHeader(Stream s) { s.Seek(0, SeekOrigin.Begin); var header = _root.Header; header.Signature = s.ReadBytes(4); header.Size1 = s.ReadValueS32(Endianness); header.ContentOffset = s.ReadValueS32(Endianness); header.Unknown1 = s.ReadValueS32(Endianness); header.Unknown2 = s.ReadValueS32(Endianness); header.ContentSize = s.ReadValueS32(Endianness); header.Unknown3 = s.ReadValueS64(Endianness); }
public void Deserialize(Stream input, Endian endian) { this.FaceCount = input.ReadValueS32(endian); this.FaceIndex = input.ReadValueS32(endian); var count = input.ReadValueS32(endian); this.BoneIndices.Clear(); this.BoneIndices.Capacity = count; for (int i = 0; i < count; i++) { this.BoneIndices.Add(input.ReadValueS16(endian)); } }
public override void Read(Stream s) { var numFiles = s.ReadValueS16(Endianness); for (var i = 0; i < numFiles; i++) { s.Seek(8 + i * 16, SeekOrigin.Begin); var f = new File { Unknown = s.ReadValueS32(Endianness), OffsetMsg = s.ReadValueS32(Endianness), OffsetRemainder = s.ReadValueS32(Endianness), SizeMsg = s.ReadValueS16(Endianness), SizeRemainder = s.ReadValueS16(Endianness) }; if (f.OffsetMsg != 0) { s.Seek(f.OffsetMsg, SeekOrigin.Begin); f.MsgBytes = s.ReadBytes(f.SizeMsg); var msgFile = new MsgFile(string.Empty); using (var ms = new MemoryStream(f.MsgBytes)) { msgFile.Read(ms); } if (msgFile.Strings.Count > 0) { foreach (var tfString in msgFile.Strings) { tfString.Section = f.OffsetMsg.ToString("X8"); tfString.FileId = Id; } } f.Msg = msgFile; } if (f.OffsetRemainder != 0) { s.Seek(f.OffsetRemainder, SeekOrigin.Begin); f.Remainder = s.ReadBytes(f.SizeRemainder); } _files.Add(f); } }
private TFString ReadString(Stream s) { var stringOffset = s.ReadValueS32(Endianness); var pos = s.Position; var value = new TFString { FileId = Id, Offset = stringOffset, Visible = false }; if (stringOffset != 0) { s.Seek(stringOffset, SeekOrigin.Begin); var str = s.ReadStringZ(Encoding); if (!string.IsNullOrEmpty(str.TrimEnd('\0'))) { str = Yakuza0Project.ReadingReplacements(str); value.Original = str; value.Translation = str; value.Visible = true; } } s.Seek(pos, SeekOrigin.Begin); return(value); }
void PropertyContainerFile.IRawVariant.Deserialize(Stream input, Endian endian) { int count = input.ReadValueS32(endian); var bytes = input.ReadBytes(count); this._Value = bytes; }
public override void Deserialize(Stream input) { var length = input.ReadValueS32(); this.Data = new byte[length]; input.Read(this.Data, 0, this.Data.Length); }
public void Deserialize(Stream input, Endian endian) { this.Size = input.ReadValueU32(endian); this.Flags = input.ReadValueEnum<HeaderFlags>(endian); this.Height = input.ReadValueS32(endian); this.Width = input.ReadValueS32(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 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 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) { 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); } }
/// <summary> /// Takes compressed archived image data and returns the raw image data /// </summary> /// <param name="data"></param> /// <returns></returns> public byte[] DecompressTex(Stream archiveStream, int offset, int uncSize, int cprSize) { int pos = 0; archiveStream.Seek(offset, SeekOrigin.Begin); int magicNumber = archiveStream.ReadValueS32(); pos += 4; if (magicNumber != -1641380927) { throw new FormatException("Magic Number is not correct. Invalid archive data"); } int blockSize = archiveStream.ReadValueS32(); pos += 4; int readCprSize = archiveStream.ReadValueS32(); //Archive cprSize doesn't include header size pos += 4; int uncReadSize = archiveStream.ReadValueS32(); if (uncReadSize != uncSize) { throw new FormatException("Uncompressed data sizes don't match. Read: " + uncReadSize + ", expected: " + uncSize); } pos += 4; int noChunks = (uncSize + blockSize - 1) / blockSize; CompressedChunkBlock[] chunks = new CompressedChunkBlock[noChunks]; for (int i = 0; i < noChunks; i++) { CompressedChunkBlock chunk = new CompressedChunkBlock(); chunk.cprSize = archiveStream.ReadValueS32(); chunk.uncSize = archiveStream.ReadValueS32(); chunk.rawData = new byte[chunk.cprSize]; pos += 8; chunks[i] = chunk; } if (readCprSize + pos != cprSize) { throw new FormatException("Compressed data sizes don't match. Invalid archive data"); } byte[] rawData = new byte[readCprSize]; rawData = archiveStream.ReadBytes(readCprSize); archiveStream.Close(); using (MemoryStream data = new MemoryStream(rawData)) { for (int i = 0; i < noChunks; i++) { chunks[i].rawData = data.ReadBytes(chunks[i].cprSize); } } byte[] imgBuffer = new byte[uncSize]; int resultPos = 0; for (int i = 0; i < noChunks; i++) { CompressedChunkBlock chunk = chunks[i]; byte[] tempResult = new byte[chunk.uncSize]; try { LZO1X.Decompress(chunk.rawData, tempResult); } catch { throw new Exception("LZO decompression failed!"); } Buffer.BlockCopy(tempResult, 0, imgBuffer, resultPos, chunk.uncSize); resultPos += chunk.uncSize; } return imgBuffer; }
public MemoryStream DecompressPCC(Stream raw, IPCCObject pcc) { raw.Seek(pcc.header.Length, SeekOrigin.Begin); int pos = 4; pcc.NumChunks = raw.ReadValueS32(); List<Chunk> Chunks = new List<Chunk>(); //DebugOutput.PrintLn("Reading chunk headers..."); for (int i = 0; i < pcc.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; }
/// <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) { 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) { 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(); } } } } } }
public void Deserialize(Stream input) { input.Seek(0, SeekOrigin.Begin); var magic = input.ReadValueU32(false); if (magic != 0x47464620) { throw new FormatException(); } var version = input.ReadValueU32(false); if (version != 0x56342E30 && // 4.0 version != 0x56342E31) // 4.1 { throw new FormatException("unsupported version"); } this.FileVersion = (byte)(version - 0x56342E30); this.FilePlatform = input.ReadValueEnum<GFF.FilePlatform>(false); this.FormatType = input.ReadValueEnum<GFF.FormatType>(false); this.FormatVersion = input.ReadValueU32(false); var littleEndian = this.FilePlatform == GFF.FilePlatform.PC; var structCount = input.ReadValueU32(littleEndian); var stringCount = this.FileVersion < 1 ? 0 : input.ReadValueU32(littleEndian); var stringOffset = this.FileVersion < 1 ? 0 : input.ReadValueU32(littleEndian); var dataOffset = input.ReadValueU32(littleEndian); if (this.FileVersion < 1) { stringOffset = dataOffset; } else { if (dataOffset < stringOffset) { throw new FormatException(); } } this.Structures.Clear(); for (uint i = 0; i < structCount; i++) { var structDef = new GFF.StructureDefinition(); //structDef.Id = input.ReadValueU32(littleEndian); structDef.Id = input.ReadValueU32(false); var fieldCount = input.ReadValueU32(littleEndian); var fieldOffset = input.ReadValueU32(littleEndian); structDef.DataSize = input.ReadValueU32(littleEndian); long nextOffset = input.Position; structDef.Fields.Clear(); input.Seek(fieldOffset, SeekOrigin.Begin); for (uint j = 0; j < fieldCount; j++) { var fieldDef = new GFF.FieldDefinition(); fieldDef.Id = input.ReadValueS32(littleEndian); var rawFlags = input.ReadValueU32(littleEndian); fieldDef.Offset = input.ReadValueU32(littleEndian); var type = (ushort)(rawFlags & 0xFFFF); var flags = (GFF.FieldFlags)((rawFlags >> 16) & 0xFFFF); if ((flags & GFF.FieldFlags.IsStructure) != 0) { flags &= ~GFF.FieldFlags.IsStructure; fieldDef.Type = GFF.FieldType.Structure; fieldDef.StructureId = type; } else { fieldDef.Type = (GFF.FieldType)type; } fieldDef.Flags = flags; structDef.Fields.Add(fieldDef); } this.Structures.Add(structDef); input.Seek(nextOffset, SeekOrigin.Begin); } if (this.FileVersion >= 1) { input.Seek(stringOffset, SeekOrigin.Begin); this.StringTable = new List<string>(); for (uint i = 0; i < stringCount; i++) { this.StringTable.Add(input.ReadStringZ(Encoding.UTF8)); } } input.Seek(dataOffset, SeekOrigin.Begin); this.Data = input.ReadToMemoryStream(input.Length - dataOffset); }
public void Deserialize(Stream input) { var magic = input.ReadValueU32(Endian.Little); if (magic != 0x666D726D && // fmrm magic.Swap() != 0x666D726D) { throw new FormatException(); } var endian = magic == 0x666D726D ? Endian.Little : Endian.Big; var version = input.ReadValueU32(endian); if (version != 1) { throw new FormatException(); } this.Version = version; /*var maxKeyLength =*/ input.ReadValueS32(endian); var maxValueLength = input.ReadValueS32(endian); var stringTableSize = input.ReadValueU32(endian); var huffmanSize = input.ReadValueU32(endian); var indexSize = input.ReadValueU32(endian); var dataSize = input.ReadValueU32(endian); var strings = new List<KeyValuePair<uint, string>>(); using (var data = input.ReadToMemoryStream(stringTableSize)) { var localStringTableSize = data.ReadValueU32(endian); if (localStringTableSize != stringTableSize) { throw new FormatException(); } var count = data.ReadValueU32(endian); var offsets = new List<KeyValuePair<uint, uint>>(); for (uint i = 0; i < count; i++) { var hash = data.ReadValueU32(endian); var offset = data.ReadValueU32(endian); offsets.Add(new KeyValuePair<uint, uint>(hash, offset)); } foreach (var kv in offsets) { var hash = kv.Key; var offset = kv.Value; data.Seek(8 + offset, SeekOrigin.Begin); var length = data.ReadValueU16(endian); var text = data.ReadString(length, Encoding.UTF8); if (text.HashCrc32() != hash) { throw new InvalidOperationException(); } strings.Add(new KeyValuePair<uint, string>(hash, text)); } } Huffman.Pair[] huffmanTree; using (var data = input.ReadToMemoryStream(huffmanSize)) { var count = data.ReadValueU16(endian); huffmanTree = new Huffman.Pair[count]; for (ushort i = 0; i < count; i++) { var left = data.ReadValueS32(endian); var right = data.ReadValueS32(endian); huffmanTree[i] = new Huffman.Pair(left, right); } } using (var index = input.ReadToMemoryStream(indexSize)) { var totalBits = input.ReadValueS32(endian); var data = input.ReadBytes(dataSize); var bitArray = new BitArray(data) { Length = totalBits }; var files = new List<KeyValuePair<string, uint>>(); var fileCount = index.ReadValueU16(endian); for (ushort i = 0; i < fileCount; i++) { var nameIndex = index.ReadValueU16(endian); var name = strings[nameIndex].Value; var offset = index.ReadValueU32(endian); files.Add(new KeyValuePair<string, uint>(name, offset)); } foreach (var fileInfo in files.OrderBy(f => f.Key)) { var file = new Coalesced.File() { Name = fileInfo.Key }; index.Seek(fileInfo.Value, SeekOrigin.Begin); var sectionCount = index.ReadValueU16(endian); var sections = new List<KeyValuePair<string, uint>>(); for (ushort i = 0; i < sectionCount; i++) { var nameIndex = index.ReadValueU16(endian); var name = strings[nameIndex].Value; var offset = index.ReadValueU32(endian); sections.Add(new KeyValuePair<string, uint>(name, offset)); } foreach (var sectionInfo in sections.OrderBy(s => s.Key)) { var section = new Dictionary<string, List<Coalesced.Entry>>(); index.Seek(fileInfo.Value + sectionInfo.Value, SeekOrigin.Begin); var valueCount = index.ReadValueU16(endian); var values = new List<KeyValuePair<string, uint>>(); for (ushort i = 0; i < valueCount; i++) { var nameIndex = index.ReadValueU16(endian); var name = strings[nameIndex].Value; var offset = index.ReadValueU32(endian); values.Add(new KeyValuePair<string, uint>(name, offset)); } foreach (var valueInfo in values.OrderBy(v => v.Key)) { var value = new List<Coalesced.Entry>(); index.Seek(fileInfo.Value + sectionInfo.Value + valueInfo.Value, SeekOrigin.Begin); var itemCount = index.ReadValueU16(endian); for (ushort i = 0; i < itemCount; i++) { var offset = index.ReadValueS32(endian); var type = (offset & 0xE0000000) >> 29; if (type == 1) { value.Add(new Coalesced.Entry(1, null)); } else if (type == 0 || type == 2 || type == 3 || type == 4) { offset &= 0x1FFFFFFF; var text = Huffman.Decoder.Decode( huffmanTree, bitArray, offset, maxValueLength); value.Add(new Coalesced.Entry(2, text)); } else { throw new NotImplementedException(); } } section.Add(valueInfo.Key, value); } file.Sections.Add(sectionInfo.Key, section); } this.Files.Add(file); } } this.Endian = endian; }
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, }); }