Beispiel #1
0
        private bool ReadBND2(BinaryReader2 br)
        {
            br.BaseStream.Position += 4;

            int platform = br.ReadInt32();

            if (platform != 1)
            {
                platform = Util.ReverseBytes(platform);
            }
            Platform     = (BundlePlatform)platform;
            br.BigEndian = Console;

            br.BaseStream.Position -= 8;
            Version = br.ReadInt32();
            if (Version != 2)
            {
                throw new ReadFailedError("Unsupported Bundle Version: " + Version);
            }
            br.BaseStream.Position += 4;

            RSTOffset     = br.ReadInt32();
            EntryCount    = br.ReadInt32();
            IDBlockOffset = br.ReadInt32();
            uint[] fileBlockOffsets = new uint[3];
            fileBlockOffsets[0] = br.ReadUInt32();
            fileBlockOffsets[1] = br.ReadUInt32();
            fileBlockOffsets[2] = br.ReadUInt32();
            Flags = (Flags)br.ReadInt32();

            // 8 Bytes Padding

            br.BaseStream.Position = IDBlockOffset;

            for (int i = 0; i < EntryCount; i++)
            {
                BundleEntry entry = new BundleEntry(this);

                entry.Index = i;

                entry.Platform = Platform;

                entry.ID = br.ReadUInt64();

                entry.References = br.ReadUInt64();

                entry.EntryBlocks = new EntryBlock[3];
                for (int j = 0; j < entry.EntryBlocks.Length; j++)
                {
                    entry.EntryBlocks[j]            = new EntryBlock();
                    entry.EntryBlocks[j].Compressed = Flags.HasFlag(Flags.Compressed);
                }

                //uint[] blockUncompressedSizes = new uint[3];

                for (int j = 0; j < entry.EntryBlocks.Length; j++)
                {
                    uint uncompressedSize = br.ReadUInt32();
                    //blockUncompressedSizes[j] = uncompressedSize & ~(0xFU << 28);
                    entry.EntryBlocks[j].UncompressedSize      = uncompressedSize & ~(0xFU << 28);
                    entry.EntryBlocks[j].UncompressedAlignment = (uint)(1 << ((int)uncompressedSize >> 28));
                }

                //uint[] blockCompressedSizes = new uint[3];

                for (int j = 0; j < entry.EntryBlocks.Length; j++)
                {
                    //blockCompressedSizes[j] = br.ReadUInt32();
                    entry.EntryBlocks[j].CompressedSize = br.ReadUInt32();
                }

                for (int j = 0; j < entry.EntryBlocks.Length; j++)
                {
                    uint blockOffset = br.ReadUInt32();
                    long lastAddr    = br.BaseStream.Position;
                    br.BaseStream.Position = blockOffset + fileBlockOffsets[j];

                    EntryBlock block = entry.EntryBlocks[j];

                    bool compressed = Flags.HasFlag(Flags.Compressed);

                    //uint readSize = compressed ? blockCompressedSizes[j] : blockUncompressedSizes[j];
                    uint readSize = compressed ? entry.EntryBlocks[j].CompressedSize : entry.EntryBlocks[j].UncompressedSize;
                    if (readSize == 0)
                    {
                        block.RawData          = null;
                        br.BaseStream.Position = lastAddr;
                        continue;
                    }

                    block.RawData = br.ReadBytes((int)readSize);
                    //if (compressed)
                    //	block.Data = block.Data.Decompress((int)blockUncompressedSizes[j]);
                    br.BaseStream.Position = lastAddr;
                }

                entry.DependenciesListOffset = br.ReadInt32();
                entry.Type            = (EntryType)br.ReadInt32();
                entry.DependencyCount = br.ReadInt16();

                br.BaseStream.Position += 2; // Padding

                entry.Dirty = false;

                Entries.Add(entry);
            }

            if (Flags.HasFlag(Flags.HasResourceStringTable))
            {
                br.BaseStream.Position = RSTOffset;

                // TODO: Store only the debug info and not the full string
                ResourceStringTable = br.ReadCStr();

                ProcessRST(ResourceStringTable);
            }

            return(true);
        }
Beispiel #2
0
        public void Write(BinaryWriter bw)
        {
            bw.Write(BundleArchive.BND2Magic);
            bw.Write(this.Version);
            bw.Write((int)this.Platform);

            long rstOffset = bw.BaseStream.Position;

            bw.Write((int)0);

            bw.Write(this.Entries.Count);

            long idBlockOffsetPos = bw.BaseStream.Position;

            bw.Write((int)0);

            long[] fileBlockOffsetsPos = new long[3];

            for (int i = 0; i < fileBlockOffsetsPos.Length; i++)
            {
                fileBlockOffsetsPos[i]  = bw.BaseStream.Position;
                bw.BaseStream.Position += 4;
            }

            bw.Write((int)this.Flags);

            bw.Align(16);

            long currentOffset = bw.BaseStream.Position;

            bw.BaseStream.Position = rstOffset;
            bw.Write((uint)currentOffset);
            bw.BaseStream.Position = currentOffset;

            if (this.Flags.HasFlag(Flags.HasResourceStringTable))
            {
                // TODO: Rebuild RST from DebugInfo
                bw.WriteCStr(this.ResourceStringTable);

                bw.Align(16);
            }

            // ID Block
            currentOffset = bw.BaseStream.Position;
            bw.Seek((int)idBlockOffsetPos, SeekOrigin.Begin);
            bw.Write((int)currentOffset);
            bw.Seek((int)currentOffset, SeekOrigin.Begin);

            List <long[]> entryDataPointerPos = new List <long[]>();

            List <byte[][]> compressedBlocks = new List <byte[][]>();

            for (int i = 0; i < this.Entries.Count; i++)
            {
                BundleEntry entry = this.Entries[i];

                compressedBlocks.Add(new byte[3][]);

                bw.Write(entry.ID);
                bw.Write(entry.References);

                for (int j = 0; j < entry.EntryBlocks.Length; j++)
                {
                    EntryBlock entryBlock       = entry.EntryBlocks[j];
                    uint       uncompressedSize = 0;
                    if (entryBlock.Data != null)
                    {
                        uncompressedSize = (uint)entryBlock.Data.Length;
                    }
                    //self.Write((entryBlock.UncompressedAlignment << 28) | uncompressedSize);
                    bw.Write((uint)(uncompressedSize | (BitScan.BitScanReverse(entryBlock.UncompressedAlignment) << 28)));
                }

                for (int j = 0; j < entry.EntryBlocks.Length; j++)
                {
                    EntryBlock entryBlock = entry.EntryBlocks[j];
                    if (entryBlock.Data == null)
                    {
                        bw.Write((uint)0);
                    }
                    else
                    {
                        compressedBlocks[i][j] = entryBlock.Data.Compress();
                        bw.Write(compressedBlocks[i][j].Length);
                    }
                }

                entryDataPointerPos.Add(new long[3]);
                for (int j = 0; j < entryDataPointerPos[i].Length; j++)
                {
                    entryDataPointerPos[i][j] = bw.BaseStream.Position;
                    bw.BaseStream.Position   += 4;
                }

                bw.Write(entry.DependenciesListOffset);
                bw.Write((int)entry.Type);
                bw.Write(entry.DependencyCount);

                bw.BaseStream.Position += 2;                 // Padding
            }

            // Data Block
            for (int i = 0; i < 3; i++)
            {
                long blockStart = bw.BaseStream.Position;
                bw.BaseStream.Position = fileBlockOffsetsPos[i];
                bw.Write((uint)blockStart);
                bw.BaseStream.Position = blockStart;

                for (int j = 0; j < this.Entries.Count; j++)
                {
                    BundleEntry entry      = this.Entries[j];
                    EntryBlock  entryBlock = entry.EntryBlocks[i];
                    bool        compressed = this.Flags.HasFlag(Flags.Compressed);
                    uint        size       = compressed ? (compressedBlocks[j][i] == null ? 0 : (uint)compressedBlocks[j][i].Length) : (uint)entryBlock.Data.Length;

                    if (size > 0)
                    {
                        long pos = bw.BaseStream.Position;
                        bw.BaseStream.Position = entryDataPointerPos[j][i];
                        bw.Write((uint)(pos - blockStart));
                        bw.BaseStream.Position = pos;

                        if (compressed)
                        {
                            bw.Write(compressedBlocks[j][i]);
                        }
                        else
                        {
                            bw.Write(entryBlock.Data);
                        }

                        bw.Align((i != 0 && j != this.Entries.Count - 1) ? (byte)0x80 : (byte)16);
                    }
                }

                if (i != 2)
                {
                    bw.Align(0x80);
                }
            }
        }
Beispiel #3
0
        private bool ReadBND1(BinaryReader2 br)
        {
            br.BigEndian = true;

            // Version number?
            br.ReadUInt32();

            uint entryCount = br.ReadUInt32();

            uint[] dataBlockSizes = new uint[5];
            for (int i = 0; i < dataBlockSizes.Length; i++)
            {
                dataBlockSizes[i]       = br.ReadUInt32();
                br.BaseStream.Position += 4;                 // Padding
            }

            br.BaseStream.Position += 0x14;             // Unknown Data

            uint idListOffset  = br.ReadUInt32();
            uint idTableOffset = br.ReadUInt32();

            br.ReadUInt32();                // dependency block
            br.ReadUInt32();                // start of data block

            Platform = BundlePlatform.X360; // Xbox only for now
            br.ReadUInt32();                // might be platform (2 being X360)

            uint compressed = br.ReadUInt32();

            if (compressed != 0)
            {
                Flags = Flags.Compressed;                 // TODO
            }
            else
            {
                Flags = 0;
            }

            br.ReadUInt32();             // unknown purpose sometimes the same as entryCount

            uint uncompressedInfoOffset = br.ReadUInt32();

            br.ReadUInt32();             // main memory alignment
            br.ReadUInt32();             // graphics memory alignment

            Entries.Clear();

            br.BaseStream.Position = idListOffset;

            List <ulong> resourceIds = new List <ulong>();

            for (int i = 0; i < entryCount; i++)
            {
                resourceIds.Add(br.ReadUInt64());
            }

            br.BaseStream.Position = idTableOffset;

            foreach (ulong resourceId in resourceIds)
            {
                BundleEntry entry = new BundleEntry(this);
                entry.EntryBlocks = new EntryBlock[3];
                entry.ID          = resourceId;

                br.ReadUInt32();                 // unknown mem stuff

                entry.DependenciesListOffset = br.ReadInt32();
                entry.Type = (EntryType)br.ReadUInt32();

                //uint[] sizes = new uint[2];

                if (compressed != 0)
                {
                    //sizes[0] = br.ReadUInt32();
                    entry.EntryBlocks[0]                = new EntryBlock();
                    entry.EntryBlocks[0].Compressed     = true;
                    entry.EntryBlocks[0].CompressedSize = br.ReadUInt32();
                    br.ReadUInt32();                     // Alignment value, should be 1
                    br.ReadUInt32();                     // other blocks. Maybe used but I'm ignoring it.
                    br.ReadUInt32();                     // Alignment value, should be 1
                    //sizes[1] = br.ReadUInt32();
                    entry.EntryBlocks[1]                = new EntryBlock();
                    entry.EntryBlocks[1].Compressed     = true;
                    entry.EntryBlocks[1].CompressedSize = br.ReadUInt32();
                    br.ReadUInt32();                     // Alignment value, should be 1
                    br.ReadUInt32();                     // other blocks. Maybe used but I'm ignoring it.
                    br.ReadUInt32();                     // Alignment value, should be 1
                    br.ReadUInt32();                     // other blocks. Maybe used but I'm ignoring it.
                    br.ReadUInt32();                     // Alignment value, should be 1
                }
                else
                {
                    //sizes[0] = br.ReadUInt32();
                    entry.EntryBlocks[0]                       = new EntryBlock();
                    entry.EntryBlocks[0].Compressed            = false;
                    entry.EntryBlocks[0].UncompressedSize      = br.ReadUInt32();
                    entry.EntryBlocks[0].UncompressedAlignment = br.ReadUInt32();
                    br.ReadUInt32();                     // other blocks. Maybe used but I'm ignoring it.
                    br.ReadUInt32();                     // Alignment value
                    //sizes[1] = br.ReadUInt32();
                    entry.EntryBlocks[1]                       = new EntryBlock();
                    entry.EntryBlocks[1].Compressed            = false;
                    entry.EntryBlocks[1].UncompressedSize      = br.ReadUInt32();
                    entry.EntryBlocks[1].UncompressedAlignment = br.ReadUInt32();
                    br.ReadUInt32();                     // other blocks. Maybe used but I'm ignoring it.
                    br.ReadUInt32();                     // Alignment value
                    br.ReadUInt32();                     // other blocks. Maybe used but I'm ignoring it.
                    br.ReadUInt32();                     // Alignment value
                }

                uint dataBlockStartOffset = 0;
                for (int j = 0; j < dataBlockSizes.Length; j++)
                {
                    if (j > 0)
                    {
                        dataBlockStartOffset += dataBlockSizes[j - 1];
                    }

                    uint readOffset = br.ReadUInt32() + dataBlockStartOffset;
                    br.ReadUInt32();                     // 1

                    if (j != 0 && j != 2)
                    {
                        continue;                         // Not supporting blocks 2, 4 and 5 right now.
                    }
                    int mappedBlock = j;
                    if (j == 2)
                    {
                        mappedBlock = 1;
                    }

                    if (entry.EntryBlocks[mappedBlock] == null)
                    {
                        entry.EntryBlocks[mappedBlock] = new EntryBlock();
                    }
                    EntryBlock entryBlock = entry.EntryBlocks[mappedBlock];

                    //uint readSize = sizes[mappedBlock];
                    uint readSize = compressed != 0 ? entryBlock.CompressedSize : entryBlock.UncompressedSize;
                    if (readSize == 0)
                    {
                        entryBlock.RawData = null;
                        continue;
                    }

                    long pos = br.BaseStream.Position;
                    br.BaseStream.Position = readOffset;

                    entryBlock.RawData = br.ReadBytes((int)readSize);

                    br.BaseStream.Position = pos;
                }

                br.BaseStream.Position += 0x14;                 // unknown mem stuff

                Entries.Add(entry);
            }

            if (compressed != 0)
            {
                br.BaseStream.Position = uncompressedInfoOffset;
                for (int i = 0; i < Entries.Count; i++)
                {
                    BundleEntry entry = Entries[i];

                    //uint[] sizes = new uint[2];

                    //sizes[0] = br.ReadUInt32();
                    entry.EntryBlocks[0].UncompressedSize      = br.ReadUInt32();
                    entry.EntryBlocks[0].UncompressedAlignment = br.ReadUInt32();
                    br.ReadUInt32();                     // other blocks. Maybe used but I'm ignoring it.
                    br.ReadUInt32();                     // Alignment value
                    //sizes[1] = br.ReadUInt32();
                    entry.EntryBlocks[1].UncompressedSize      = br.ReadUInt32();
                    entry.EntryBlocks[1].UncompressedAlignment = br.ReadUInt32();
                    br.ReadUInt32();                     // other blocks. Maybe used but I'm ignoring it.
                    br.ReadUInt32();                     // Alignment value
                    br.ReadUInt32();                     // other blocks. Maybe used but I'm ignoring it.
                    br.ReadUInt32();                     // Alignment value

                    //for (int j = 0; j < 2; j++)
                    //{
                    //	EntryBlock entryBlock = entry.EntryBlocks[j];
                    //	if (sizes[j] > 0)
                    //		entryBlock.Data = entryBlock.Data.Decompress((int)sizes[j]);
                    //}
                }
            }

            for (int i = 0; i < Entries.Count; i++)
            {
                BundleEntry entry     = Entries[i];
                uint        depOffset = (uint)entry.DependenciesListOffset;
                if (depOffset == 0)
                {
                    continue;
                }

                br.BaseStream.Position = depOffset;

                entry.DependencyCount = (short)br.ReadUInt32();
                if (br.ReadUInt32() != 0)
                {
                    return(false);
                }

                for (int j = 0; j < entry.DependencyCount; j++)
                {
                    Dependency dep = new Dependency();
                    dep.ID = br.ReadUInt64();
                    dep.EntryPointerOffset = br.ReadUInt32();

                    br.ReadUInt32();                     // Skip

                    entry.Dependencies.Add(dep);
                }
            }

            BundleEntry rst = GetEntryByID(0xC039284A);

            if (rst == null)
            {
                return(true);
            }

            BinaryReader2 br2 = new BinaryReader2(rst.MakeStream());

            br2.BigEndian = false;

            // TODO: Store only the debug info and not the full string
            ResourceStringTable = br2.ReadLenString();

            br2.Close();

            // Cover Criterion's broken XML writer.
            if (ResourceStringTable.StartsWith("</ResourceStringTable>"))
            {
                ResourceStringTable = ResourceStringTable.Remove(1, 1);
            }
            string badLine = "</ResourceStringTable>\n\t";
            int    index   = ResourceStringTable.IndexOf(badLine);

            if (index > -1)
            {
                ResourceStringTable = ResourceStringTable.Remove(index, badLine.Length);
            }

            ProcessRST(ResourceStringTable);

            Entries.Remove(rst);

            return(true);
        }