Example #1
0
            void DisallowTags()
            {
                BlamLib.IO.EndianReader input = new BlamLib.IO.EndianReader(output.FileName);
                input.BaseAddress = Program.PeAddressMask;
                input.Seek(AddressOf.TagGroupDefinitions[Platform.Guerilla] - Program.PeAddressMask);

                uint[] offsets = new uint[Constants.StockTagGroupCount];
                for (int x = 0; x < offsets.Length; x++)
                {
                    offsets[x] = input.ReadPointer();
                }

                for (int x = 0; x < offsets.Length; x++)
                {
                    input.Seek(offsets[x]);
                    string name = Program.ReadCString(input.ReadPointer(), input);
                    if (IsDisallowedTag(name))
                    {
                        input.Seek(0x20, System.IO.SeekOrigin.Current);
                        output.Seek(input.Position - 2);
                        output.Write((short)1);
                        output.Seek(input.ReadPointer() + 0x14);
                        output.Write(0);
                        output.Write(0);
                        output.Write(0);
                    }
                }
                input.Close();
            }
        public static string ReadCString(uint offset, BlamLib.IO.EndianReader io)
        {
            if (offset == 0)
            {
                return(string.Empty);
            }

            uint pos = io.PositionUnsigned;

            io.Seek(offset);

            byte btchar  = 0;
            var  cstring = new System.Text.StringBuilder();

            do
            {
                btchar = io.ReadByte();
                if (btchar != 0)
                {
                    cstring.Append((char)btchar);
                }
            } while (btchar != 0);

            io.Seek(pos);

            return(cstring.ToString());
        }
Example #3
0
 public void Read(BlamLib.IO.EndianReader s)
 {
     s.Seek(4 + 4, System.IO.SeekOrigin.Current);
     Count.Read(s);
     Size.Read(s);
     OffsetReferences.Read(s);
     OffsetStrings.Read(s);
     s.Seek(1 + 3, System.IO.SeekOrigin.Current);
 }
 protected void ReadDependents(BlamLib.IO.EndianReader s)
 {
     DependentDatums = new DatumIndex[dependentTagsCount];
     s.Seek(dependentTagsOffset, System.IO.SeekOrigin.Begin);
     for (int x = 0; x < dependentTagsCount; x++)
     {
         s.Seek(sizeof(uint), System.IO.SeekOrigin.Current);                 // group tag
         DependentDatums[x].Read(s);
     }
 }
        public override void Read(BlamLib.IO.EndianReader s)
        {
            if (isLoaded)
            {
                return;
            }

            // goto the start if we're leaching off another cache's IO
            if (IsSharedReference)
            {
                s.Seek(0);
            }

            cacheHeader.Read(s);

            DetermineEngineVersion();

            // Shared caches can't be loaded from here
            if (cacheHeader.SharedType == Cache.SharedType.Shared ||
                cacheHeader.SharedType == Cache.SharedType.Campaign)
            {
                throw new SharedCacheAccessException();
            }

            TagIndexInitializeAndRead(s);

            isLoaded = true;
        }
 void ReadGroupTags(BlamLib.IO.EndianReader s)
 {
     groupTags = new Halo4.CacheItemGroupTag[groupTagsCount];
     s.Seek(groupTagsOffset, System.IO.SeekOrigin.Begin);
     for (int x = 0; x < groupTagsCount; x++)
     {
         (groupTags[x] = new Halo4.CacheItemGroupTag()).Read(s);
     }
 }
 void ReadGroupTags(BlamLib.IO.EndianReader s)
 {
     groupTags = CreateEngineItemGroupTags(groupTagsCount);
     s.Seek(groupTagsOffset, System.IO.SeekOrigin.Begin);
     for (int x = 0; x < groupTagsCount; x++)
     {
         (groupTags[x] = CreateEngineItemGroupTag()).Read(s);
     }
 }
 protected void ReadTagInstances(BlamLib.IO.EndianReader s)
 {
     items = new Cache.CacheItemGen3[tagCount];
     s.Seek(tagsOffset, System.IO.SeekOrigin.Begin);
     for (int x = 0; x < tagCount; x++)
     {
         (items[x] = new Cache.CacheItemGen3()).Read(s);
     }
 }
        protected void TagIndexInitializeAndRead(BlamLib.IO.EndianReader s)
        {
            base.StringIdManagerInitializeAndRead();
            base.InitializeReferenceManager(s.FileName);
            base.InitializeTagIndexManager();

            s.Seek(cacheHeader.OffsetToIndex, System.IO.SeekOrigin.Begin);
            cacheIndex.Read(s);
        }
Example #10
0
        public CacheItemGroupTag[] ReadGroupTags(BlamLib.IO.EndianReader s)
        {
            CacheItemGroupTag[] group_tags = new CacheItemGroupTag[groupTagsCount];
            s.Seek(groupTagsOffset, System.IO.SeekOrigin.Begin);
            for (int x = 0; x < groupTagsCount; x++)
            {
                (group_tags[x] = new CacheItemGroupTag()).Read(s);
            }

            return(group_tags);
        }
        public override void Read(BlamLib.IO.EndianReader s)
        {
            Blam.CacheFile.ValidateHeader(s, 0x800);

            s.Seek(4);
            version = s.ReadInt32();
            if (version != 5)
            {
                throw new InvalidCacheFileException(s.FileName);
            }

            fileLength = s.ReadInt32();

            int xbox = s.ReadInt32();             // Xbox only field

            offsetToIndex = s.ReadInt32();
            s.ReadInt32();             // stream size

            s.ReadInt32(); s.ReadInt32();

            name = s.ReadTagString();

            build     = s.ReadTagString();         // Xbox only field. Always '400'
            cacheType = (CacheType)s.ReadInt16();
            s.ReadInt16();
            s.ReadInt32();             // CRC

            s.Seek((485 * sizeof(int)) + sizeof(uint), System.IO.SeekOrigin.Current);


            CacheFile cf = s.Owner as CacheFile;

            if (xbox != 0)
            {
                cf.EngineVersion = BlamVersion.Stubbs_Xbox;
            }
            else             // no way to tell when it's mac, which just seems to use PC maps anyway (byte swaps everything when map is loaded)
            {
                cf.EngineVersion = BlamVersion.Stubbs_PC;
            }
        }
        public override void Read(BlamLib.IO.EndianReader s)
        {
            if (!isMemoryMap)
            {
                Header.Read(s);
            }

            if (!isMemoryMap)
            {
                s.Seek(Header.OffsetToIndex, System.IO.SeekOrigin.Begin);
            }
            else
            {
                s.Seek(Program.GetManager(engineVersion)[engineVersion].CacheTypes.BaseAddress, System.IO.SeekOrigin.Begin);
            }

            base.InitializeReferenceManager(s.FileName);
            base.InitializeTagIndexManager();

            cacheIndex.Read(s);
        }
        public override void Read(BlamLib.IO.EndianReader s)
        {
            DataCacheFile cache = s.Owner as DataCacheFile;

            type = (DataCacheType)s.ReadInt32();
            tagNamesTableOffset     = s.ReadInt32();
            tagInstancesTableOffset = s.ReadInt32();
            tagCount = s.ReadInt32();
            items    = new DataItem[tagCount];

            TagInterface.TagGroup tgroup = null;
            switch (type)
            {
            case DataCacheType.Bitmap: tgroup = TagGroups.bitm; break;

            case DataCacheType.Sound: tgroup = TagGroups.snd_; break;

            case DataCacheType.Loc:
                break;
            }

            s.Seek(TagNamesTableOffset, System.IO.SeekOrigin.Begin);
            DataItem item = null;

            for (int x = 0; x < TagCount; x++)
            {
                item               = new DataItem();
                items[x]           = item;
                item.GroupTag      = tgroup;
                item.ReferenceName = cache.References.AddOptimized(item.GroupTag, s.ReadCString());
            }

            s.Seek(tagInstancesTableOffset, System.IO.SeekOrigin.Begin);
            for (int x = 0; x < TagCount; x++)
            {
                items[x].Read(s);
            }
        }
        public override void Read(BlamLib.IO.EndianReader s)
        {
            Blam.CacheFile.ValidateHeader(s, 0x800);

            s.Seek(4);
            s.ReadInt32();             // version, should be 5

            fileLength = s.ReadInt32();

            int xbox = s.ReadInt32();             // Xbox only field

            offsetToIndex = s.ReadInt32();
            s.ReadInt32();             // stream size

            s.ReadInt32(); s.ReadInt32();

            name = s.ReadTagString();

            build     = s.ReadTagString(); // Xbox only field. Always '400'
            cacheType = (CacheType)s.ReadInt32();
            s.ReadInt32();                 // CRC

            s.Seek((485 * sizeof(int)) + sizeof(uint), System.IO.SeekOrigin.Current);


            CacheFile cf = s.Owner as CacheFile;

            if (xbox != 0)
            {
                cf.EngineVersion = BlamVersion.Stubbs_Xbox;
            }
            else
            {
                cf.EngineVersion = BlamVersion.Stubbs_PC;              // no way to tell when its mac...
            }
        }
Example #15
0
        public override void Read(BlamLib.IO.EndianReader s)
        {
            if (isLoaded)
            {
                return;
            }

            // goto the start if we're leaching off another cache's IO
            if (IsSharedReference)
            {
                s.Seek(0);
            }

            cacheHeader.Read(s);

            TagIndexInitializeAndRead(s);

            isLoaded = true;
        }
Example #16
0
        public override void Read(BlamLib.IO.EndianReader s)
        {
            bool is_alpha;
            bool is_pc = false;

            Blam.CacheFile.ValidateHeader(s, 0x800);

            #region figure out if this is a alpha map
            s.Seek(0x120);
            is_alpha = s.ReadTagString() == "02.06.28.07902";
            #endregion
            #region figure out if this is a pc map
            if (!is_alpha)
            {
                s.Seek(0x24);
                int test = s.ReadInt32();
                if (test == -1 || (test != 0 && test < s.Length))
                {
                    is_pc = true;
                }
            }
            #endregion
            s.Seek(4);

            version    = s.ReadInt32();
            fileLength = s.ReadInt32();
            s.ReadInt32();
            offsetToIndex   = s.ReadInt32();
            indexStreamSize = s.ReadInt32();

            tagBufferSize = s.ReadInt32(); // size of the tag data, excluding the bsp data
            s.ReadInt32();                 // max size: 0x3200000, indexStreamSize+tagBufferSize

            if (is_pc)
            {
                PcFields.VirtualAddress = s.ReadUInt32();                 // virtual base address

                PcFields.TagDependencyGraphOffset = s.ReadInt32();        // buffer offset (starts right before tag index, 512 byte aligned). not shared? should equal -1
                PcFields.TagDependencyGraphSize   = s.ReadUInt32();       // buffer size. not shared? should be zero. Max: 0x100000
            }

            sourceFile = s.ReadAsciiString(256);
            build      = s.ReadTagString();
            cacheType  = (Blam.CacheType)s.ReadInt32();
            // SP Filesize Max: 0x11800000
            // MP Filesize Max: 0x5000000
            // Mainmenu Filesize Max: 0x20800000
            // Shared Filesize Max: 0xB400000
            // Single Player Shared Filesize Max: 0x20800000
            s.ReadInt32();             // cache resource (tag) crc
            s.ReadInt32();             // boolean, set to true in pc when building cache

            s.ReadInt32(); s.ReadInt32();

            s.ReadInt32();             // count of some sort? only on the xbox

            // offset, then size
            // (size+0xFFF) & 0xFFFFF000
            // test that with 0x1FF, if true, or with 0x1FF then add 1
            s.ReadInt32();             // begins with 0x200 bytes of a chunk of the tag filenames table and ends with the same
            s.ReadInt32();             // has something to do with bitmaps. the bigger the file, the bigger this is

            #region string id
            // each string this buffer is aligned to 128 characters (the max length + 1 of a string_id)
            /*stringIdsBufferAlignedOffset = */ s.ReadInt32();
            stringIdsCount = s.ReadInt32();

            stringIdsBufferSize   = s.ReadInt32();
            stringIdIndicesOffset = s.ReadInt32();
            stringIdsBufferOffset = s.ReadInt32();
            #endregion

            s.ReadInt32();             // 4 bools

            Filetime.dwHighDateTime = s.ReadInt32();
            Filetime.dwLowDateTime  = s.ReadInt32();

            /*MainmenuFiletime.dwHighDateTime*/ SharedFiletimes[0].dwHighDateTime  = s.ReadInt32();
            /*MainmenuFiletime.dwLowDateTime = */ SharedFiletimes[0].dwLowDateTime = s.ReadInt32();

            /*SharedFiletime.dwHighDateTime*/ SharedFiletimes[1].dwHighDateTime = s.ReadInt32();
            /*SharedFiletime.dwLowDateTime*/ SharedFiletimes[1].dwLowDateTime   = s.ReadInt32();

            /*SharedSingleplayerFiletime.dwHighDateTime*/ SharedFiletimes[2].dwHighDateTime = s.ReadInt32();
            /*SharedSingleplayerFiletime.dwLowDateTime*/ SharedFiletimes[2].dwLowDateTime   = s.ReadInt32();

            name = s.ReadTagString();
            s.ReadInt32();             // dword, but unused
            scenarioPath = s.ReadAsciiString(256);

            // minor version
            needsShared = s.ReadInt32() == 1;             // doesn't exist on the pc

            #region tag names
            tagNamesCount        = s.ReadInt32();      // not used in alpha
            tagNamesBufferOffset = s.ReadInt32();      // not used in alpha
            tagNamesBufferSize   = s.ReadInt32();      // not used in alpha
            tagNameIndicesOffset = s.ReadInt32();      // not used in alpha
            #endregion

            if (is_pc)
            {
                // s_cache_language_pack
                PcFields.LanguagePacksOffset = s.ReadInt32();                 // offset, shared database = -1
                // sizeof(s_cache_language_pack) * LanguageType.kMax
                PcFields.LanguagePacksSizeOf = s.ReadUInt32();                // sizeof, shared database = 0

                // secondary sound gestalt
                PcFields.SecondarySoundGestalt.Read(s);                 // shared database = -1

                // fast geometry load region
                PcFields.FastLoadGeometryBlockOffset = s.ReadInt32();                // offset to a cache block resource
                PcFields.FastLoadGeometryBlockSize   = s.ReadUInt32();               // sizeof entire cache block resources partition. max size: 0x4000000

                checksum = s.ReadUInt32();

                // another xor checksum
                // sbsp
                //	- data 0x28C: global_structure_physics_struct->MoppCode
                //	- data 0x2BC: global_structure_physics_struct->BreakableSurfacesMoppCode
                //	- block 0xD4: structure_bsp_cluster_block
                //		* data 0xC4: "Collision mopp Code"
                //		* block 0x54: structure_bsp_cluster_data_block_new
                //			- data 0x3C: global_geometry_section_struct->"Visibility mopp Code"
                // phmo
                //	- data 0xE8: "mopp codes"
                // coll
                //	- block 0x28: collision_model_region_block
                //		* block 0x04: collision_model_permutation_block
                //			- block 0x10: collision_bsp_physics_block
                //				* data 0x64: "mopp Code Data"
                // mode
                //	- block 0x30: render_model_section_block
                //		* block 0x34: render_model_section_data_block
                //			- data 0x3C: global_geometry_section_struct->"Visibility mopp Code"
                // ltmp
                //	- block 0x80: structure_lightmap_group_block
                //		* block 0x30: lightmap_geometry_section_block
                //			- block 0x54: lightmap_geometry_section_cache_data_block
                //				* data 0x3C: global_geometry_section_struct->"Visibility mopp Code"
                //		* block 0x48: lightmap_geometry_section_block
                //			- block 0x54: lightmap_geometry_section_cache_data_block
                //				* data 0x3C: global_geometry_section_struct->"Visibility mopp Code"
                PcFields.MoppCodesChecksum = s.ReadUInt32();                 // shared databases = 0

                s.Seek(1284 + sizeof(uint), System.IO.SeekOrigin.Current);
            }
            else
            {
                checksum = s.ReadUInt32();

                s.Seek(1320 + sizeof(uint), System.IO.SeekOrigin.Current);
            }

            CacheFile cf = s.Owner as CacheFile;
            if (is_pc)
            {
                cf.EngineVersion = BlamVersion.Halo2_PC;
            }
            else if (build == "02.08.28.09214")
            {
                cf.EngineVersion = BlamVersion.Halo2_Epsilon;
            }
            else if (is_alpha)
            {
                cf.EngineVersion = BlamVersion.Halo2_Alpha;
            }
            else
            {
                cf.EngineVersion = BlamVersion.Halo2_Xbox;
            }
        }
        void ReadBeta(BlamLib.IO.EndianReader s)
        {
            s.ReadUInt32();

            //s.ReadBool();
            //s.ReadBool(); // false if it belongs to a untracked build
            //s.ReadBool();
            //s.ReadBool();
            // Just read the booleans as a f*****g int...
            s.ReadInt32();

            // Filetime.dwHighDateTime = s.ReadInt32();
            // Filetime.dwLowDateTime = s.ReadInt32();
            s.ReadInt32(); s.ReadInt32();

            s.ReadInt32(); s.ReadInt32(); s.ReadInt32();

            #region string id
            // retail doesn't include the 128 byte per string id table, so nix the members
            /*stringIdsBufferAlignedOffset = */ s.ReadInt32();
            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...
            s.ReadInt32();
            Filetime.dwHighDateTime = s.ReadInt32();
            Filetime.dwLowDateTime  = s.ReadInt32();
            if (s.ReadInt32() != 0)
            {
                flags.Add(CacheHeaderFlags.DependsOnMainMenu);
            }
            s.ReadInt32();
            if (s.ReadInt32() != 0)
            {
                flags.Add(CacheHeaderFlags.DependsOnShared);
            }
            s.ReadInt32();
            if (s.ReadInt32() != 0)
            {
                flags.Add(CacheHeaderFlags.DependsOnCampaign);
            }
            s.ReadInt32();
            #endregion

            name = s.ReadTagString();
            s.ReadInt32();
            scenarioPath = s.ReadAsciiString(256);
            needsShared  = s.ReadInt32() == 1;

            #region tag names
            tagNamesCount        = s.ReadInt32();
            tagNamesBufferOffset = s.ReadInt32();
            tagNamesBufferSize   = s.ReadInt32();
            tagNameIndicesOffset = s.ReadInt32();
            #endregion

            checksum = s.ReadUInt32();                // 0x2CC
            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
            memoryPartitions = new Partition[3];
            memoryPartitions[0].BaseAddress = s.ReadUInt32();     // address
            memoryPartitions[0].Size        = s.ReadInt32();      // size
            memoryPartitions[1].BaseAddress = s.ReadUInt32();     // address
            memoryPartitions[1].Size        = s.ReadInt32();      // size
            memoryPartitions[2].BaseAddress = s.ReadUInt32();     // address
            memoryPartitions[2].Size        = s.ReadInt32();      // size
            #endregion

            s.Seek(256, System.IO.SeekOrigin.Current);

            s.Seek(1004 + sizeof(uint), System.IO.SeekOrigin.Current);


            Managers.BlamDefinition bdef = Program.GetManager(BlamVersion.Halo3_Beta);

            uint base_address = (s.Owner as Blam.CacheFile).AddressMask = bdef[BlamVersion.Halo3_Beta].CacheTypes.BaseAddress - (uint)MemoryBufferOffset;

            offsetToIndex = (int)(tagIndexAddress - base_address);
            CalculatePartitionOffsets();
        }
        public override void Read(BlamLib.IO.EndianReader s)
        {
            int pos = 0;

            Blam.CacheFile.ValidateHeaderAdjustEndian(s, 0x800);
            s.Seek(4);

            Halo1.Version ver = (Halo1.Version)(version = s.ReadInt32());
            fileLength = s.ReadInt32();
            if (fileLength < s.Length)
            {
                throw new Debug.ExceptionLog("Compressed map editing not available yet!");
            }

            s.ReadInt32();

            if (ver == Halo1.Version.PC_Demo)
            {
                pos           = s.Position;
                s.Position    = 0x5EC;
                offsetToIndex = s.ReadInt32();
                s.Position    = pos;
            }
            else
            {
                offsetToIndex = s.ReadInt32();
            }

            tagBufferSize = s.ReadInt32();

            s.ReadInt32(); s.ReadInt32();

            if (ver == Halo1.Version.PC_Demo)
            {
                pos        = s.Position;
                s.Position = 0x5E8;
                name       = s.ReadTagString();
                s.Position = pos;
            }
            else
            {
                name = s.ReadTagString();
            }

            build     = s.ReadTagString();
            cacheType = (CacheType)s.ReadInt32();
            s.ReadInt32();             // CRC

            s.ReadInt32();
            s.Seek((484 * sizeof(int)) + sizeof(uint), System.IO.SeekOrigin.Current);

            CacheFile cache = s.Owner as CacheFile;

            if (ver == Halo1.Version.Xbox)
            {
                cache.EngineVersion = BlamVersion.Halo1_Xbox;
            }
            else if (ver == Halo1.Version.PC || ver == Halo1.Version.PC_Demo)
            {
                if (s.State == IO.EndianState.Big)
                {
                    cache.EngineVersion = BlamVersion.Halo1_XboxX;
                }
                else
                {
                    // Interestingly, HaloPC is build 01.00.00.0564, HA10 is build 01.00.01.0563
                    // Little
                    if (build == "01.00.01.0563")
                    {
                        cache.EngineVersion = BlamVersion.Halo1_PCX;
                    }
                    else
                    {
                        cache.EngineVersion = BlamVersion.Halo1_PC;
                    }
                }
            }
            else if (ver == Halo1.Version.CE)
            {
                cache.EngineVersion = BlamVersion.Halo1_CE;
            }
        }
        public override void Read(BlamLib.IO.EndianReader s)
        {
            CacheFileBase cache = s.Owner as CacheFileBase;

            #region read body
            groupTagsCount  = s.ReadInt32();
            groupTagsOffset = (groupTagsAddress = s.ReadUInt32()) - cache.AddressMask;

            tagCount   = s.ReadInt32();
            tagsOffset = (address = s.ReadUInt32()) - cache.AddressMask;

            dependentTagsCount  = s.ReadInt32();
            dependentTagsOffset = (dependentTagsAddress = s.ReadUInt32()) - cache.AddressMask;

            s.ReadInt32();
            s.ReadUInt32();            // seems to be the same address as the dependent tags

            s.ReadUInt32();            // crc?
            s.ReadInt32();             // 'tags'
            #endregion

            ReadDependents(s);

            ReadTagInstances(s);

            ReadGroupTags(s);

            #region fixup group tag info
            for (int x = 0; x < tagCount; x++)
            {
                var item = items[x];
                if (!item.IsEmpty)
                {
                    item.GroupTag    = groupTags[item.Datum.Index].GroupTag1;
                    item.GroupTagInt = item.GroupTag.ID;
                    item.Fixup((ushort)x);                     // Fix the hacks Bungie did for Halo3
                }
            }
            #endregion

            #region Load tag names
            s.Seek(cache.HeaderHalo3.TagNamesBufferOffset);
            string file_name;
            foreach (var ci in items)
            {
                if (!ci.IsEmpty)
                {
                    ci.TagNameOffset = s.PositionUnsigned;
                    file_name        = s.ReadCString();
                    if (file_name == "")
                    {
                        file_name = "NONE";
                    }
                }
                else
                {
                    ci.TagNameOffset = uint.MaxValue;
                    ci.ReferenceName = DatumIndex.Null;
                    continue;
                }

                ci.ReferenceName = cache.References.AddOptimized(ci.GroupTag, file_name);
            }
            #endregion
        }
        public override void Read(BlamLib.IO.EndianReader s)
        {
            bool is_beta = false;
            bool is_odst = !((s.Owner as Blam.CacheFile).EngineVersion == BlamVersion.Halo3);

            Blam.CacheFile.ValidateHeader(s, kSizeOf);

            s.Seek(4);
            version = s.ReadInt32(); is_beta = version == 9;
            if (version != 9 && version != 11)
            {
                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();

            if (is_beta)
            {
                s.ReadInt16(); sharedType = Cache.SharedType.Beta;
                ReadBeta(s);
                return;
            }
            else
            {
                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
            // old 128 byte aligned string table not used after the Delta builds of Halo 3

            stringIdsCount        = s.ReadInt32();
            stringIdsBufferSize   = s.ReadInt32();           // cstring buffer total size in bytes
            stringIdIndicesOffset = s.ReadInt32();
            stringIdsBufferOffset = s.ReadInt32();           // cstring buffer
            #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(CacheHeaderFlags.DependsOnMainMenu);
            }
            s.ReadInt32();
            if (s.ReadInt32() != 0)
            {
                flags.Add(CacheHeaderFlags.DependsOnShared);
            }
            s.ReadInt32();
            if (s.ReadInt32() != 0)
            {
                flags.Add(CacheHeaderFlags.DependsOnCampaign);
            }
            s.ReadInt32();
            #endregion

            name = s.ReadTagString();
            s.ReadInt32();
            scenarioPath = s.ReadAsciiString(256);
            s.ReadInt32();             // minor version, normally not used

            #region tag names
            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
            // 0x2E8

            // 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();             // sound cache resource buffer
            memoryPartitions[1].Size        = s.ReadInt32();

            memoryPartitions[2].BaseAddress = s.ReadUInt32();             // global tags buffer
            memoryPartitions[2].Size        = s.ReadInt32();
            memoryPartitions[3].BaseAddress = s.ReadUInt32();             // shared tag blocks?
            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(12, 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(kSizeOf);

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

            #region blah 2
            {
                // 0x27C4
                // This on the other hand, sc110 french and english had MINOR differences. Those differences were in
                // DWORDs @ 0x4 and 0x8

                // 005 - 1
                // 010 - 3
                // 020 - 3
                // 030 - 2
                // 040 - 2
                // 050 - 2
                // 070 - 3
                // 100 - 3
                // 110 - 2
                // 120 - 2
                // 130 - 1

                // c100  - 1
                // c200  - 1
                // h100  - 9
                // l200  - 7
                // l300  - 8
                // sc100 - 5
                // sc110 - 5
                // sc120 - 6
                // sc130 - 6
                // sc140 - 6
                // sc150 - 6

                // going to punt and just assume there is a max count of 10 of these possible

                // maybe related to bsp\'zones'?
                int blah2_sizeof = !is_odst ? 172 : 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
            }
            #endregion

            s.Seek((!is_odst ? 380 : 300) + sizeof(uint), System.IO.SeekOrigin.Current);             // zero


            ReadPostprocessForInterop();

            ReadPostprocessForBaseAddresses(s);
        }
        public override void Read(BlamLib.IO.EndianReader s)
        {
            CacheFile cache = s.Owner as CacheFile;

            #region read body
            groupTagsCount  = s.ReadInt32();
            groupTagsOffset = (groupTagsAddress = s.ReadUInt32()) - cache.AddressMask;

            tagCount   = s.ReadInt32();
            tagsOffset = (address = s.ReadUInt32()) - cache.AddressMask;

            dependentTagsCount  = s.ReadInt32();
            dependentTagsOffset = (dependentTagsAddress = s.ReadUInt32()) - cache.AddressMask;

            s.Seek(sizeof(int) +
                   sizeof(uint) +            // seems to always be the same address as the dependent tags
                   sizeof(int),              // new to Reach. Only seen as zero so far
                   System.IO.SeekOrigin.Current);

            s.ReadUInt32();            // crc?
            s.ReadInt32();             // 'tags'
            #endregion

            ReadDependents(s);

            ReadTagInstances(s);

            ReadGroupTags(s);

            #region fixup group tag info
            for (int x = 0; x < tagCount; x++)
            {
                var item = items[x];
                if (!item.IsEmpty)
                {
                    item.GroupTag    = groupTags[item.Datum.Index].GroupTag1;
                    item.GroupTagInt = item.GroupTag.ID;
                    item.Fixup((ushort)x);                     // Fix the hacks Bungie did for Halo3
                }
            }
            #endregion

            #region Load tag names
            using (var buffer = cache.DecryptCacheSegmentStream(CacheSectionType.Tag, cache.HeaderHalo4.TagNamesBufferOffset, cache.HeaderHalo4.TagNamesBufferSize))
            {
                string tag_name;
                foreach (var ci in items)
                {
                    if (!ci.IsEmpty)
                    {
                        // NOTE, we're recording a buffer relative offset here...since the
                        // cache has it encrypted I don't see the point of having the
                        // offset relative to the cache file
                        ci.TagNameOffset = buffer.PositionUnsigned;
                        tag_name         = buffer.ReadCString();
                        if (tag_name == "")
                        {
                            tag_name = "NONE";
                        }
                    }
                    else
                    {
                        ci.TagNameOffset = uint.MaxValue;
                        ci.ReferenceName = DatumIndex.Null;
                        continue;
                    }

                    ci.ReferenceName = cache.References.AddOptimized(ci.GroupTag, tag_name);
                }
            }
            #endregion
        }
Example #22
0
			void DisallowTags()
			{
				BlamLib.IO.EndianReader input = new BlamLib.IO.EndianReader(output.FileName);
				input.BaseAddress = Program.PeAddressMask;
				input.Seek(AddressOf.TagGroupDefinitions[Platform.Guerilla] - Program.PeAddressMask);

				uint[] offsets = new uint[Constants.StockTagGroupCount];
				for (int x = 0; x < offsets.Length; x++)
					offsets[x] = input.ReadPointer();

				for (int x = 0; x < offsets.Length; x++)
				{
					input.Seek(offsets[x]);
					string name = Program.ReadCString(input.ReadPointer(), input);
					if (IsDisallowedTag(name))
					{
						input.Seek(0x20, System.IO.SeekOrigin.Current);
						output.Seek(input.Position - 2);
						output.Write((short)1);
						output.Seek(input.ReadPointer() + 0x14);
						output.Write(0);
						output.Write(0);
						output.Write(0);
					}
				}
				input.Close();
			}
Example #23
0
        public override void Read(BlamLib.IO.EndianReader s)
        {
            CacheFile cache = s.Owner as CacheFile;

            tagsOffset = (uint)(cache.Header.OffsetToIndex + cache.HeaderHalo2.IndexStreamSize);
            bool is_alpha = cache.EngineVersion == BlamVersion.Halo2_Alpha;
            bool is_echo  = cache.EngineVersion == BlamVersion.Halo2_Epsilon;
            bool is_pc    = cache.EngineVersion == BlamVersion.Halo2_PC;
            bool is_mp    = cache.HeaderHalo2.CacheType == CacheType.Multiplayer;

            Managers.BlamDefinition bdef = Program.GetManager(cache.EngineVersion);

            uint tags_addressmask;

            if (!is_pc)
            {
                cache.AddressMask =
                    bdef[cache.EngineVersion].CacheTypes.BaseAddress - (uint)cache.Header.OffsetToIndex;
                tags_addressmask =
                    (uint)(cache.Header.OffsetToIndex + cache.HeaderHalo2.IndexStreamSize);
            }
            else
            {
                // pc maps use virtual addresses which are actually offsets relative to
                // the start of the tag memory buffer. since these are offsets and not actually
                // addresses which we would normally mask the base off of, we have to do some
                // number magic so our subtraction operations actually end up working in reverse
                // to get the correct file offset
                tags_addressmask = 0 - (uint)cache.Header.OffsetToIndex;

                cache.AddressMask = tags_addressmask;
            }

            #region version dependant loading
            if (is_alpha)
            {
                groupTagsAddress = address = s.ReadUInt32();
                groupTagsCount   = 0;
                scenario.Read(s);
                s.ReadInt32();                 // crc
                tagCount = s.ReadInt32();
                items    = new CacheItem[tagCount];
                s.ReadInt32();                 // 'tags'
            }
            else if (is_pc)
            {
                groupTagsAddress = s.ReadPointer();            // offset (relative to the tag index offset)
                groupTagsCount   = s.ReadInt32();
                uint offset = s.ReadPointer();                 // offset (relative to the tag index offset) to the tag entries
                scenario.Read(s);
                gameGlobals.Read(s);
                s.ReadInt32();                 // crc
                tagCount = s.ReadInt32();
                items    = new CacheItem[tagCount];
                s.ReadInt32();                                         // 'tags'

                s.Seek(offset /*- 32, System.IO.SeekOrigin.Current*/); // go to the first tag entry
            }
            else
            {
                groupTagsAddress = s.ReadUInt32();
                groupTagsCount   = s.ReadInt32();
                address          = s.ReadUInt32();
                scenario.Read(s);
                gameGlobals.Read(s);
                s.ReadInt32();                 // crc
                tagCount = s.ReadInt32();
                items    = new CacheItem[tagCount];
                s.ReadInt32();                                             // 'tags'

                s.Seek(groupTagsCount * 12, System.IO.SeekOrigin.Current); // go to the first tag entry
            }

            this.groupTagsOffset = this.groupTagsAddress - s.BaseAddress;
            #endregion

            CacheItem item;
            uint      temp_pos    = 0;
            uint      sbsp_offset = 0;

            DatumIndex[] ltmps = null;
            Tags.scenario_structure_bsp_reference_block bsp_block = new Tags.scenario_structure_bsp_reference_block();

            if (is_pc)             // MP maps need this adjustment
            {
                cache.AddressMask = tags_addressmask += cache.HeaderHalo2.PcFields.VirtualAddress;
            }

            for (int x = 0; x < items.Length; x++)
            {
                item     = new CacheItem();
                items[x] = item;
                if (is_alpha)
                {
                    item.ReadAlpha(s);
                }
                else
                {
                    item.Read(s);
                }

                if (item.Location == ItemLocation.Unknown)
                {
                    items[x] = CacheItem.Null;
                }
                else if (is_pc && item.HasExternalData)
                {
                    HasExternalTags = true;
                }
            }

            if (!is_pc)
            {
                // While the tag definitions come right after the tag header in a cache file, when
                // finally loaded into game memory this isn't the case. The 'stream' size of the tag
                // header is how much actual memory is used by map's generated the tag header, but the
                // map's tag header may not utilize the entire memory space dedicated to it in game memory.
                // So, the game would read the tag header data using the offset and 'stream' size data from
                // the cache header, then it would seek to offset+stream_size to get to the tag definitions
                // which it would then read into game memory at the memory location defined by 'address'
                tags_addressmask =
                    items[0].Address - tags_addressmask;
                cache.AddressMask = tags_addressmask;
                for (int x = 0; x < items.Length; x++)
                {
                    item        = items[x];
                    item.Offset = (int)(item.Address - tags_addressmask);

                    #region on scnr tag
                    if (!is_alpha && !is_echo && TagGroups.scnr.ID == item.GroupTag.ID)
                    {
                        temp_pos = s.PositionUnsigned;

                        //if (is_alpha || is_echo)
                        //	s.Seek(item.Offset + 828);
                        //else
                        s.Seek(item.Offset + 528);

                        bspTags     = new Item[s.ReadInt32()];
                        sbsp_offset = s.ReadPointer();

                        ltmps = new DatumIndex[bspTags.Length];

                        s.Seek(temp_pos);
                    }
                    #endregion
                    #region on sbsp tag
                    else if (!is_alpha && !is_echo && TagGroups.sbsp.ID == item.GroupTag.ID)
                    {
                        temp_pos = s.PositionUnsigned;

                        s.Seek(sbsp_offset + (uint)(bspCount *
                                                    Halo2.Tags.scenario_structure_bsp_reference_block.kRuntimeSizeOf));
                        bspTags[bspCount] = item;
                        bsp_block.Read(cache);

                        if (bsp_block.RuntimeOffset != 0)
                        {
                            item.Offset  = bsp_block.RuntimeOffset;
                            item.Size    = bsp_block.RuntimeSize;
                            item.Address = (uint)bsp_block.RuntimeAddress.Value;
                            //cache.BspAddressMasks.Add((uint)(item.Address - item.Offset));
                        }

                        ltmps[bspCount] = bsp_block.Lightmap.Datum;
                        item.BspIndex   = bspCount++;

                        s.Seek(temp_pos);
                    }
                    #endregion
                }
            }

            #region alpha tag name code
            if (is_alpha)
            {
                // following the tag datums in alpha builds is the tag names buffer
                foreach (Halo2.CacheItem ci in items)
                {
                    ci.TagNameOffset = s.PositionUnsigned;
                    ci.ReferenceName = cache.References.AddOptimized(ci.GroupTag, s.ReadCString());
                }
            }
            #endregion
            #region retail tag name & bsp offset fixup code
            else
            {
                // Build the absolute tag name offsets
                s.Seek(cache.HeaderHalo2.TagNameIndicesOffset);
                int[] offsets = new int[tagCount];
                for (int x = 0; x < offsets.Length; x++)
                {
                    int offset = s.ReadInt32();
                    // Offset will be -1 if the tag in question is 'null'
                    if (offset != -1)
                    {
                        offset += cache.HeaderHalo2.TagNamesBufferOffset;
                    }

                    offsets[x] = offset;
                }
                // Fixup all tag instances which are named
                for (int x = 0; x < tagCount; x++)
                {
                    if (offsets[x] != -1)
                    {
                        FixupTagInstanceHeaderName(cache, items[x], offsets[x], s);
                    }
                }

                // PC maps store all zones in the tag memory, they don't need to swap out and thus don't
                // need any fix ups (durrr, PCs have loltons of RAM)
                if (!is_pc && !is_echo)
                {
                    var head = new Halo2.Tags.scenario_structure_bsps_header();
                    foreach (CacheItem tmp_item in bspTags)
                    {
                        s.Seek(tmp_item.Offset);
                        head.Read(cache);

                        // bsp
                        uint bsp_address_mask = head.FixupBspInstanceHeader(tmp_item, s.Position);
                        cache.BspAddressMasks.Add(bsp_address_mask);

                        // ltmp
                        DatumIndex ltmp_datum = ltmps[tmp_item.BspIndex];
                        if (ltmp_datum != DatumIndex.Null)
                        {
                            head.FixupLightmapInstanceHeader(this.items[ltmp_datum.Index], tmp_item);
                        }
                    }
                }
            }
            #endregion
        }
 public void Read(BlamLib.IO.EndianReader s)
 {
     s.Seek(ByteCount);
 }