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); }
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); }
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); }
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); }
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); }