/// <summary> /// Read and preprocess header information /// </summary> private void ReadPreprocess() { char[] gtag; #region Endian Switch ushort us_temp = InputStream.ReadUInt16(); if (us_temp == HeaderEndian) { SetEndianState(IO.EndianState.Little); } else if (us_temp == HeaderEndianSwap) { SetEndianState(IO.EndianState.Big); } else { throw new Debug.ExceptionLog("File: Invalid switch! {0:X4}", us_temp); } #endregion #region Version us_temp = InputStream.ReadUInt16(); Debug.Assert.If(us_temp == HeaderVersion, "File: mismatching file version! [{0}, !{1}", HeaderVersion, us_temp); #endregion #region Signature gtag = InputStream.ReadTag(); Debug.Assert.If(TagGroup.Test(gtag, (char[])IO.TagGroups.BlamLib), "File: invalid signature! [{0} !{1}]", IO.TagGroups.BlamLib.TagToString(), new string(gtag)); #endregion flags.Reset((uint)(InputStream.ReadUInt16() << 16) | flags); #region Data Version us_temp = InputStream.ReadUInt16(); Debug.Assert.If(us_temp == data.Attribute.Version, "File: mismatching data version! [{0}, !{1}", data.Attribute.Version, us_temp); #endregion #region Data Signature gtag = InputStream.ReadTag(); Debug.Assert.If(TagGroup.Test(gtag, (char[])data.GroupTag), "File: invalid data signature! [{0} !{1}]", data.GroupTag.TagToString(), new string(gtag)); #endregion #region Data Directories InputStream.ReadInt32(); InputStream.ReadInt32(); #endregion #region Data InputStream.ReadInt32(); int data_offset = InputStream.ReadInt32(); #endregion Debug.Assert.If(InputStream.Position == HeaderSize, "File: Update header size! [{0}, !{1}]", HeaderSize, InputStream.Position); InputStream.Seek(data_offset); }
void InitializeBspTags(IO.EndianReader s, Blam.CacheFile cache) { // Seek to the scenario's scenario_structure_bsps_block tag_block field s.Seek(items[0].Offset + 1444, System.IO.SeekOrigin.Begin); bspTags = new Item[s.ReadInt32()]; uint sbsp_offset = s.ReadPointer(); // Seek to the scenario_structure_bsps_block definitions s.Seek(sbsp_offset, System.IO.SeekOrigin.Begin); DatumIndex di = new DatumIndex(); CacheItemBase item = null; // Process each definition's runtime data for (int x = 0; x < bspTags.Length; x++) { s.Seek(28, System.IO.SeekOrigin.Current); di.Read(s); item = items[di.Index]; bspTags[x] = item as CacheItemBase; // Seek back to the beginning of the definition so the following stream code works s.Seek(-Halo1.Tags.scenario_structure_bsps_block.kSizeOf, System.IO.SeekOrigin.Current); // We're actually selectively reading scenario_structure_bsps_block fields here // The offset actually points to the bsp header, and the bsp comes after that header item.Offset = s.ReadInt32() + Halo1.Tags.scenario_structure_bsps_header.kSizeOf; item.Size = s.ReadInt32(); cache.BspAddressMasks.Add(s.ReadUInt32() - (uint)item.Offset); // won't count the header item.BspIndex = bspCount++; // Seek to the end of this definition, and thus, the start of the next definition s.Seek(20, System.IO.SeekOrigin.Current); } }
/// <summary> /// Process the reference data from a stream /// </summary> /// <param name="s">Stream</param> /// <exception cref="Exceptions.InvalidTagBlock"></exception> public override void ReadHeader(IO.EndianReader s) { headerOffset = s.PositionUnsigned; // nifty for debugging Resize(s.ReadInt32()); // element count s.ReadInt32(); // elements s.ReadInt32(); // definition }
public void ReadAlpha(IO.EndianReader s) { GroupTagInt = s.ReadUInt32(); groupTag = Program.Halo2.Manager.TagGroupFind(TagInterface.TagGroup.FromUInt(GroupTagInt)); IO.ByteSwap.SwapUDWord(ref GroupTagInt); s.ReadUInt32(); s.ReadUInt32(); datum.Read(s); tagNameOffset = s.ReadUInt32(); address = s.ReadUInt32(); //offset = (int)(address - s.BaseAddress); size = s.ReadInt32(); s.ReadInt32(); }
private bool DecompressUIFileToDisk(byte[] eraFileEntryBuffer, string fullPath) { bool success = false; using (var ms = new System.IO.MemoryStream(eraFileEntryBuffer, false)) using (var s = new IO.EndianReader(ms, Shell.EndianFormat.Little)) { uint buffer_signature; if (ResourceUtils.IsScaleformBuffer(s, out buffer_signature)) { int decompressed_size = s.ReadInt32(); int compressed_size = (int)(ms.Length - ms.Position); byte[] decompressed_data = ResourceUtils.DecompressScaleform(eraFileEntryBuffer, decompressed_size); using (var fs = System.IO.File.Create(fullPath + ".bin")) { fs.Write(decompressed_data, 0, decompressed_data.Length); } success = true; } } return(success); }
/// <summary> /// Process the reference data from a tag stream /// </summary> /// <param name="ts"></param> /// <exception cref="Exceptions.InvalidTagBlock"></exception> public override void ReadHeader(IO.ITagStream ts) { IO.EndianReader s = ts.GetInputStream(); headerOffset = s.PositionUnsigned; // nifty for debugging try { Resize(s.ReadInt32()); // element count relativeOffset = s.ReadPointer(); // elements s.ReadInt32(); // definition } catch (Exception ex) { throw new Exceptions.InvalidTagBlock(ex, base.headerOffset, uint.MaxValue, this.owner, ts); } }
/// <summary></summary> /// <param name="offsets">Buffer containing the offsets of the string values in <paramref name="buffer"/></param> /// <param name="buffer">Buffer containing the string values</param> /// <param name="is_packed">If true, reads the strings as null terminated strings, else as 128 character strings</param> /// <remarks> /// Doesn't actually populate the collection from a debug stream. Instead it seeks the streams to directly after this set's /// data, assuming the streams have data which matches this collection. Also assumes the streams aren't filled with just static /// strings, but also contain dynamic string data as well (or else the seek operations this performs will exception) /// </remarks> public void FromDebugStream(IO.EndianReader offsets, IO.EndianReader buffer, bool is_packed) { int last_offset = sizeof(uint) * Count; offsets.Seek(last_offset); int last_offset_buffer = offsets.ReadInt32(); buffer.Seek(last_offset_buffer); }
/// <summary>Read the character count for the string values from a stream</summary> /// <param name="s"></param> /// <remarks> /// Obviously, this needs to be called before <see cref="ReadStrings(IO.EndianReader s)"/> /// if you're going to even use this (due to performance reasons or due to the storage definition) /// </remarks> public void ReadStringCharacterLengths(IO.EndianReader s) { Contract.Requires(s != null); ioStringLengths = new int[Count]; for (int x = 0; x < ioStringLengths.Length; x++) { ioStringLengths[x] = s.ReadInt32(); } }
public void ReadChildren(IO.EndianReader s) { if (mChildrenOffset.IsInvalidHandle) { return; } s.Seek((long)mChildrenOffset); for (int x = 0; x < ChildrenIndices.Capacity; x++) { ChildrenIndices.Add(s.ReadInt32()); } }
/// <summary>Read the header for the pool from a stream to properly initialize this pool's configuration, counts, etc</summary> /// <param name="s"></param> public void ReadHeader(IO.EndianReader s) { Contract.Requires(s != null); // #TODO: test to see if the config is a built-in, else we could overwrite an existing config // Configuration.Read(s); int count = s.ReadInt32(); Size = s.ReadUInt32(); InitializeCollections(count); for (int x = 0; x < mReferences.Count; x++) { mReferences[x] = new Values.PtrHandle(Settings.AddressSize); } }
public void Parse() { InputStream.ReadTag(); // Ext tag header InputStream.ReadInt32(); // Flags InputStream.ReadTag(); // Stubbs InputStream.ReadTag(); // Halo1 InputStream.ReadTag(); // Halo2 InputStream.ReadTag(); // Halo3 InputStream.ReadInt16(); // IDs count InputStream.ReadInt16(); // Blocks count Parse(commands); }
public void Build(IO.EndianReader stream, int offset, int count, int total_size) { stream.Seek(offset); int[] indicies = new int[count]; for (int x = 0; x < indicies.Length; x++) { indicies[x] = stream.ReadInt32(); } ValueLengths = new byte[count]; for (int x = count - 1, prev_offset = total_size; x >= 0; x--) { ValueLengths[x] = (byte)((prev_offset - indicies[x]) - 1); prev_offset = indicies[x]; } Count = count; }
public override void Read(IO.EndianReader s) { BlamVersion ver = (BlamVersion)s.ReadUInt16(); // HACK: this is a hack if (ver == BlamVersion.Halo1) { ver = BlamVersion.Halo1_CE; } Debug.Assert.If(ver == engine, "Engine version mismatch: expected {0}, but got {1}", engine, ver); s.Seek(2, System.IO.SeekOrigin.Current); #region FileNames int file_count = s.ReadInt32(); for (int x = 0; x < file_count; x++) { files.Add(s.ReadCString()); } #endregion }
byte[] ReadStrPascal(IO.EndianReader s, out int actualCount) { actualCount = TypeExtensions.kNone; int length; // One would think that the length prefix would be of the same endian as the stream, but just in case... using (s.BeginEndianSwitch(mStorage.ByteOrder)) switch (mStorage.LengthPrefix) { case StringStorageLengthPrefix.Int7: length = s.Read7BitEncodedInt(); break; case StringStorageLengthPrefix.Int8: length = s.ReadByte(); break; case StringStorageLengthPrefix.Int16: length = s.ReadInt16(); break; case StringStorageLengthPrefix.Int32: length = s.ReadInt32(); break; default: throw new Debug.UnreachableException(); } return(s.ReadBytes(GetMaxCleanByteCount(length))); }
public override void Read(IO.EndianReader s) { GroupTagInt = s.ReadUInt32(); groupTag = Program.Halo2.Manager.TagGroupFind(TagInterface.TagGroup.FromUInt(GroupTagInt)); IO.ByteSwap.SwapUDWord(ref GroupTagInt); datum.Read(s); address = s.ReadUInt32(); if (GroupTagInt == uint.MaxValue) { location = CacheIndex.ItemLocation.Unknown; } else if (address == 0) { location = CacheIndex.ItemLocation.External; } else { offset = (int)(address - s.BaseAddress); } size = s.ReadInt32(); }
public static bool DetermineEngineFromMapFile(string fileName, out string engine, out string mapName) { // Clear our out values engine = ""; mapName = ""; // Check the file exists if (System.IO.File.Exists(fileName) == false) { // Output error and return false Console.WriteLine("Error file \"{0}\" not found!", fileName); return(false); } // Create a new endian reader IO.EndianReader br = new IO.EndianReader(IO.Endianness.Little, new System.IO.FileStream(fileName, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read)); // Check for the 'head' or 'daeh' identifier bool result = false; int headMagic = br.ReadInt32(); if (headMagic == /* 'head' */ 0x64616568) { // Big endian map, ex halo 3 } else if (headMagic == /* 'daeh' */ 0x68656164) { // Check engine version int engineVersion = br.ReadInt32(); if (engineVersion == 8) { // Halo 2 map, but we need to check the build date to determine which version of halo 2 br.BaseStream.Position = 288; if (br.ReadInt32() == 0) { // There is no build date at 288, advance to 300 and check if it is a halo 2 vista map br.BaseStream.Position = 300; } else { // Parse the whole build date so we can check it br.BaseStream.Position = 288; string buildDate = new string(br.ReadChars(32)).Replace("\0", ""); // Check if the map is a final or beta build map if (buildDate.Equals("02.09.27.09809") == true) { // It's a final halo 2 xbox map engine = "Halo2Xbox"; // Read the map name br.BaseStream.Position = 408; mapName = new string(br.ReadChars(32)).Replace("\0", ""); // Done result = true; } else if (buildDate.Equals("02.06.28.07902") == true) { // It's a halo 2 beta map engine = "Halo2Beta"; // Read the map name br.BaseStream.Position = 408; mapName = new string(br.ReadChars(32)).Replace("\0", ""); // Done result = true; } } } } // Close the reader br.Close(); // Done return(result); }
public void Read(IO.EndianReader s) { var context = s.UserData as XmbFileContext; using (s.ReadSignatureWithByteSwapSupport(kSignature)) { if (context.PointerSize == Shell.ProcessorSize.x64) { // #HACK to deal with xmb files which weren't updated with new tools if (s.ByteOrder == Shell.EndianFormat.Big) { context.PointerSize = Shell.ProcessorSize.x32; } } s.VirtualAddressTranslationInitialize(context.PointerSize); Values.PtrHandle elements_offset_pos; if (context.PointerSize == Shell.ProcessorSize.x64) { s.Pad32(); } #region Initialize elements { int count = s.ReadInt32(); if (context.PointerSize == Shell.ProcessorSize.x64) { s.Pad32(); } s.ReadVirtualAddress(out elements_offset_pos); mElements = new List <Element>(count); } #endregion #region Initialize and read pool { int size = s.ReadInt32(); if (context.PointerSize == Shell.ProcessorSize.x64) { s.Pad32(); } Values.PtrHandle pool_offset_pos = s.ReadVirtualAddress(); s.Seek((long)pool_offset_pos); byte[] buffer = s.ReadBytes(size); mPool = new XmbVariantMemoryPool(buffer, s.ByteOrder); } #endregion if (context.PointerSize == Shell.ProcessorSize.x64) { s.Pad64(); } s.Seek((long)elements_offset_pos); for (int x = 0; x < mElements.Capacity; x++) { var e = new Element(); mElements.Add(e); e.Index = x; e.Read(this, context, s); } foreach (var e in mElements) { e.ReadAttributes(this, s); e.ReadChildren(s); } } }
void ReadInt(IO.EndianReader s) { switch (TypeDesc.SizeOf) { case sizeof(byte): { if (ArrayLength == 1) { Int = TypeDesc.IsUnsigned ? (uint)s.ReadByte() : (uint)s.ReadSByte(); } else { if (TypeDesc.IsUnsigned) { var array = s.ReadBytes(ArrayLength); OpaqueArrayRef = array; } else { var array = new sbyte[ArrayLength]; for (int x = 0; x < array.Length; x++) { array[x] = s.ReadSByte(); } OpaqueArrayRef = array; } } } break; case sizeof(ushort): { if (ArrayLength == 1) { Int = TypeDesc.IsUnsigned ? (uint)s.ReadUInt16() : (uint)s.ReadInt16(); } else { if (TypeDesc.IsUnsigned) { var array = new ushort[ArrayLength]; for (int x = 0; x < array.Length; x++) { array[x] = s.ReadUInt16(); } OpaqueArrayRef = array; } else { var array = new short[ArrayLength]; for (int x = 0; x < array.Length; x++) { array[x] = s.ReadInt16(); } OpaqueArrayRef = array; } } } break; case sizeof(uint): { if (ArrayLength == 1) { Int = TypeDesc.IsUnsigned ? (uint)s.ReadUInt32() : (uint)s.ReadInt32(); } else { if (TypeDesc.IsUnsigned) { var array = new uint[ArrayLength]; for (int x = 0; x < array.Length; x++) { array[x] = s.ReadUInt32(); } OpaqueArrayRef = array; } else { var array = new int[ArrayLength]; for (int x = 0; x < array.Length; x++) { array[x] = s.ReadInt32(); } OpaqueArrayRef = array; } } } break; case sizeof(ulong): { if (ArrayLength == 1) { Int64 = TypeDesc.IsUnsigned ? (ulong)s.ReadUInt64() : (ulong)s.ReadInt64(); } else { if (TypeDesc.IsUnsigned) { var array = new ulong[ArrayLength]; for (int x = 0; x < array.Length; x++) { array[x] = s.ReadUInt64(); } OpaqueArrayRef = array; } else { var array = new long[ArrayLength]; for (int x = 0; x < array.Length; x++) { array[x] = s.ReadInt64(); } OpaqueArrayRef = array; } } } break; default: throw new KSoft.Debug.UnreachableException(TypeDesc.SizeOf.ToString()); } }
public override void Read(IO.EndianReader s) { int k_local_sizeof = Blam.CacheFile.ValidateHeader(s, kSizeOf); s.Seek(4); version = s.ReadInt32(); if (version != 11 && version != 12) { throw new InvalidCacheFileException(s.FileName); } fileLength = s.ReadInt32(); s.ReadInt32(); tagIndexAddress = s.ReadUInt32(); memoryBufferOffset = s.ReadInt32(); memoryBufferSize = s.ReadInt32(); sourceFile = s.ReadAsciiString(256); build = s.ReadTagString(); cacheType = (Blam.CacheType)s.ReadInt16(); sharedType = (Cache.SharedType)s.ReadInt16(); s.ReadBool(); s.ReadBool(); // false if it belongs to a untracked build s.ReadBool(); // PATCH: this is '3' in main menu patches s.ReadByte(); // appears to be an ODST-only field s.ReadInt32(); s.ReadInt32(); s.ReadInt32(); s.ReadInt32(); s.ReadInt32(); #region string id table // 0x158 stringIdsCount = s.ReadInt32(); stringIdsBufferSize = s.ReadInt32(); stringIdIndicesOffset = s.ReadInt32(); stringIdsBufferOffset = s.ReadInt32(); #endregion #region filetimes? // pretty sure this is a flags field // used to tell which of the following 64bit values // are used. Damn sure this are FILETIME structures, but // hex workshop doesn't like them so I can't be for sure... needsShared = s.ReadInt32() != 0; // just a little 'hack' if you will. if zero, the map is self reliant, so no worries Filetime.dwHighDateTime = s.ReadInt32(); Filetime.dwLowDateTime = s.ReadInt32(); if (s.ReadInt32() != 0) { flags.Add(Halo3.CacheHeaderFlags.DependsOnMainMenu); } s.ReadInt32(); if (s.ReadInt32() != 0) { flags.Add(Halo3.CacheHeaderFlags.DependsOnShared); } s.ReadInt32(); if (s.ReadInt32() != 0) { flags.Add(Halo3.CacheHeaderFlags.DependsOnCampaign); } s.ReadInt32(); #endregion name = s.ReadTagString(); s.ReadInt32(); scenarioPath = s.ReadAsciiString(256); // PATCH: this is -1 in main menu patches s.ReadInt32(); // minor version, normally not used #region tag paths tagNamesCount = s.ReadInt32(); tagNamesBufferOffset = s.ReadInt32(); // cstring buffer tagNamesBufferSize = s.ReadInt32(); // cstring buffer total size in bytes tagNameIndicesOffset = s.ReadInt32(); TagsUnknown1Count = s.ReadInt32(); TagsUnknown1Offset = s.ReadInt32(); // PATCH: zero for non-patch data TagsUnknown2Count = s.ReadInt32(); TagsUnknown2Offset = s.ReadInt32(); #endregion checksum = s.ReadUInt32(); // 0x2D4 s.Seek(32, System.IO.SeekOrigin.Current); // these bytes are always the same. first 8 changed in Halo4 baseAddress = s.ReadUInt32(); // expected base address xdkVersion = s.ReadInt32(); // xdk version #region memory partitions // 0x300 // memory partitions memoryPartitions = new Partition[6]; memoryPartitions[0].BaseAddress = s.ReadUInt32(); // cache resource buffer memoryPartitions[0].Size = s.ReadInt32(); // readonly memoryPartitions[1].BaseAddress = s.ReadUInt32(); // cache gestalt resource buffer memoryPartitions[1].Size = s.ReadInt32(); memoryPartitions[2].BaseAddress = s.ReadUInt32(); // global tags buffer (cache sound tags likes this memory space too) memoryPartitions[2].Size = s.ReadInt32(); memoryPartitions[3].BaseAddress = s.ReadUInt32(); // shared tag blocks? (havok data likes this memory space too) memoryPartitions[3].Size = s.ReadInt32(); memoryPartitions[4].BaseAddress = s.ReadUInt32(); // address memoryPartitions[4].Size = s.ReadInt32(); // readonly memoryPartitions[5].BaseAddress = s.ReadUInt32(); // map tags buffer memoryPartitions[5].Size = s.ReadInt32(); #endregion int count = s.ReadInt32(); s.Seek(4 + 8, System.IO.SeekOrigin.Current); // these bytes are always the same // if there is a hash in the header, this is the ONLY // place where it can be s.Seek(20 /*SHA1*/ + 40 + 256 /*RSA*/, System.IO.SeekOrigin.Current); // ??? // 0x47C cacheInterop.Read(s); cacheInterop.PostprocessForCacheRead(k_local_sizeof); s.Seek(16, System.IO.SeekOrigin.Current); // GUID?, these bytes are always the same. ODST is different from Halo 3 // PATCH: main menu patches have a single entry (where stock has none) #region blah 1 // 0x4AC // campaign has a shit load of these // but shared doesn't nor mainmenu // I compared the sc110 french and english and both have the SAME counts and element data. So // I don't think this is a hash or something. At least, if it is, it's not runtime relative so // nothing we have to worry about s.ReadInt16(); // I've only seen this be two different values (besides zero). count = s.ReadInt16(); // I think the above specifies the size of the structure this count represents? s.ReadInt32(); // seems to always be zero CompressionGuid = new Guid(s.ReadBytes(16)); s.Seek(count * 28, System.IO.SeekOrigin.Current); // seek past the elements // dword // long // buffer [0x14] (probably a sha1 hash) s.Seek((3600 - count) * 28, System.IO.SeekOrigin.Current); // seek past the unused elements #endregion // PATCH: main menu patches have a count of '1' but doesn't appear to have #region blah 2 s.Seek(sizeof(uint) + 0x4E9C, System.IO.SeekOrigin.Current); #if false { // 0x18E94 // going to punt and just assume there is a max count of 13 of these possible // maybe related to bsp\'zones'? const int blah2_sizeof = 0x60C; count = (int)(s.ReadUInt32() >> 24); // did someone forget to f*****g byte swap something? s.Seek(count * blah2_sizeof, System.IO.SeekOrigin.Current); // seek past the elements s.Seek((13 - count) * blah2_sizeof, System.IO.SeekOrigin.Current); // seek past the unused elements } #endif #endregion s.Seek(712 + sizeof(uint), System.IO.SeekOrigin.Current); ReadPostprocessForInterop(); if (!cacheInterop.IsNull) { int debug_mask = (int)cacheInterop[CacheSectionType.Debug].AddressMask; if (TagsUnknown1Offset != 0) { TagsUnknown1Offset -= debug_mask; } if (TagsUnknown2Offset != 0) { TagsUnknown2Offset -= debug_mask; } } ReadPostprocessForBaseAddresses(s); }
/// <summary> /// Stream map id from a buffer /// </summary> /// <param name="input"></param> public void Read(IO.EndianReader input) { Index = input.ReadInt32(); Id = input.ReadInt32(); }