Exemple #1
0
        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);
        }
Exemple #2
0
        protected override ChunkList InternalGetChildren()
        {
            if (ChunkTypeId == SCUMM1ChunkSpecs.RoomName)
            {
                return(GetRoomChildren());
            }
            ChunkList result = new ChunkList();

            return(result);
        }
Exemple #3
0
        public Chunk SelectSingle(string path)
        {
            ChunkList list = Select(path);

            if (list.Count == 0)
            {
                return(null);
            }
            return(list[0]);
        }
Exemple #4
0
        public Chunk SelectSingleAfter(string path, uint offset)
        {
            ChunkList list = Select(path);

            foreach (Chunk chunk in list)
            {
                if (chunk.Offset >= offset)
                {
                    return(chunk);
                }
            }
            return(null);
        }
Exemple #5
0
        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);
        }
Exemple #6
0
        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);
        }
Exemple #7
0
        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);
        }
Exemple #8
0
        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);
        }
Exemple #9
0
        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);
        }
Exemple #10
0
        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);
        }
Exemple #11
0
        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);
        }
Exemple #12
0
        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);
        }
Exemple #13
0
        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);
        }
Exemple #14
0
 public ChunkList GetChildren()
 {
     return(children ?? (children = InternalGetChildren()));
 }
Exemple #15
0
        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);
        }