Пример #1
0
        private void LoadInteropData(StructureValueCollection headerValues)
        {
            // TODO: fix this shit for the h3beta better
            if (headerValues.HasArray("offset masks") && headerValues.HasArray("sections"))
            {
                SectionOffsetMasks = headerValues.GetArray("offset masks").Select(v => (uint)v.GetInteger("mask")).ToArray();
                Sections           = headerValues.GetArray("sections").Select(v => new ThirdGenInteropSection(v)).ToArray();

                // H3 MCC currently doesn't store section data for campaign/shared, so it must be hacked together
                if (_expander.IsValid && (Type == CacheFileType.Shared || Type == CacheFileType.SinglePlayerShared))
                {
                    if (Sections[(int)ThirdGenInteropSectionType.Resource].Size == 0)
                    {
                        Sections[(int)ThirdGenInteropSectionType.Resource].VirtualAddress = (uint)HeaderSize;
                        Sections[(int)ThirdGenInteropSectionType.Resource].Size           = (uint)FileSize - (uint)HeaderSize;
                    }
                }
            }
            else             //else hack up our own sections
            {
                SectionOffsetMasks = new uint[] { 0, 0, 0, 0 };

                ThirdGenInteropSection debugSection = new ThirdGenInteropSection(
                    (uint)headerValues.GetInteger("string index table offset"),
                    (uint)(headerValues.GetInteger("file size") - headerValues.GetInteger("string index table offset")));
                ThirdGenInteropSection resourceSection = new ThirdGenInteropSection(0, 0);                 // this is between locales and tag, so if we had a locale size, this section could be calculated. Using 0's for now seems to work at least
                ThirdGenInteropSection tagSection      = new ThirdGenInteropSection(
                    (uint)headerValues.GetInteger("tag buffer offset"),
                    (uint)headerValues.GetInteger("virtual size"));
                ThirdGenInteropSection localeSection = new ThirdGenInteropSection(
                    (uint)HeaderSize,
                    (uint)headerValues.GetInteger("tag buffer offset"));                     //bs the size for now

                Sections = new ThirdGenInteropSection[] { debugSection, resourceSection, tagSection, localeSection };
            }

            DebugPointerConverter     = MakePointerConverter(ThirdGenInteropSectionType.Debug);
            ResourcePointerConverter  = MakePointerConverter(ThirdGenInteropSectionType.Resource);
            TagBufferPointerConverter = MakePointerConverter(ThirdGenInteropSectionType.Tag);
            LocalePointerConverter    = MakePointerConverter(ThirdGenInteropSectionType.Localization);
        }
Пример #2
0
        /// <summary>
        ///     Rebuilds the interop data table in a cache file.
        /// </summary>
        /// <param name="localeArea">The localization area of the file.</param>
        private void RebuildInteropData(FileSegmentGroup localeArea)
        {
            ThirdGenInteropSection debugSection  = Sections[(int)ThirdGenInteropSectionType.Debug];
            ThirdGenInteropSection rsrcSection   = Sections[(int)ThirdGenInteropSectionType.Resource];
            ThirdGenInteropSection tagSection    = Sections[(int)ThirdGenInteropSectionType.Tag];
            ThirdGenInteropSection localeSection = Sections[(int)ThirdGenInteropSectionType.Localization];

            // Recompute base addresses
            // Section addresses are usually in the following order: resource, locale, tag, debug.
            // Each address can immediately follow after the previous non-null section,
            // even though this isn't the case in some of the official files (because of removed debug data).
            //
            // TODO: This could possibly be made into a for loop and cleaned up if the pointer converters are stored in an array.
            // I just want to get this working for now.
            //rsrcSection.VirtualAddress = 0; // This is (not) always zero

            if (cacheSegmentAlignment == 0x800)
            {
                rsrcSection.VirtualAddress = 0x800;                 // hax for h3b saving, sections aren't in the same order as final
            }
            rsrcSection.Size             = (ResourcePointerConverter != null) ? (uint)RawTable.Size : 0;
            localeSection.VirtualAddress = (LocalePointerConverter != null) ? rsrcSection.VirtualAddress + rsrcSection.Size : 0;
            localeSection.Size           = (LocalePointerConverter != null) ? (uint)localeArea.Size : 0;
            tagSection.VirtualAddress    = (TagBufferPointerConverter != null)
                                ? rsrcSection.VirtualAddress + rsrcSection.Size + localeSection.Size
                                : 0;
            tagSection.Size             = (TagBufferPointerConverter != null) ? (uint)MetaArea.Size : 0;
            debugSection.VirtualAddress = (DebugPointerConverter != null)
                                ? rsrcSection.VirtualAddress + rsrcSection.Size + localeSection.Size + tagSection.Size
                                : 0;
            debugSection.Size = (DebugPointerConverter != null) ? (uint)StringArea.Size : 0;

            // If the offset mask for the debug section wasn't originally zero, then we have to subtract the first partition size from the debug base address
            // Not entirely sure why this is the case, but that's what the official files do
            if (debugSection.VirtualAddress != 0 && SectionOffsetMasks[(int)ThirdGenInteropSectionType.Debug] != 0)
            {
                debugSection.VirtualAddress -= Partitions[0].Size;
            }

            // Recompute offset masks
            SectionOffsetMasks[(int)ThirdGenInteropSectionType.Debug] = (debugSection.Size > 0)
                                ? (uint)(StringArea.Offset - debugSection.VirtualAddress)
                                : 0;
            SectionOffsetMasks[(int)ThirdGenInteropSectionType.Resource] = (rsrcSection.Size > 0)
                                ? (uint)(RawTable.Offset - rsrcSection.VirtualAddress)
                                : 0;
            SectionOffsetMasks[(int)ThirdGenInteropSectionType.Tag] = (tagSection.Size > 0)
                                ? (uint)(MetaArea.Offset - tagSection.VirtualAddress)
                                : 0;
            SectionOffsetMasks[(int)ThirdGenInteropSectionType.Localization] = (localeSection.Size > 0)
                                ? (uint)(localeArea.Offset - localeSection.VirtualAddress)
                                : 0;

            // Update pointer converters
            if (DebugPointerConverter != null)
            {
                DebugPointerConverter.BasePointer = debugSection.VirtualAddress;
            }
            if (ResourcePointerConverter != null)
            {
                ResourcePointerConverter.BasePointer = rsrcSection.VirtualAddress;
            }
            if (TagBufferPointerConverter != null)
            {
                TagBufferPointerConverter.BasePointer = tagSection.VirtualAddress;
            }
            if (LocalePointerConverter != null)
            {
                LocalePointerConverter.BasePointer = localeSection.VirtualAddress;
            }
        }