Пример #1
0
        /// <summary>
        /// Builds a memory map for a tag.
        /// </summary>
        /// <param name="data">The tag data to build a memory map for.</param>
        /// <returns>The built map.</returns>
        private static MemoryMap BuildTagMap(CachedTagData data)
        {
            // Create a memory map with a boundary at each fixup target
            // and at the main structure
            var result = new MemoryMap(0, (uint)data.Data.Length);

            result.AddBoundary(data.MainStructOffset);
            result.AddBoundaries(data.PointerFixups.Select(f => f.TargetOffset));
            return(result);
        }
Пример #2
0
 public TagLayoutGuess Analyze(CachedTagData data)
 {
     _tagMap = BuildTagMap(data);
     _dataFixupsByWriteOffset     = data.PointerFixups.ToDictionary(f => f.WriteOffset);
     _resourceFixupsByWriteOffset = new HashSet <uint>(data.ResourcePointerOffsets);
     using (var reader = new BinaryReader(new MemoryStream(data.Data)))
     {
         reader.BaseStream.Position = data.MainStructOffset;
         return(AnalyzeStructure(reader, 1));
     }
 }
Пример #3
0
 public void BeginSerialize(TagStructureInfo info)
 {
     Data = new CachedTagData
     {
         Group = new TagGroup
                 (
             tag: info.GroupTag,
             parentTag: info.ParentGroupTag,
             grandparentTag: info.GrandparentGroupTag,
             name: (info.Structure.Name != null) ? Context.GetStringId(info.Structure.Name) : StringId.Invalid
                 ),
     };
 }
Пример #4
0
        private void AddTags(HashSet <int> tagIndices)
        {
            // define current cache tags, names
            var modTagCache  = ModPackage.TagCaches[0];
            var modTagNames  = ModPackage.TagCacheNames[0];
            var modTagStream = ModPackage.TagCachesStreams[0];

            using (var srcTagStream = CacheContext.OpenCacheRead())
            {
                var resourceIndices = new Dictionary <ResourceLocation, Dictionary <int, PageableResource> >
                {
                    [ResourceLocation.Audio]        = new Dictionary <int, PageableResource>(),
                    [ResourceLocation.Lightmaps]    = new Dictionary <int, PageableResource>(),
                    [ResourceLocation.Mods]         = new Dictionary <int, PageableResource>(),
                    [ResourceLocation.RenderModels] = new Dictionary <int, PageableResource>(),
                    [ResourceLocation.Resources]    = new Dictionary <int, PageableResource>(),
                    [ResourceLocation.ResourcesB]   = new Dictionary <int, PageableResource>(),
                    [ResourceLocation.Textures]     = new Dictionary <int, PageableResource>(),
                    [ResourceLocation.TexturesB]    = new Dictionary <int, PageableResource>()
                };

                var srcResourceCaches  = new Dictionary <ResourceLocation, ResourceCacheHaloOnline>();
                var srcResourceStreams = new Dictionary <ResourceLocation, Stream>();

                foreach (var value in Enum.GetValues(typeof(ResourceLocation)))
                {
                    ResourceCacheHaloOnline resourceCache = null;
                    var location = (ResourceLocation)value;

                    if (location == ResourceLocation.None)
                    {
                        continue;
                    }

                    try
                    {
                        resourceCache = CacheContext.ResourceCaches.GetResourceCache(location);
                    }
                    catch (FileNotFoundException)
                    {
                        continue;
                    }

                    srcResourceCaches[location]  = resourceCache;
                    srcResourceStreams[location] = CacheContext.ResourceCaches.OpenCacheRead(location);
                }

                for (var tagIndex = 0; tagIndex < CacheContext.TagCache.Count; tagIndex++)
                {
                    var srcTag = CacheContext.TagCache.GetTag(tagIndex);

                    if (srcTag == null)
                    {
                        modTagCache.AllocateTag(new TagTool.Tags.TagGroup());
                        continue;
                    }

                    if (!tagIndices.Contains(tagIndex))
                    {
                        var emptyTag      = modTagCache.AllocateTag(srcTag.Group, srcTag.Name);
                        var cachedTagData = new CachedTagData();
                        cachedTagData.Data  = new byte[0];
                        cachedTagData.Group = emptyTag.Group;
                        modTagCache.SetTagData(modTagStream, (CachedTagHaloOnline)emptyTag, cachedTagData);
                        continue;
                    }

                    var destTag = modTagCache.AllocateTag(srcTag.Group, srcTag.Name);

                    using (var tagDataStream = new MemoryStream(CacheContext.TagCacheGenHO.ExtractTagRaw(srcTagStream, (CachedTagHaloOnline)srcTag)))
                        using (var tagDataReader = new EndianReader(tagDataStream, leaveOpen: true))
                            using (var tagDataWriter = new EndianWriter(tagDataStream, leaveOpen: true))
                            {
                                var resourcePointerOffsets = new HashSet <uint>();

                                foreach (var resourcePointerOffset in ((CachedTagHaloOnline)srcTag).ResourcePointerOffsets)
                                {
                                    if (resourcePointerOffset == 0 || resourcePointerOffsets.Contains(resourcePointerOffset))
                                    {
                                        continue;
                                    }

                                    resourcePointerOffsets.Add(resourcePointerOffset);

                                    tagDataStream.Position = resourcePointerOffset;
                                    var resourcePointer = tagDataReader.ReadUInt32();

                                    if (resourcePointer == 0)
                                    {
                                        continue;
                                    }

                                    var resourceOffset = ((CachedTagHaloOnline)srcTag).PointerToOffset(resourcePointer);

                                    tagDataReader.BaseStream.Position = resourceOffset + 2;
                                    var locationFlags = (OldRawPageFlags)tagDataReader.ReadByte();

                                    var resourceLocation =
                                        locationFlags.HasFlag(OldRawPageFlags.InAudio) ?
                                        ResourceLocation.Audio :
                                        locationFlags.HasFlag(OldRawPageFlags.InResources) ?
                                        ResourceLocation.Resources :
                                        locationFlags.HasFlag(OldRawPageFlags.InResourcesB) ?
                                        ResourceLocation.ResourcesB :
                                        locationFlags.HasFlag(OldRawPageFlags.InTextures) ?
                                        ResourceLocation.Textures :
                                        locationFlags.HasFlag(OldRawPageFlags.InTexturesB) ?
                                        ResourceLocation.TexturesB :
                                        ResourceLocation.ResourcesB;

                                    tagDataReader.BaseStream.Position = resourceOffset + 4;
                                    var resourceIndex  = tagDataReader.ReadInt32();
                                    var compressedSize = tagDataReader.ReadUInt32();

                                    if (resourceIndex == -1)
                                    {
                                        continue;
                                    }

                                    PageableResource pageable = null;

                                    if (resourceIndices[resourceLocation].ContainsKey(resourceIndex))
                                    {
                                        pageable = resourceIndices[resourceLocation][resourceIndex];
                                    }
                                    else
                                    {
                                        var newResourceIndex = ModPackage.Resources.AddRaw(
                                            ModPackage.ResourcesStream,
                                            srcResourceCaches[resourceLocation].ExtractRaw(
                                                srcResourceStreams[resourceLocation],
                                                resourceIndex,
                                                compressedSize));

                                        pageable = resourceIndices[resourceLocation][resourceIndex] = new PageableResource
                                        {
                                            Page = new ResourcePage
                                            {
                                                OldFlags = OldRawPageFlags.InMods,
                                                Index    = newResourceIndex
                                            }
                                        };
                                    }

                                    tagDataReader.BaseStream.Position = resourceOffset + 2;
                                    tagDataWriter.Write((byte)pageable.Page.OldFlags);

                                    tagDataReader.BaseStream.Position = resourceOffset + 4;
                                    tagDataWriter.Write(pageable.Page.Index);
                                }

                                modTagCache.SetTagDataRaw(modTagStream, (CachedTagHaloOnline)destTag, tagDataStream.ToArray());
                            }
                }

                foreach (var stream in srcResourceStreams.Values)
                {
                    if (stream != null)
                    {
                        stream.Dispose();
                    }
                }

                modTagCache.UpdateTagOffsets(new EndianWriter(modTagStream));
            }
        }