Beispiel #1
0
        public RenderMaterial(Direct3D.Device device, GameCache cache, TagTool.Geometry.RenderMaterial material)
        {
            if (material.RenderMethod == null)
            {
                return;
            }

            using (var cacheStream = cache.OpenCacheRead())
            {
                var renderMethod = cache.Deserialize <RenderMethod>(cacheStream, material.RenderMethod);

                var template = cache.Deserialize <RenderMethodTemplate>(cacheStream, renderMethod.ShaderProperties[0].Template);

                Textures = new Dictionary <string, RenderTexture>();

                for (var shaderMapIndex = 0; shaderMapIndex < renderMethod.ShaderProperties[0].TextureConstants.Count; shaderMapIndex++)
                {
                    var shaderMapName = cache.StringTable.GetString(template.TextureParameterNames[shaderMapIndex].Name);

                    if (Textures.ContainsKey(shaderMapName))
                    {
                        continue;
                    }

                    var shaderMap           = renderMethod.ShaderProperties[0].TextureConstants[shaderMapIndex];
                    var shaderMapDefinition = cache.Deserialize <Bitmap>(cacheStream, shaderMap.Bitmap);

                    Textures[shaderMapName] = new RenderTexture(device, cache, shaderMapDefinition, shaderMap.BitmapIndex);
                }
            }
        }
Beispiel #2
0
        public GeometryToObjectConverter(
            GameCacheHaloOnlineBase destCache, Stream destStream, GameCache sourceCache,
            Stream sourceStream, Scenario scenario, int structureBspIndex)
        {
            DestCache         = destCache;
            DestStream        = destStream;
            SourceCache       = sourceCache;
            SourceStream      = sourceStream;
            StructureBspIndex = structureBspIndex;
            PortTag           = new PortTagCommand(destCache, sourceCache);
            PortTag.SetFlags(PortTagCommand.PortingFlags.Default);

            Scenario          = scenario;
            StructureBspIndex = structureBspIndex;
            StructureBsp      = SourceCache.Deserialize <ScenarioStructureBsp>(SourceStream, Scenario.StructureBsps[structureBspIndex].StructureBsp);
            sLdT = SourceCache.Deserialize <ScenarioLightmap>(SourceStream, Scenario.Lightmap);

            if (SourceCache.Version >= CacheVersion.Halo3ODST)
            {
                Lbsp = SourceCache.Deserialize <ScenarioLightmapBspData>(SourceStream, sLdT.LightmapDataReferences[StructureBspIndex]);
            }
            else
            {
                Lbsp = sLdT.Lightmaps[StructureBspIndex];
            }

            var resourceDefinition = SourceCache.ResourceCache.GetRenderGeometryApiResourceDefinition(Lbsp.Geometry.Resource);

            Lbsp.Geometry.SetResourceBuffers(resourceDefinition);

            StructureBspResources = SourceCache.ResourceCache.GetStructureBspTagResources(StructureBsp.CollisionBspResource);
        }
Beispiel #3
0
        public RenderMethod MatchShader(RenderMethod renderMethod)
        {
            if (renderMethod.ShaderProperties.Count < 0)
            {
                return(renderMethod);
            }

            var property           = renderMethod.ShaderProperties[0];
            var originalTemplate   = PortingCache.Deserialize <RenderMethodTemplate>(PortingCacheStream, property.Template);
            var matchedTemplateTag = FindClosestTemplate(property.Template, originalTemplate);
            var matchedTemplate    = BaseCache.Deserialize <RenderMethodTemplate>(BaseCacheStream, matchedTemplateTag);

            renderMethod = MatchRenderMethods(renderMethod, matchedTemplate, originalTemplate);
            // might require some special checks if match render method can fail
            return(renderMethod);
        }
Beispiel #4
0
        public override object Execute(List <string> args)
        {
            if (args.Count < 1 || args.Count > 2)
            {
                return(false);
            }

            if (args[0] == "new")
            {
                return(MatchShaderNew(args[1]));
            }
            else if (args.Count == 2)
            {
                return(false);
            }

            RenderMethodTemplate bmRmt2 = new RenderMethodTemplate();
            CachedTag            bmRmt2Instance;

            using (var blamStream = BlamCache.OpenCacheRead())
            {
                if (BlamCache.TryGetCachedTag(args[0], out bmRmt2Instance))
                {
                    bmRmt2 = BlamCache.Deserialize <RenderMethodTemplate>(blamStream, bmRmt2Instance);
                }
                else
                {
                    return(false);
                }
            }

            List <string> bmMaps = new List <string>();
            List <string> bmArgs = new List <string>();

            // Get a simple list of H3 bitmaps and arguments names
            foreach (var a in bmRmt2.TextureParameterNames)
            {
                bmMaps.Add(BlamCache.StringTable.GetString(a.Name));
            }
            foreach (var a in bmRmt2.RealParameterNames)
            {
                bmArgs.Add(BlamCache.StringTable.GetString(a.Name));
            }

            string result = null;

            using (var cacheStream = Cache.OpenCacheRead())
            {
                ShaderMatcher Matcher = new ShaderMatcher();
                Matcher.Init(cacheStream, Cache, BlamCache);

                // Find a HO equivalent rmt2
                var edRmt2Instance = Matcher.FixRmt2Reference(cacheStream, bmRmt2Instance.Name, bmRmt2Instance, bmRmt2, bmMaps, bmArgs);
                result = edRmt2Instance.Name;
            }

            Console.WriteLine($"Blam template \"{bmRmt2Instance.Name}.rmt2\"\n matched with \"{result}.rmt2\".");
            return(true);
        }
Beispiel #5
0
        private byte[] ConvertGen3SoundData(GameCache cache, Sound definition, byte[] soundData)
        {
            // todo: use PortingContextFactory here (currently inaccessible)
            SoundCacheFileGestalt blamSoundGestalt = null;

            foreach (var tag in cache.TagCache.TagTable)
            {
                if (tag.Group.Tag == "ugh!")
                {
                    using (var stream = cache.OpenCacheRead())
                        blamSoundGestalt = cache.Deserialize <SoundCacheFileGestalt>(stream, tag);
                    break;
                }
            }

            // ExportSoundCommand code
            using (MemoryStream soundDataStream = new MemoryStream())
            {
                using (EndianWriter output = new EndianWriter(soundDataStream, EndianFormat.BigEndian))
                {
                    if (blamSoundGestalt != null)
                    {
                        for (int pitchRangeIndex = definition.SoundReference.PitchRangeIndex; pitchRangeIndex < definition.SoundReference.PitchRangeIndex + definition.SoundReference.PitchRangeCount; pitchRangeIndex++)
                        {
                            var relativePitchRangeIndex = pitchRangeIndex - definition.SoundReference.PitchRangeIndex;
                            var permutationCount        = blamSoundGestalt.GetPermutationCount(pitchRangeIndex);

                            for (int i = 0; i < permutationCount; i++)
                            {
                                BlamSound blamSound = SoundConverter.ConvertGen3Sound(cache, blamSoundGestalt, definition, relativePitchRangeIndex, i, soundData);

                                output.WriteBlock(blamSound.Data);
                            }
                        }
                    }
                }

                return(soundDataStream.ToArray());
            }
        }
Beispiel #6
0
        public static SoundCacheFileGestalt LoadSoundGestalt(GameCache cache, Stream cacheStream)
        {
            CachedTag blamTag = null;

            foreach (var tag in cache.TagCache.TagTable)
            {
                if (tag.Group.Tag == "ugh!")
                {
                    blamTag = tag;
                    break;
                }
            }

            if (blamTag == null)
            {
                return(null);
            }

            SoundCacheFileGestalt result = cache.Deserialize <SoundCacheFileGestalt>(cacheStream, blamTag);

            return(result);
        }
Beispiel #7
0
        public override object Execute(List <string> args)
        {
            var argStack = new Stack <string>(args.AsEnumerable().Reverse());

            var portingFlags = ParsePortingFlags(argStack);

            if (argStack.Count < 1)
            {
                Console.WriteLine("ERROR: Expected bsp index!");
                return(false);
            }

            var sbspIndex = int.Parse(argStack.Pop());

            using (var blamCacheStream = BlamCache.OpenCacheRead())
                using (var hoCacheStream = HoCache.OpenCacheReadWrite())
                {
                    var blamScnr = BlamCache.Deserialize <Scenario>(blamCacheStream, BlamCache.TagCache.FindFirstInGroup("scnr"));
                    var blamSbsp = BlamCache.Deserialize <ScenarioStructureBsp>(blamCacheStream, blamScnr.StructureBsps[sbspIndex].StructureBsp);

                    var desiredInstances = new Dictionary <int, string>();

                    if (argStack.Count > 0)
                    {
                        var    identifier  = argStack.Pop();
                        string desiredName = null;
                        if (argStack.Count > 0)
                        {
                            desiredName = argStack.Pop();
                        }

                        var index = FindBlockIndex(blamSbsp.Clusters, identifier);
                        desiredInstances.Add(index, desiredName);
                    }
                    else
                    {
                        Console.WriteLine("------------------------------------------------------------------");
                        Console.WriteLine("Enter each cluster with the format <Index> [New tagname]");
                        Console.WriteLine("Enter a blank line to finish.");
                        Console.WriteLine("------------------------------------------------------------------");
                        for (string line; !String.IsNullOrWhiteSpace(line = Console.ReadLine());)
                        {
                            var parts      = line.Split(' ');
                            var identifier = parts[0];
                            var name       = parts.Length > 1 ? string.Join(" ", parts.Skip(1)) : null;

                            var index = FindBlockIndex(blamSbsp.Clusters, identifier);
                            if (index == -1)
                            {
                                Console.WriteLine($"ERROR: Instance not found by identifier {identifier}!");
                                return(false);
                            }

                            desiredInstances.Add(index, name);
                        }
                    }

                    if (desiredInstances.Count < 1)
                    {
                        return(true);
                    }

                    var converter = new GeometryToObjectConverter(HoCache, hoCacheStream, BlamCache, blamCacheStream, blamScnr, sbspIndex);
                    converter.PortTag.SetFlags(portingFlags);


                    var forgTag = HoCache.TagCache.FindFirstInGroup("forg");
                    var forg    = HoCache.Deserialize <ForgeGlobalsDefinition>(hoCacheStream, forgTag);

                    var newTags = new List <CachedTag>();
                    foreach (var kv in desiredInstances)
                    {
                        try
                        {
                            var tag = converter.ConvertGeometry(kv.Key, kv.Value, true);

                            forg.Palette.Add(new ForgeGlobalsDefinition.PaletteItem()
                            {
                                CategoryIndex    = (short)1,
                                DescriptionIndex = -1,
                                Name             = tag.Name,
                                Object           = tag,
                                Type             = ForgeGlobalsDefinition.PaletteItemType.Prop,
                                Setters          = new List <ForgeGlobalsDefinition.PaletteItem.Setter>()
                                {
                                    new ForgeGlobalsDefinition.PaletteItem.Setter()
                                    {
                                        Target       = ForgeGlobalsDefinition.PaletteItem.SetterTarget.General_Physics,
                                        IntegerValue = 1 // phased
                                    }
                                }
                            });
                        }
                        finally
                        {
                            HoCache.SaveStrings();
                            HoCache.SaveTagNames();
                        }
                    }
                    HoCache.Serialize(hoCacheStream, forgTag, forg);
                }

            return(true);
        }
Beispiel #8
0
        public RenderObject(D3DDevice device, GameCache cache, GameObject definition, RealPoint3d position, RealEulerAngles3d rotation)
        {
            if (device == null)
            {
                throw new ArgumentNullException(nameof(device));
            }
            else if (cache == null)
            {
                throw new ArgumentNullException(nameof(cache));
            }
            else if (definition == null)
            {
                throw new ArgumentNullException(nameof(definition));
            }

            Device = device;
            Cache  = cache;
            Object = definition;

            Position = position;
            Rotation = rotation;
            UpdateTransform();

            using (var cacheStream = Cache.OpenCacheRead())
            {
                if (Object.Model == null)
                {
                    throw new NullReferenceException(nameof(Object.Model));
                }

                Model = Cache.Deserialize <Model>(cacheStream, Object.Model);

                if (Model.RenderModel == null)
                {
                    throw new NullReferenceException(nameof(Model.RenderModel));
                }

                RenderModel = Cache.Deserialize <RenderModel>(cacheStream, Model.RenderModel);

                if (Model.Variants == null || Model.Variants.Count == 0)
                {
                    var modelVariant = new Model.Variant
                    {
                        Name    = Cache.StringTable.GetStringId("default"),
                        Regions = new List <Model.Variant.Region>()
                    };

                    foreach (var region in RenderModel.Regions)
                    {
                        var modelRegion = new Model.Variant.Region
                        {
                            Name = region.Name,
                            RenderModelRegionIndex = (sbyte)RenderModel.Regions.IndexOf(region),
                            Permutations           = new List <Model.Variant.Region.Permutation>()
                        };

                        foreach (var permutation in region.Permutations)
                        {
                            modelRegion.Permutations.Add(new Model.Variant.Region.Permutation
                            {
                                Name = modelVariant.Name,
                                RenderModelPermutationIndex = (sbyte)region.Permutations.IndexOf(permutation)
                            });
                        }

                        modelVariant.Regions.Add(modelRegion);
                    }

                    Model.Variants = new List <Model.Variant> {
                        modelVariant
                    };
                }

                Materials = new List <RenderMaterial>();

                foreach (var material in RenderModel.Materials)
                {
                    Materials.Add(new RenderMaterial(device, Cache, material));
                }

                if (RenderModel.Geometry.Resource == null)
                {
                    throw new NullReferenceException(nameof(RenderModel.Geometry.Resource));
                }

                RenderGeometryResource = Cache.ResourceCache.GetRenderGeometryApiResourceDefinition(RenderModel.Geometry.Resource);

                VertexBuffers = new Dictionary <int, VertexBuffer>();
                IndexBuffers  = new Dictionary <int, IndexBuffer>();

                var compression = RenderModel.Geometry.Compression[0];

                foreach (var mesh in RenderModel.Geometry.Meshes)
                {
                    var renderVertex = VertexDefinition.Get(mesh.Type);
                    var streamTypes  = renderVertex.GetStreamTypes();

                    foreach (var streamEntry in streamTypes)
                    {
                        var vertexBufferIndex = mesh.VertexBufferIndices[streamEntry.Key];

                        if (vertexBufferIndex == -1 || VertexBuffers.ContainsKey(vertexBufferIndex))
                        {
                            continue;
                        }

                        var vbDef = RenderGeometryResource.VertexBuffers[vertexBufferIndex].Definition;

                        var vb     = new VertexBuffer(streamEntry.Value, vbDef.Data.Data.Length, device, Usage.DoNotClip, renderVertex.GetStreamFormat(streamEntry.Key), Pool.Managed);
                        var vbData = vb.Lock(0, vbDef.Data.Data.Length, LockFlags.None);

                        var vertices = Array.CreateInstance(streamEntry.Value, vbDef.Count);

                        using (var vbDefData = new MemoryStream(vbDef.Data.Data))
                            using (var vbDefReader = new BinaryReader(vbDefData))
                            {
                                for (var i = 0; i < vbDef.Count; i++)
                                {
                                    var handle = GCHandle.Alloc(vbDefReader.ReadBytes(Marshal.SizeOf(streamEntry.Value)), GCHandleType.Pinned);
                                    var vertex = Marshal.PtrToStructure(handle.AddrOfPinnedObject(), streamEntry.Value);

                                    var positionField = streamEntry.Value.GetField("Position");

                                    if (positionField != null)
                                    {
                                        var xyz = (Vector3)positionField.GetValue(vertex);

                                        positionField.SetValue(vertex, new Vector3(
                                                                   xyz.X * compression.X.Length + compression.X.Lower,
                                                                   xyz.Y * compression.Y.Length + compression.Y.Lower,
                                                                   xyz.Z * compression.Z.Length + compression.Z.Lower));
                                    }

                                    var texcoordField = streamEntry.Value.GetField("Texcoord");

                                    if (texcoordField != null)
                                    {
                                        var uv = (Vector2)texcoordField.GetValue(vertex);

                                        texcoordField.SetValue(vertex, new Vector2(
                                                                   uv.X * compression.U.Length + compression.U.Lower,
                                                                   uv.Y * compression.V.Length + compression.V.Lower));
                                    }

                                    vertices.SetValue(vertex, i);

                                    handle.Free();
                                }
                            }

                        vbData.Write(vertices);
                        vb.Unlock();

                        VertexBuffers[vertexBufferIndex] = vb;
                    }

                    foreach (var indexBufferIndex in mesh.IndexBufferIndices)
                    {
                        if (indexBufferIndex == -1 /*ushort.MaxValue*/ || IndexBuffers.ContainsKey(indexBufferIndex))
                        {
                            continue;
                        }

                        var ibDef = RenderGeometryResource.IndexBuffers[indexBufferIndex].Definition;

                        switch (ibDef.Format)
                        {
                        case IndexBufferFormat.PointList:
                            mesh.IndexBufferType = TagPrimitiveType.PointList;
                            break;

                        case IndexBufferFormat.LineList:
                            mesh.IndexBufferType = TagPrimitiveType.LineList;
                            break;

                        case IndexBufferFormat.LineStrip:
                            mesh.IndexBufferType = TagPrimitiveType.LineStrip;
                            break;

                        case IndexBufferFormat.TriangleList:
                            mesh.IndexBufferType = TagPrimitiveType.TriangleList;
                            break;

                        case IndexBufferFormat.TriangleFan:
                            mesh.IndexBufferType = TagPrimitiveType.TriangleFan;
                            break;

                        case IndexBufferFormat.TriangleStrip:
                            mesh.IndexBufferType = TagPrimitiveType.TriangleStrip;
                            break;
                        }

                        var ib     = new IndexBuffer(device, ibDef.Data.Data.Length, Usage.DoNotClip, Pool.Managed, true);
                        var ibData = ib.Lock(0, ibDef.Data.Data.Length, LockFlags.None);

                        /*resourceStream.Position = ibDef.Data.Address.Offset;
                         *
                         * var indices = new ushort[ibDef.Data.Data.Length / 2];
                         *
                         * for (var i = 0; i < ibDef.Data.Data.Length / 2; i++)
                         *  indices[i] = reader.ReadUInt16();*/

                        // may not work, hard to test (original code above)
                        short[] indices = new short[(int)Math.Ceiling(ibDef.Data.Data.Length / 2.0)];
                        Buffer.BlockCopy(ibDef.Data.Data, 0, indices, 0, ibDef.Data.Data.Length);

                        ibData.Write(indices);
                        ib.Unlock();

                        IndexBuffers[indexBufferIndex] = ib;
                    }
                }
            }
        }
Beispiel #9
0
        private List <ShaderTemplateItem> CollectRmt2Info(Stream cacheStream, CachedTag bmRmt2Instance, List <string> bmMaps, List <string> bmArgs)
        {
            var edRmt2BestStats = new List <ShaderTemplateItem>();

            RenderMethodTemplate bmRmt2;
            PixelShader          bmPixl;

            using (var blamStream = BlamCache.OpenCacheRead())
            {
                bmRmt2 = BlamCache.Deserialize <RenderMethodTemplate>(blamStream, bmRmt2Instance);
                bmPixl = BlamCache.Deserialize <PixelShader>(blamStream, bmRmt2.PixelShader);
            }


            // loop trough all rmt2 and find the closest
            foreach (var edRmt2_ in Rmt2TagsInfo)
            {
                var rmt2Type = bmRmt2Instance.Name.Split("\\".ToArray())[1];

                var edRmt2Tag = (CachedTagHaloOnline)CacheContext.TagCache.GetTag(edRmt2_.Key);

                // Ignore all rmt2 that are not of the same type.
                if (edRmt2Tag == null || !(edRmt2Tag.Name?.Contains(rmt2Type) ?? false))
                {
                    continue;
                }

                using (var reader = new EndianReader(cacheStream, true))
                {
                    reader.SeekTo(edRmt2Tag.HeaderOffset + edRmt2Tag.DefinitionOffset + 28);
                    var edPixl = (CachedTagHaloOnline)CacheContext.TagCache.GetTag(reader.ReadInt32());

                    if (edPixl == null)
                    {
                        continue;
                    }

                    reader.SeekTo(edPixl.HeaderOffset + edPixl.DefinitionOffset + 0x4);
                    var drawModeCount = reader.ReadInt32();

                    reader.SeekTo(edPixl.HeaderOffset + edPixl.DefinitionOffset + 0x14);
                    var shaderCount = reader.ReadInt32();

                    if (bmPixl.DrawModes.Count > drawModeCount || bmPixl.Shaders.Count > shaderCount)
                    {
                        continue;
                    }
                }

                int mapsCommon   = 0;
                int argsCommon   = 0;
                int mapsUncommon = 0;
                int argsUncommon = 0;
                int mapsMissing  = 0;
                int argsMissing  = 0;

                var edMaps_ = new List <string>();
                var edArgs_ = new List <string>();

                foreach (var a in edRmt2_.Value[0])
                {
                    edMaps_.Add(a);
                }

                foreach (var a in edRmt2_.Value[1])
                {
                    edArgs_.Add(a);
                }

                foreach (var a in bmMaps)
                {
                    if (edMaps_.Contains(a))
                    {
                        mapsCommon++;
                    }
                }

                foreach (var a in bmMaps)
                {
                    if (!edMaps_.Contains(a))
                    {
                        mapsMissing++;
                    }
                }

                foreach (var a in edMaps_)
                {
                    if (!bmMaps.Contains(a))
                    {
                        mapsUncommon++;
                    }
                }

                foreach (var a in bmArgs)
                {
                    if (edArgs_.Contains(a))
                    {
                        argsCommon++;
                    }
                }

                foreach (var a in bmArgs)
                {
                    if (!edArgs_.Contains(a))
                    {
                        argsMissing++;
                    }
                }

                foreach (var a in edArgs_)
                {
                    if (!bmArgs.Contains(a))
                    {
                        argsUncommon++;
                    }
                }

                edRmt2BestStats.Add(new ShaderTemplateItem
                {
                    rmt2TagIndex            = edRmt2_.Key,
                    rmdfValuesMatchingCount = 0,
                    mapsCountEd             = edRmt2_.Value[0].Count,
                    argsCountEd             = edRmt2_.Value[1].Count,
                    mapsCountBm             = bmMaps.Count,
                    argsCountBm             = bmArgs.Count,
                    mapsCommon   = mapsCommon,
                    argsCommon   = argsCommon,
                    mapsUncommon = mapsUncommon,
                    argsUncommon = argsUncommon,
                    mapsMissing  = mapsMissing,
                    argsMissing  = argsMissing
                });
            }

            return(edRmt2BestStats);
        }
        public override object Execute(List <string> args)
        {
            var argStack = new Stack <string>(args.AsEnumerable().Reverse());

            var portingFlags = ParsePortingFlags(argStack);

            if (argStack.Count < 1)
            {
                Console.WriteLine("ERROR: Expected bsp index!");
                return(false);
            }

            var sbspIndex = int.Parse(argStack.Pop());

            using (var blamCacheStream = BlamCache.OpenCacheRead())
                using (var hoCacheStream = HoCache.OpenCacheReadWrite())
                {
                    var blamScnr = BlamCache.Deserialize <Scenario>(blamCacheStream, BlamCache.TagCache.FindFirstInGroup("scnr"));
                    var blamSbsp = BlamCache.Deserialize <ScenarioStructureBsp>(blamCacheStream, blamScnr.StructureBsps[sbspIndex].StructureBsp);

                    var desiredInstances = new Dictionary <int, string>();

                    if (argStack.Count > 0)
                    {
                        var    identifier  = argStack.Pop();
                        string desiredName = null;
                        if (argStack.Count > 0)
                        {
                            desiredName = argStack.Pop();
                        }

                        var index = FindBlockIndex(blamSbsp.InstancedGeometryInstances, identifier);
                        desiredInstances.Add(index, desiredName);
                    }
                    else
                    {
                        Console.WriteLine("------------------------------------------------------------------");
                        Console.WriteLine("Enter each instance with the format <Name or Index> [New tagname]");
                        Console.WriteLine("Enter a blank line to finish.");
                        Console.WriteLine("------------------------------------------------------------------");
                        for (string line; !String.IsNullOrWhiteSpace(line = Console.ReadLine());)
                        {
                            var parts      = line.Split(' ');
                            var identifier = parts[0];
                            var name       = parts.Length > 1 ? string.Join(" ", parts.Skip(1)) : null;

                            var index = FindBlockIndex(blamSbsp.InstancedGeometryInstances, identifier);
                            if (index == -1)
                            {
                                Console.WriteLine($"ERROR: Instance not found by identifier {identifier}!");
                                return(false);
                            }

                            desiredInstances.Add(index, name);
                        }
                    }

                    if (desiredInstances.Count < 1)
                    {
                        return(true);
                    }

                    var converter = new GeometryToObjectConverter(HoCache, hoCacheStream, BlamCache, blamCacheStream, blamScnr, sbspIndex);
                    converter.PortTag.SetFlags(portingFlags);

                    foreach (var kv in desiredInstances)
                    {
                        try
                        {
                            var instance = blamSbsp.InstancedGeometryInstances[kv.Key];
                            var tag      = converter.ConvertGeometry(kv.Key, kv.Value);
                        }
                        finally
                        {
                            HoCache.SaveStrings();
                            HoCache.SaveTagNames();
                        }
                    }
                }

            return(true);
        }