/// <summary>Switch the <see cref="Reader"/> for a <see cref="BigEndianBinaryReader"/>.</summary> public BinaryReader MakeBigEndian() { return Reader = new BigEndianBinaryReader(Stream); }
/// <summary>Switch to the use of a <see cref="MarkingStream"/>.</summary> /// <returns></returns> public MarkingStream StartMarking() { if (Reader.BaseStream is MarkingStream) { return (MarkingStream)Reader.BaseStream; } var markingStream = new MarkingStream(Reader.BaseStream); if (Reader is BigEndianBinaryReader) Reader = new BigEndianBinaryReader(markingStream); else Reader = new BinaryReader(markingStream); return markingStream; }
internal Archive(AssetManager manager, AssetLoader loader) : base(manager, "Dark Souls archive - " + loader.Name) { FileManager = new ArchiveFileManager(this); var reader = loader.Reader; var path = loader.Name; var context = loader.FileManager; string magic = reader.ReadString(4, Encoding.ASCII); string extension = System.IO.Path.GetExtension(path); // Switch to the headers file if we got a contents file. if (magic == ContentsMagicBDF3 || magic == ContentsMagicBDF4) { string headersPathBase = RemoveSuffix(path, ContentsExtensionEnd); Stream headersStream = OpenOtherFile(headersPathBase, context, HeadersExtensionEnd, HeadersExtension5End); DataStream = reader.BaseStream; DataReader = reader; reader = BigEndianBinaryReader.Create(IsBigEndian ? ByteOrder.BigEndian : ByteOrder.LittleEndian, headersStream); magic = reader.ReadString(4, Encoding.ASCII); } if (magic == PackageMagicBND4) { IsBigEndian = true; IsDarkSoulsII = true; } // Get the variant. switch (magic) { case ContentsMagicBDF3: case HeadersMagicBHD5: Variant = ArchiveVariant.V5; break; case HeadersMagicBHF3: case PackageMagicBND3: Variant = ArchiveVariant.V3; break; case ContentsMagicBDF4: case HeadersMagicBHF4: case PackageMagicBND4: Variant = ArchiveVariant.V4; break; default: throw new NotImplementedException(); } if (DataReader == null) { if (magic == PackageMagicBND4 || magic == PackageMagicBND3) { IsHeaderlessPackage = true; DataStream = reader.BaseStream; DataReader = reader; if (IsBigEndian) reader = new BigEndianBinaryReader(reader.BaseStream); } else if (magic == HeadersMagicBHD5 || magic == HeadersMagicBHF4 || magic == HeadersMagicBHF3) { string contentsPathBase = RemoveSuffix(path, HeadersExtensionEnd, HeadersExtension5End); DataStream = OpenOtherFile(contentsPathBase, context, ContentsExtensionEnd); DataReader = new BinaryReader(DataStream); if (IsBigEndian) reader = new BigEndianBinaryReader(reader.BaseStream); } else throw new NotImplementedException(); } try { switch (Variant) { case ArchiveVariant.V3: { Id = reader.ReadStringz(8, Encoding.ASCII); int version = reader.ReadInt32(); if (version != 0x74 && version != 0x54) throw new InvalidDataException(); int recordCount = reader.ReadInt32(); int totalHeaderSize = reader.ReadInt32(); // Either zero or the unaligned end of the last record's name before the first record's data. reader.RequireZeroes(8); for (int index = 0; index < recordCount; index++) new ArchiveRecord(this, index, reader, -1); break; } case ArchiveVariant.V4: { IsDarkSoulsII = true; int byteOrder = reader.ReadInt32(); if (byteOrder == 257) { IsBigEndian = true; reader = new BigEndianBinaryReader(reader.BaseStream); } else if (byteOrder != 0x01010000) throw new Exception(); reader.Require(0x10000); int recordCount = reader.ReadInt32(); long recordOffset = reader.ReadInt64(); if (recordOffset != 0x40) throw new Exception(); Id = reader.ReadString(8, Encoding.ASCII); int recordHeaderSize = checked((int)reader.ReadInt64()); if (recordHeaderSize != 0x1C && recordHeaderSize != 0x24) throw new Exception(); long u2 = reader.ReadInt64(); // 0 or end of the name strings int u1 = reader.ReadInt16(); // 0x1C or 0x12E? reader.RequireZeroes(14); for (int index = 0; index < recordCount; index++) new ArchiveRecord(this, index, reader, recordHeaderSize); break; } case ArchiveVariant.V5: reader.Require(0xFF); reader.Require(1); uint totalFileSize = reader.ReadUInt32(); int binCount = reader.ReadInt32(); reader.Require(0x18); // Groups offset int[] binInfo = reader.ReadArrayInt32(binCount * 2); for (int index = 0, totalRecordIndex = 0; index < binCount; index++) { reader.BaseStream.Position = binInfo[index * 2 + 1]; int count = binInfo[index * 2 + 0]; // Each record in a group belongs to the same "bin"; for (int recordIndex = 0; recordIndex < count; recordIndex++) new ArchiveRecord(this, totalRecordIndex, reader, -1); } break; default: throw new NotImplementedException(Variant + " is not implemented, durr"); } } finally { if (!IsHeaderlessPackage) reader.Dispose(); } SortChildrenRecursively(); foreach (var record in Records) { RecordsById[record.Id] = record; RecordsByPath[record.PathName] = record; } }