public override void Read(IO.EndianReader s) { int k_local_sizeof = Blam.CacheFile.ValidateHeader(s, kSizeOfBeta, 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(); 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); 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(); #endregion checksum = s.ReadUInt32(); // 0x2C4 s.Seek(32, System.IO.SeekOrigin.Current); // these bytes are always the same baseAddress = s.ReadUInt32(); // expected base address xdkVersion = s.ReadInt32(); // xdk version #region memory partitions // 0x2F0 // 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); // ??? // 0x46C 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 #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((320 - count) * 28, System.IO.SeekOrigin.Current); // seek past the unused elements #endregion // this shit has changed. f**k you. #region blah 2 #if false { // 0x27C4 // This on the other hand, sc110 french and english had MINOR differences. Those differences were in // DWORDs @ 0x4 and 0x8 // going to punt and just assume there is a max count of 10 of these possible // maybe related to bsp\'zones'? const int blah2_sizeof = 180; 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((10 - count) * blah2_sizeof, System.IO.SeekOrigin.Current); // seek past the unused elements } #endif #endregion //s.Seek(300 + sizeof(uint), System.IO.SeekOrigin.Current); // zero s.Seek(6200 + sizeof(uint), System.IO.SeekOrigin.Current); ReadPostprocessForInterop(); ReadPostprocessForBaseAddresses(s); }
/// <summary> /// Stream the field from a buffer /// </summary> /// <param name="input"></param> public override void Read(IO.EndianReader input) { if (StringType == StringType.Normal) Value = input.ReadTagString(); else if (StringType == StringType.Unicode) Value = input.ReadUnicodeString(Length); else if (StringType == StringType.Ascii) Value = input.ReadAsciiString(Length); else if (StringType == StringType.Halo1Profile) Value = input.ReadUnicodeString(12); else if (StringType == StringType.Halo2Profile) Value = input.ReadUnicodeString(16); else if (StringType == StringType.CString) Value = input.ReadCString(); }