Пример #1
0
        public static EntryType GetEntryType(string path, uint id, bool console = false)
        {
            DebugTimer timer  = DebugTimer.Start("GetEntryType");
            EntryType  result = EntryType.Invalid;

            Stream        s  = File.Open(path, FileMode.Open, FileAccess.Read);
            BinaryReader2 br = new BinaryReader2(s);

            if (!br.VerifyMagic(BND2Magic))
            {
                timer.StopLog();
                br.Close();
                s.Close();
                return(EntryType.Invalid);
            }

            br.BaseStream.Position += 4;

            int platformInt = br.ReadInt32();

            if (platformInt != 1)
            {
                platformInt = Util.ReverseBytes(platformInt);
            }
            BundlePlatform platform = (BundlePlatform)platformInt;

            br.BigEndian = platform == BundlePlatform.X360 || platform == BundlePlatform.PS3;

            br.BaseStream.Position = 0x10;
            int fileCount = br.ReadInt32();
            int metaStart = br.ReadInt32();

            br.BaseStream.Position = metaStart;

            for (int i = 0; i < fileCount; i++)
            {
                uint id2 = br.ReadUInt32();
                br.BaseStream.Position += 0x34;
                EntryType type = (EntryType)br.ReadUInt32();
                br.BaseStream.Position += 0x4;

                if (id2 == id)
                {
                    result = type;
                    break;
                }
            }

            br.Close();
            s.Close();

            timer.StopLog();

            return(result);
        }
Пример #2
0
        public static List <uint> GetEntryIDs(string path, bool console = false)
        {
            List <uint> result = new List <uint>();

            Stream        s  = File.Open(path, FileMode.Open, FileAccess.Read);
            BinaryReader2 br = new BinaryReader2(s);

            if (!br.VerifyMagic(BND2Magic))
            {
                br.Close();
                s.Close();
                return(null);
            }

            br.BaseStream.Position += 4;

            int platformInt = br.ReadInt32();

            if (platformInt != 1)
            {
                platformInt = Util.ReverseBytes(platformInt);
            }
            BundlePlatform platform = (BundlePlatform)platformInt;

            br.BigEndian = platform == BundlePlatform.X360 || platform == BundlePlatform.PS3;

            br.BaseStream.Position = 0x10;
            int fileCount = br.ReadInt32();
            int metaStart = br.ReadInt32();

            br.BaseStream.Position = metaStart;

            for (int i = 0; i < fileCount; i++)
            {
                uint id = br.ReadUInt32();
                br.BaseStream.Position += 0x3C;

                result.Add(id);
            }

            br.Close();
            s.Close();

            return(result);
        }
Пример #3
0
        public static List <EntryInfo> GetEntryInfos(string path, bool console = false)
        {
            List <EntryInfo> result = new List <EntryInfo>();

            Stream        s  = File.Open(path, FileMode.Open, FileAccess.Read);
            BinaryReader2 br = new BinaryReader2(s);

            if (!br.VerifyMagic(BND2Magic))
            {
                br.Close();
                s.Close();
                return(null);
            }

            br.BaseStream.Position += 4;

            int platformInt = br.ReadInt32();

            if (platformInt != 1)
            {
                platformInt = Util.ReverseBytes(platformInt);
            }
            BundlePlatform platform = (BundlePlatform)platformInt;

            br.BigEndian = platform == BundlePlatform.X360 || platform == BundlePlatform.PS3;

            br.BaseStream.Position = 0xC;
            uint rstOffset = br.ReadUInt32();
            int  fileCount = br.ReadInt32();
            int  metaStart = br.ReadInt32();

            br.BaseStream.Position += 0xC;
            Flags flags = (Flags)br.ReadInt32();

            Dictionary <ulong, DebugInfo> debugInfo = null;

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

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

                debugInfo = GetDebugInfoFromRST(rst);
            }

            br.BaseStream.Position = metaStart;

            for (int i = 0; i < fileCount; i++)
            {
                uint id = br.ReadUInt32();
                br.BaseStream.Position += 0x34;
                EntryType type = (EntryType)br.ReadUInt32();
                br.BaseStream.Position += 0x4;

                DebugInfo debug = default;

                if (debugInfo != null && debugInfo.ContainsKey(id))
                {
                    debug = debugInfo[id];
                }

                result.Add(new EntryInfo(id, type, path, debug));
            }

            br.Close();
            s.Close();

            return(result);
        }
Пример #4
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);
        }
Пример #5
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);
        }