Exemplo n.º 1
0
 /// <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();
     }
 }
        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);
        }