protected override ChunkList InternalGetChildren() { var bnhdChunk = SelectSingle("../BNHD"); if (bnhdChunk == null) { throw new ScummRevisitedException("BNHD chunk is required to read contents of BNDT."); } ChunkList result = new ChunkList(); using (var reader = bnhdChunk.GetReader()) { reader.Position = 0x1002a; // header (0x2a) + some table (0x10000) while (reader.Position < reader.Size) { string name = reader.ReadStringZ(0xaa, true); reader.Position += (ulong)(200 - (name.Length + 1)); uint size = reader.ReadU32LE(); ulong offset = reader.ReadU32LE() + this.Offset + 8; // Offset is relative to start of BNDT's content (after FourCC and size) var chunk = new FileChunk(file, this, name, offset, size); result.Add(chunk); reader.Position += 44; } } return(result); }
protected override ChunkList InternalGetChildren() { ChunkList result = new ChunkList(); file.Position = Offset + 8; uint fileCount = file.ReadU32LE(); uint nameDirectorySize = file.ReadU32LE(); uint nameDirectoryOffset = file.ReadU32LE(); byte nameEncryption = 0; if (nameDirectoryOffset == 0) { // GF bundle: // We actually just read the first file name offset, so retreat: file.Position -= 4; nameDirectoryOffset = 0x10 + fileCount * 0x10; } else { // EMI bundle: // Names are encrypted: nameEncryption = 0x96; // Looks like an attempt to make reverse engineering harder: nameDirectoryOffset -= 0x13D0F; } uint[] nameOffsets = new uint[fileCount]; uint[] offsets = new uint[fileCount]; uint[] sizes = new uint[fileCount]; for (uint i = 0; i < fileCount; i++) { nameOffsets[i] = file.ReadU32LE(); offsets[i] = file.ReadU32LE(); sizes[i] = file.ReadU32LE(); uint reserved = file.ReadU32LE(); Debug.Assert(reserved == 0, String.Format("Reserved directory value {0} isn't 0", i)); } for (uint i = 0; i < fileCount; i++) { file.Position = nameDirectoryOffset + nameOffsets[i]; string name = nameEncryption == 0 ? file.ReadStringZ() : file.ReadStringZ(nameEncryption); Chunk chunk = new FileChunk(file, this, name, offsets[i], sizes[i]); result.Add(chunk); } return(result); }
protected override ChunkList InternalGetChildren() { ChunkList result = new ChunkList(); ulong offset = Offset; while (offset < Offset + Size) { file.Position = offset; Chunk chunk = SCUMM5Chunk.ReadChunk(file, this); result.Add(chunk); offset += chunk.Size; } return(result); }
protected override ChunkList InternalGetChildren() { // TODO: This should probably be moved to be handled by TellTaleFile file.Position = Offset; var reader = file; //.GetChunkReader(this); var fileInfo = TTArchFile.PrepareFileInfo(reader); var result = new ChunkList(); reader.Position = fileInfo.InfoOffset; uint folderCount = reader.ReadU32LE(); for (uint i = 0; i < folderCount; i++) { uint nameSize = reader.ReadU32LE(); string name = reader.ReadString(nameSize); result.Add(new TellTaleFileChunk(this.File, this, name, 0, 0)); } uint fileCount = reader.ReadU32LE(); for (uint i = 0; i < fileCount; i++) { uint nameSize = reader.ReadU32LE(); string name = reader.ReadString(nameSize); uint zero = reader.ReadU32LE(); ulong offset = reader.ReadU32LE() + fileInfo.VirtualBlocksOffset; uint size = reader.ReadU32LE(); result.Add(new TellTaleFileChunk(this.File, this, name, offset, size)); } return(result); }
protected override ChunkList InternalGetChildren() { ChunkList result = new ChunkList(); file.Position = Offset + spec.ChildOffset; ulong maxPosition = Offset + Size; while (file.Position < maxPosition) { Chunk chunk = ReadChunk(file, this); result.Add(chunk); file.Position = chunk.Offset + chunk.Size; } return(result); }
private ChunkList ReadTTA3(BinReader reader) { ChunkList result = new ChunkList(); FourCC tta3 = reader.ReadFourCC(); uint tta3Version = reader.ReadU32LE(); uint namesSize = reader.ReadU32LE(); uint fileCount = reader.ReadU32LE(); uint infoSize = fileCount * (8 + 8 + 4 + 4 + 2 + 2); ulong namesOffset = reader.Position + infoSize; ulong baseOffset = namesOffset + namesSize; byte[] infoTable = new byte[infoSize]; byte[] namesTable = new byte[namesSize]; reader.Read(infoTable, 0, infoSize); reader.Read(namesTable, 0, namesSize); using (MemoryStream infoStream = new MemoryStream(infoTable)) { using (BinReader infoReader = new BinReader(infoStream)) { for (int i = 0; i < fileCount; i++) { ulong hash = infoReader.ReadU64LE(); // In compressed archives, the offset is the offset in the "virtual" uncompressed archive ulong offset = infoReader.ReadU64LE() + baseOffset; uint size = infoReader.ReadU32LE(); uint unknown = infoReader.ReadU32LE(); ushort nameBlock = infoReader.ReadU16LE(); ushort nameOffset = infoReader.ReadU16LE(); long namePosition = nameOffset + (long)nameBlock * 0x10000; string name = GetNameFromTable(namesTable, namePosition); Chunk chunk = new TellTaleFileChunk(file, this, name, offset, size); result.Add(chunk); } } } return(result); }
protected override ChunkList InternalGetChildren() { ChunkList result = new ChunkList(); file.Position = Offset + 8; ulong maxPosition = Offset + Size; while (file.Position < maxPosition) { Chunk chunk = ReadChunk(file, this); if (chunk.ChunkTypeId == "BNDT") { chunk = new BNDTChunk(file, this, chunk.Offset, chunk.Size); } result.Add(chunk); file.Position = chunk.Offset + chunk.Size; } return(result); }
protected override ChunkList InternalGetChildren() { ChunkList result = new ChunkList(); file.Position = Offset + 4; uint dirOffset = file.ReadU32BE(); uint fileCount = file.ReadU32BE(); string date = file.ReadString(12); file.Position = dirOffset; for (uint i = 0; i < fileCount; i++) { string name = ""; byte b; for (int index = 0; index <= 11; index++) { b = file.ReadU8(); if (b != 0) { if (index == 8) { name += "."; } name += (char)b; } } uint offset = file.ReadU32BE(); uint size = file.ReadU32BE(); Chunk chunk = new FileChunk(file, this, name, offset, size); result.Add(chunk); } return(result); }
protected override ChunkList InternalGetChildren() { ChunkList result = new ChunkList(); file.Position = Offset + 4; float version = file.ReadU32LE(); uint crcOffset = file.ReadU32LE(); uint dirOffset = file.ReadU32LE(); uint nameTableOffset = file.ReadU32LE(); uint dataOffset = file.ReadU32LE(); uint crcSize = file.ReadU32LE(); uint dirSize = file.ReadU32LE(); uint nameTableSize = file.ReadU32LE(); uint dataSize = file.ReadU32LE(); uint dirPosition = dirOffset; while (dirPosition < nameTableOffset) { file.Position = dirPosition; uint offset = dataOffset + file.ReadU32LE(); uint nameOffset = nameTableOffset + file.ReadU32LE(); uint size = file.ReadU32LE(); uint otherSize = file.ReadU32LE(); uint flags = file.ReadU32LE(); file.Position = nameOffset; string name = file.ReadStringZ(); Chunk chunk = new FileChunk(file, this, name, offset, size); result.Add(chunk); dirPosition += 20; } return(result); }
private ChunkList GetRoomChildren() { var result = new ChunkList(); var reader = GetReader(); reader.Position = 10; ushort imageCharsOffset = reader.ReadU16LE(); ushort imageOffset = reader.ReadU16LE(); ushort paletteOffset = reader.ReadU16LE(); ushort zplaneOffset = reader.ReadU16LE(); ushort zplaneCharsOffset = reader.ReadU16LE(); byte objectCount = reader.ReadU8(); // or U16LE? byte unknown1 = reader.ReadU8(); byte soundCount = reader.ReadU8(); byte scriptCount = reader.ReadU8(); ushort excdOffset = reader.ReadU16LE(); ushort encdOffset = reader.ReadU16LE(); ushort afterObjectsOffset = excdOffset > 0 ? excdOffset // If there's an EXCD block, use that : encdOffset > 0 ? encdOffset // Or ENCD block : (ushort)Size; // If none of them, use the room block size List <ushort> obimOffsets = new List <ushort>(); List <ushort> obcdOffsets = new List <ushort>(); for (int i = 0; i < objectCount; i++) { obimOffsets.Add(reader.ReadU16LE()); } for (int i = 0; i < objectCount; i++) { obcdOffsets.Add(reader.ReadU16LE()); } obimOffsets.Sort(); obcdOffsets.Sort(); // RMHD = everything we read up until now var rmhdChunk = new SCUMM1Chunk(file, this, "RMHDv1", Offset + 2, (uint)reader.Position - 2); result.Add(rmhdChunk); // BOXD ulong boxdOffset = reader.Position; byte boxCount = reader.ReadU8(); uint boxdSize = (uint)(boxCount * 8 + 1); var boxdChunk = new SCUMM1Chunk(file, this, "BOXDv1", boxdOffset, boxdSize); result.Add(boxdChunk); reader.Position = boxdOffset + boxdSize; // BOXM ulong boxmOffset = reader.Position; uint boxmSize = (uint)(boxCount + boxCount * boxCount); var boxmChunk = new SCUMM1Chunk(file, this, "BOXMv1", boxmOffset, boxmSize); result.Add(boxmChunk); // There's not supposed to be a gap here, but in case there is... if (reader.Position < imageCharsOffset) { var unknownChunk = new SCUMM1Chunk(file, this, "????v1", reader.Position, (uint)(imageCharsOffset - reader.Position)); result.Add(unknownChunk); reader.Position = imageCharsOffset; } // RMCH - room image characters var rmchChunk = new SCUMM1Chunk(file, this, "RMCHv1", imageCharsOffset, (uint)(imageOffset - imageCharsOffset)); result.Add(rmchChunk); // RMIM var rmimChunk = new SCUMM1Chunk(file, this, "RMIMv1", imageOffset, (uint)(paletteOffset - imageOffset)); result.Add(rmimChunk); // CLUT - palette var clutChunk = new SCUMM1Chunk(file, this, "CLUTv1", paletteOffset, (uint)(zplaneOffset - paletteOffset)); result.Add(clutChunk); // ZPLN var zplnChunk = new SCUMM1Chunk(file, this, "ZPLNv1", zplaneOffset, (uint)(zplaneCharsOffset - zplaneOffset)); result.Add(zplnChunk); // ZPCH - zplane characters // Calculation of size depends on whether we have objects or not ushort zpchSize; if (objectCount > 0) { zpchSize = (ushort)(obimOffsets[0] - zplaneCharsOffset); } else { // If no objects, use offset to after-objects: zpchSize = (ushort)(afterObjectsOffset - zplaneCharsOffset); } var zpchChunk = new SCUMM1Chunk(file, this, "ZPCHv1", zplaneCharsOffset, zpchSize); result.Add(zpchChunk); // OBIM for (int i = 0; i < objectCount; i++) { uint offset = obimOffsets[i]; uint size = ((i < objectCount - 1) ? obimOffsets[i + 1] : obcdOffsets[0]) - offset; var chunk = new SCUMM1Chunk(file, this, "OBIMv1", offset, size); result.Add(chunk); } // OBCD for (int i = 0; i < objectCount; i++) { uint offset = obcdOffsets[i]; reader.Position = offset; uint calculatedSize = ((i < objectCount - 1) ? obcdOffsets[i + 1] : afterObjectsOffset) - offset; uint readSize = reader.ReadU16LE(); if (calculatedSize != readSize) { Logger.Warning("OBIM size differs between calculated ({0}) and read ({1})", calculatedSize, readSize); } var chunk = new SCUMM1Chunk(file, this, "OBCDv1", offset, calculatedSize); result.Add(chunk); } // EXCD if (excdOffset > 0) { uint excdSize = (encdOffset > 0 ? encdOffset : Size) - excdOffset; var excdChunk = new SCUMM1Chunk(file, this, "EXCDv1", excdOffset, excdSize); result.Add(excdChunk); } if (encdOffset > 0) { uint encdSize = Size - encdOffset; var encdChunk = new SCUMM1Chunk(file, this, "ENCDv1", encdOffset, encdSize); result.Add(encdChunk); } return(result); }
protected override ChunkList InternalGetChildren() { ChunkList result = new ChunkList(); file.Position = 9; version = file.ReadU32LE(); indexOffset = file.ReadU64LE(); unknown1 = file.ReadU64LE(); unknown2 = file.ReadU64LE(); // Index file.Position = indexOffset; uint fileCount = file.ReadU32LE(); uint index3Records = file.ReadU32LE(); // Only in AnvilNext?: uint unknown3 = file.ReadU32LE(); ulong unknown4 = file.ReadU64LE(); ulong unknown5 = file.ReadU64LE(); uint maxFilesPerFragment = file.ReadU32LE(); uint fragmentIndex = file.ReadU32LE(); ulong nextFragmentOffset = file.ReadU64LE(); while (nextFragmentOffset != 0xffffffffffffffff) { file.Position = nextFragmentOffset; uint fileCountInFragment = file.ReadU32LE(); uint fragmentIndex3Records = file.ReadU32LE(); ulong index1Offset = file.ReadU64LE(); nextFragmentOffset = file.ReadU64LE(); uint firstFileIndex = file.ReadU32LE(); uint lastFileIndex = file.ReadU32LE(); ulong index2Offset = file.ReadU64LE(); ulong index3Offset = file.ReadU64LE(); file.Position = index1Offset; List <DataBlockInfo> dataBlocks = new List <DataBlockInfo>(); for (uint fileIndex = 0; fileIndex < fileCountInFragment; fileIndex++) { ulong offset = file.ReadU64LE(); uint identifier = file.ReadU32LE(); uint unknown = file.ReadU32LE(); uint size = file.ReadU32LE(); dataBlocks.Add(new DataBlockInfo(offset, identifier, size)); } file.Position = index2Offset; for (int fileIndex = 0; fileIndex < fileCountInFragment; fileIndex++) { DataBlockInfo info = dataBlocks[fileIndex]; uint size = file.ReadU32LE(); info.Checksum = file.ReadU64LE(); info.Unknown1 = file.ReadU64LE(); info.Unknown2 = file.ReadU64LE(); info.NextFileIndex = file.ReadU32LE(); info.PreviousFileIndex = file.ReadU32LE(); info.Unknown3 = file.ReadU32LE(); info.Timestamp = file.ReadU32LE(); info.Name = file.ReadStringZ(128); info.Unknown4 = file.ReadU64LE(); info.Unknown5 = file.ReadU32LE(); info.Unknown6 = file.ReadU32LE(); // AnvilNext only? uint unknown7 = file.ReadU32LE(); } foreach (DataBlockInfo info in dataBlocks) { result.Add(new ForgeFileChunk(info, file, this)); } } return(result); }