A serialization context for serializing and deserializing tags.
상속: ISerializationContext
예제 #1
0
        public override bool Execute(List<string> args)
        {
            if (args.Count != 1)
                return false;

            var groupTag = ArgumentParser.ParseGroupTag(Info.StringIDs, args[0]);

            if (groupTag == null || !TagGroup.Instances.ContainsKey(groupTag))
                return false;

            TagInstance instance;

            using (var stream = Info.OpenCacheReadWrite())
            {
                instance = Info.Cache.AllocateTag(TagGroup.Instances[groupTag]);
                var context = new TagSerializationContext(stream, Info.Cache, Info.StringIDs, instance);
                var data = Activator.CreateInstance(TagStructureTypes.FindByGroupTag(groupTag));
                Info.Serializer.Serialize(context, data);
            }

            var tagName = Info.TagNames.ContainsKey(instance.Index) ?
                Info.TagNames[instance.Index] :
                $"0x{instance.Index:X4}";

            Console.WriteLine($"[Index: 0x{instance.Index:X4}, Offset: 0x{instance.HeaderOffset:X8}, Size: 0x{instance.TotalSize:X4}] {tagName}.{Info.StringIDs.GetString(instance.Group.Name)}");

            return true;
        }
예제 #2
0
        public override bool Execute(List<string> args)
        {
            if (args.Count != 0)
                return false;

            foreach (var property in Definition.ShaderProperties)
            {
                RenderMethodTemplate template = null;

                using (var cacheStream = Info.CacheFile.Open(FileMode.Open, FileAccess.Read))
                {
                    var context = new TagSerializationContext(cacheStream, Info.Cache, Info.StringIDs, property.Template);
                    template = Info.Deserializer.Deserialize<RenderMethodTemplate>(context);
                }

                for (var i = 0; i < template.ShaderMaps.Count; i++)
                {
                    var mapTemplate = template.ShaderMaps[i];

                    Console.WriteLine($"Bitmap {i} ({Info.StringIDs.GetString(mapTemplate.Name)}): {property.ShaderMaps[i].Bitmap.Group.Tag} 0x{property.ShaderMaps[i].Bitmap.Index:X4}");
                }
            }

            return true;
        }
예제 #3
0
        private bool ImportAnimationResource(TagInstance tagIndex, string cachePath, string dataPath)
        {
            ModelAnimationGraph animation;
            ResourceCache resourceCache;
            uint compressedSize = 0;
            var data = File.ReadAllBytes(dataPath);

            using (var cacheStream = _info.OpenCacheReadWrite())
            {
                var tagContext = new TagSerializationContext(cacheStream, _info.Cache, _info.StringIDs, tagIndex);
                animation = _info.Deserializer.Deserialize<ModelAnimationGraph>(tagContext);
            }
            using (var stream = File.Open(_info.CacheFile.DirectoryName + "\\" + cachePath, FileMode.Open, FileAccess.ReadWrite))
            {
                resourceCache = new ResourceCache(stream);
                animation.ResourceGroups[0].Resource.Index = resourceCache.Add(stream, data, out compressedSize);
                animation.ResourceGroups[0].Resource.CompressedSize = compressedSize;
                animation.ResourceGroups[0].Resource.OldLocationFlags = (OldResourceLocationFlags)2;
            }
            using (var cacheStream = _fileInfo.Open(FileMode.Open, FileAccess.ReadWrite))
            {
                var context = new TagSerializationContext(cacheStream, _cache, _stringIds, tagIndex);
                _info.Serializer.Serialize(context, animation);
            }
            Console.WriteLine("{1}: Imported 0x{0}.", compressedSize, tagIndex);
            return true;
        }
예제 #4
0
        public override bool Execute(List<string> args)
        {
            if (args.Count != 1)
                return false;

            var outDir = args[0];
            Directory.CreateDirectory(outDir);

            Console.WriteLine("Loading resource caches...");
            var resourceManager = new ResourceDataManager();
            try
            {
                resourceManager.LoadCachesFromDirectory(_info.CacheFile.DirectoryName);
            }
            catch
            {
                Console.WriteLine("Unable to load the resource .dat files.");
                Console.WriteLine("Make sure that they all exist and are valid.");
                return true;
            }

            var extractor = new BitmapDdsExtractor(resourceManager);
            var count = 0;
            using (var tagsStream = _info.OpenCacheRead())
            {
                foreach (var tag in _info.Cache.Tags.FindAllInGroup("bitm"))
                {
                    Console.Write("Extracting ");
                    TagPrinter.PrintTagShort(tag);

                    try
                    {
                        var tagContext = new TagSerializationContext(tagsStream, _info.Cache, _info.StringIDs, tag);
                        var bitmap = _info.Deserializer.Deserialize<TagDefinitions.Bitmap>(tagContext);
                        var ddsOutDir = outDir;
                        if (bitmap.Images.Count > 1)
                        {
                            ddsOutDir = Path.Combine(outDir, tag.Index.ToString("X8"));
                            Directory.CreateDirectory(ddsOutDir);
                        }
                        for (var i = 0; i < bitmap.Images.Count; i++)
                        {
                            var outPath = Path.Combine(ddsOutDir,
                                ((bitmap.Images.Count > 1) ? i.ToString() : tag.Index.ToString("X8")) + ".dds");
                            using (var outStream = File.Open(outPath, FileMode.Create, FileAccess.Write))
                            {
                                extractor.ExtractDds(_info.Deserializer, bitmap, i, outStream);
                            }
                        }
                        count++;
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("ERROR: Failed to extract bitmap: " + ex.Message);
                    }
                }
            }
            Console.WriteLine("Extracted {0} bitmaps.", count);
            return true;
        }
예제 #5
0
        public override bool Execute(List<string> args)
        {
            if (args.Count != 0)
                return false;

            var shaderMaps = new Dictionary<StringID, TagInstance>();

            foreach (var property in Definition.ShaderProperties)
            {
                RenderMethodTemplate template = null;

                using (var cacheStream = Info.CacheFile.Open(FileMode.Open, FileAccess.Read))
                {
                    var context = new TagSerializationContext(cacheStream, Info.Cache, Info.StringIDs, property.Template);
                    template = Info.Deserializer.Deserialize<RenderMethodTemplate>(context);
                }

                for (var i = 0; i < template.ShaderMaps.Count; i++)
                {
                    var mapTemplate = template.ShaderMaps[i];

                    Console.Write(string.Format("Please enter the {0} index: ", Info.StringIDs.GetString(mapTemplate.Name)));
                    shaderMaps[mapTemplate.Name] = ArgumentParser.ParseTagIndex(Info, Console.ReadLine());
                    property.ShaderMaps[i].Bitmap = shaderMaps[mapTemplate.Name];
                }
            }

            foreach (var import in Definition.ImportData)
                if (shaderMaps.ContainsKey(import.MaterialType))
                    import.Bitmap = shaderMaps[import.MaterialType];

            using (var cacheStream = Info.CacheFile.Open(FileMode.Open, FileAccess.ReadWrite))
            {
                var context = new TagSerializationContext(cacheStream, Info.Cache, Info.StringIDs, Tag);
                Info.Serializer.Serialize(context, Definition);
            }

            Console.WriteLine("Done!");

            return true;
        }
예제 #6
0
        public override bool Execute(List<string> args)
        {
            foreach (var material in Definition.Materials)
            {
                if (material.RenderMethod != null)
                    Console.Write("Please enter the replacement {0:X8} index: ", material.RenderMethod.Index);
                else
                    Console.Write("Please enter the replace material #{0} index: ", Definition.Materials.IndexOf(material));

                material.RenderMethod = ArgumentParser.ParseTagIndex(Info, Console.ReadLine());
            }

            using (var cacheStream = Info.CacheFile.Open(FileMode.Open, FileAccess.ReadWrite))
            {
                var context = new TagSerializationContext(cacheStream, Info.Cache, Info.StringIDs, Tag);
                Info.Serializer.Serialize(context, Definition);
            }

            Console.WriteLine("Done!");

            return true;
        }
예제 #7
0
 public TagDataBlock(TagSerializationContext context)
 {
     _context = context;
     Stream   = new MemoryStream();
     Writer   = new BinaryWriter(Stream);
 }
예제 #8
0
        public override bool Execute(List<string> args)
        {
            if (args.Count != 0)
                return false;

            // Load resource caches
            Console.WriteLine("Loading resource caches...");
            var resourceManager = new ResourceDataManager();
            try
            {
                resourceManager.LoadCachesFromDirectory(Info.CacheFile.DirectoryName);
            }
            catch
            {
                Console.WriteLine("Unable to load the resource .dat files.");
                Console.WriteLine("Make sure that they all exist and are valid.");
                return true;
            }

            if (BSP.CollisionBSPResource == null)
            {
                Console.WriteLine("Collision BSP does not have a resource associated with it.");
                return true;
            }

            // Deserialize the collision resource definition
            var resourceContext = new ResourceSerializationContext(BSP.CollisionBSPResource);
            var definition = Info.Deserializer.Deserialize<CollisionBSPResourceDefinition>(resourceContext);

            // Reserialize the collision resource definition
            Info.Serializer.Serialize(resourceContext, definition);

            // Reserialize the tag definition
            using (var cacheStream = Info.OpenCacheReadWrite())
            {
                var tagContext = new TagSerializationContext(cacheStream, Info.Cache, Info.StringIDs, Tag);
                Info.Serializer.Serialize(tagContext, BSP);
            }

            return true;
        }
예제 #9
0
        public override bool Execute(List<string> args)
        {
            if (args.Count != 1)
                return false;

            //
            // Verify and load the blam shader
            //

            var shaderName = args[0];

            CacheBase.IndexItem item = null;

            Console.WriteLine("Verifying blam shader tag...");

            foreach (var tag in BlamCache.IndexItems)
            {
                if ((tag.ParentClass == "rm") && tag.Filename == shaderName)
                {
                    item = tag;
                    break;
                }
            }

            if (item == null)
            {
                Console.WriteLine("Blam shader tag does not exist: " + shaderName);
                return false;
            }

            var renderMethod = DefinitionsManager.rmsh(BlamCache, item);

            var templateItem = BlamCache.IndexItems.Find(i =>
                i.ID == renderMethod.Properties[0].TemplateTagID);

            var template = DefinitionsManager.rmt2(BlamCache, templateItem);

            //
            // Determine the blam shader's base bitmap
            //

            var bitmapIndex = -1;
            var bitmapArgName = "";

            for (var i = 0; i < template.UsageBlocks.Count; i++)
            {
                var entry = template.UsageBlocks[i];

                if (entry.Usage.StartsWith("base_map") ||
                    entry.Usage.StartsWith("diffuse_map") ||
                    entry.Usage == "foam_texture")
                {
                    bitmapIndex = i;
                    bitmapArgName = entry.Usage;
                    break;
                }
            }

            //
            // Load and decode the blam shader's base bitmap
            //

            var bitmItem = BlamCache.IndexItems.Find(i =>
                i.ID == renderMethod.Properties[0].ShaderMaps[bitmapIndex].BitmapTagID);

            var bitm = DefinitionsManager.bitm(BlamCache, bitmItem);
            var submap = bitm.Bitmaps[0];

            byte[] raw;

            if (BlamCache.Version <= DefinitionSet.Halo2Vista)
                raw = BlamCache.GetRawFromID(submap.PixelsOffset, submap.RawSize);
            else
            {
                if (bitm.RawChunkBs.Count > 0)
                {
                    int rawID = bitm.RawChunkBs[submap.InterleavedIndex].RawID;
                    byte[] buffer = BlamCache.GetRawFromID(rawID);
                    raw = new byte[submap.RawSize];
                    Array.Copy(buffer, submap.Index2 * submap.RawSize, raw, 0, submap.RawSize);
                }
                else
                {
                    int rawID = bitm.RawChunkAs[0].RawID;
                    raw = BlamCache.GetRawFromID(rawID, submap.RawSize);
                }
            }

            var vHeight = submap.VirtualHeight;
            var vWidth = submap.VirtualWidth;

            var ms = new MemoryStream();
            var bw = new BinaryWriter(ms);

            if (submap.Flags.Values[3])
                raw = DXTDecoder.ConvertToLinearTexture(raw, vWidth, vHeight, submap.Format);

            if (submap.Format != BitmapFormat.A8R8G8B8)
                for (int i = 0; i < raw.Length; i += 2)
                    Array.Reverse(raw, i, 2);
            else
                for (int i = 0; i < (raw.Length); i += 4)
                    Array.Reverse(raw, i, 4);

            new DDS(submap).Write(bw);
            bw.Write(raw);

            raw = ms.ToArray();

            bw.Close();
            bw.Dispose();

            //
            // ElDorado Serialization
            //

            using (var cacheStream = Info.CacheFile.Open(FileMode.Open, FileAccess.ReadWrite))
            {
                //
                // Create the new eldorado bitmap
                //

                var resourceManager = new ResourceDataManager();
                resourceManager.LoadCachesFromDirectory(Info.CacheFile.DirectoryName);

                var newBitm = Info.Cache.DuplicateTag(cacheStream, Info.Cache.Tags[0x101F]);

                var bitmap = new TagDefinitions.Bitmap
                {
                    Flags = TagDefinitions.Bitmap.RuntimeFlags.UseResource,
                    Sequences = new List<TagDefinitions.Bitmap.Sequence>
                    {
                        new TagDefinitions.Bitmap.Sequence
                        {
                            Name = "",
                            FirstBitmapIndex = 0,
                            BitmapCount = 1
                        }
                    },
                    Images = new List<TagDefinitions.Bitmap.Image>
                    {
                        new TagDefinitions.Bitmap.Image
                        {
                            Signature = new Tag("bitm").Value,
                            Unknown28 = -1
                        }
                    },
                    Resources = new List<TagDefinitions.Bitmap.BitmapResource>
                    {
                        new TagDefinitions.Bitmap.BitmapResource()
                    }
                };

                using (var imageStream = new MemoryStream(raw))
                {
                    var injector = new BitmapDdsInjector(resourceManager);
                    imageStream.Seek(0, SeekOrigin.Begin);
                    injector.InjectDds(Info.Serializer, Info.Deserializer, bitmap, 0, imageStream);
                }

                var context = new TagSerializationContext(cacheStream, Info.Cache, Info.StringIDs, newBitm);
                Info.Serializer.Serialize(context, bitmap);

                //
                // Create the new eldorado shader
                //

                var newRmsh = Info.Cache.DuplicateTag(cacheStream, Info.Cache.Tags[0x331A]);
                context = new TagSerializationContext(cacheStream, Info.Cache, Info.StringIDs, newRmsh);
                var shader = Info.Deserializer.Deserialize<TagDefinitions.Shader>(context);

                shader.ShaderProperties[0].ShaderMaps[0].Bitmap = newBitm;

                Info.Serializer.Serialize(context, shader);

                Console.WriteLine("Done! New shader tag is 0x" + newRmsh.Index.ToString("X8"));
            }

            return true;
        }
        public override bool Execute(List<string> args)
        {
            //Arguments needed: filepath, <new>|<tagIndex>
            if (args.Count < 2)
            {
                return false;
            }

            TagInstance tag = null;
            bool b_duplicate;

            // optional argument: forces overwriting of tags that are not type: coll
            var b_force = (args.Count >= 3 && args[2].ToLower().Equals("force"));

            if (args[1].ToLower().Equals("new"))
            {
                b_duplicate = true;
            }
            else
            {
                tag = ArgumentParser.ParseTagIndex(Info, args[1]);
                if (tag == null)
                {
                    return false;
                }
                b_duplicate = false;
            }

            if (!b_force && !b_duplicate && !tag.IsInGroup("coll"))
            {
                Console.WriteLine("Tag to override was not of class- 'coll'. Use third argument- 'force' to inject into this tag.");
                return false;
            }

            string filepath = args[0];
            string[] fpaths = null;
            CollisionModel coll = null;
            bool b_singleFile = Path.GetExtension(filepath).Equals(".model_collision_geometry")
                && !Directory.Exists(filepath);

            var modelbuilder = new CollisionGeometryBuilder();
            int n_objects = 1;

            if (!b_singleFile)
            {
                fpaths = Directory.GetFiles(filepath, "*.model_collision_geometry");

                if (fpaths.Length == 0)
                {
                    Console.WriteLine("No Halo 1 coll tags in directory: \"{0}\"", filepath);
                    return false;
                }

                filepath = fpaths[0];
                n_objects = fpaths.Length;
            }

            Console.WriteLine(
                (n_objects == 1 ? "Loading coll tag..." : "Loading coll tags..."), n_objects);

            if (!modelbuilder.ParseFromFile(filepath))
                return false;

            coll = modelbuilder.Build();

            if (coll == null)
            {
                Console.WriteLine("Builder produced null result.");
                return false;
            }

            if (!b_singleFile)
            {
                for (int i = 1; i < fpaths.Length; ++i)
                {
                    if (!modelbuilder.ParseFromFile(fpaths[i]))
                        return false;

                    var coll2 = modelbuilder.Build();

                    if (coll2 == null)
                    {
                        Console.WriteLine("Builder produced null result.");
                        return false;
                    }

                    coll.Regions.Add(coll2.Regions[0]);
                }
            }

            using (var stream = Info.OpenCacheReadWrite())
            {

                if (b_duplicate)
                {
                    //duplicate an existing tag, trashcan phmo
                    tag = Info.Cache.DuplicateTag(stream, Info.Cache.Tags[0x4436]);
                    if (tag == null)
                    {
                        Console.WriteLine("Failed tag duplication.");
                        return false;
                    }
                }

                var context = new TagSerializationContext(stream, Info.Cache, Info.StringIDs, tag);
                Info.Serializer.Serialize(context, coll);

            }
            Console.WriteLine(
                (n_objects == 1 ? "Added 1 collision." : "Added {0} collisions in one tag."), n_objects);
            Console.Write("Successfully imported coll to: ");
            TagPrinter.PrintTagShort(tag);

            return true;
        }
예제 #11
0
        public override bool Execute(List<string> args)
        {
            if (args.Count != 2)
                return false;

            var tag = ArgumentParser.ParseTagIndex(Info, args[0]);
            var imagePath = args[1];

            Console.WriteLine("Loading textures.dat...");
            var resourceManager = new ResourceDataManager();
            resourceManager.LoadCacheFromDirectory(Info.CacheFile.DirectoryName, ResourceLocation.Textures);

            Console.WriteLine("Importing image...");
            var bitmap = new TagDefinitions.Bitmap
            {
                Flags = TagDefinitions.Bitmap.RuntimeFlags.UseResource,
                Sequences = new List<TagDefinitions.Bitmap.Sequence>
                {
                    new TagDefinitions.Bitmap.Sequence
                    {
                        FirstBitmapIndex = 0,
                        BitmapCount = 1
                    }
                },
                Images = new List<TagDefinitions.Bitmap.Image>
                {
                    new TagDefinitions.Bitmap.Image
                    {
                        Signature = new Tag("bitm").Value,
                        Unknown28 = -1,
                    }
                },
                Resources = new List<TagDefinitions.Bitmap.BitmapResource>
                {
                    new TagDefinitions.Bitmap.BitmapResource()
                }
            };
            using (var imageStream = File.OpenRead(imagePath))
            {
                var injector = new BitmapDdsInjector(resourceManager);
                injector.InjectDds(Info.Serializer, Info.Deserializer, bitmap, 0, imageStream);
            }

            Console.WriteLine("Creating a new tag...");

            using (var tagsStream = Info.OpenCacheReadWrite())
            {
                var tagContext = new TagSerializationContext(tagsStream, Info.Cache, Info.StringIDs, tag);
                Info.Serializer.Serialize(tagContext, bitmap);
            }

            Console.WriteLine();
            Console.WriteLine("All done! The new bitmap tag is:");
            TagPrinter.PrintTagShort(tag);
            return true;
        }
예제 #12
0
        public override bool Execute(List<string> args)
        {
            if (args.Count != 3)
                return false;

            var variantName = args[0];
            var fileType = args[1];
            var fileName = args[2];

            if (fileType != "obj" && fileType != "amf")
                return false;

            // Find the variant to extract
            if (Definition.RenderModel == null)
            {
                Console.WriteLine("The model does not have a render model associated with it.");
                return true;
            }

            var variant = Definition.Variants.FirstOrDefault(v => (Info.StringIDs.GetString(v.Name) ?? v.Name.ToString()) == variantName);
            if (variant == null && Definition.Variants.Count > 0)
            {
                Console.WriteLine("Unable to find variant \"{0}\"", variantName);
                Console.WriteLine("Use \"listvariants\" to list available variants.");
                return true;
            }

            if (fileType == "amf")
                return ExtractAMF(variant, fileName);

            // Load resource caches
            Console.WriteLine("Loading resource caches...");
            var resourceManager = new ResourceDataManager();
            try
            {
                resourceManager.LoadCachesFromDirectory(Info.CacheFile.DirectoryName);
            }
            catch
            {
                Console.WriteLine("Unable to load the resource .dat files.");
                Console.WriteLine("Make sure that they all exist and are valid.");
                return true;
            }

            // Deserialize the render model tag
            Console.WriteLine("Reading model data...");
            RenderModel renderModel;
            using (var cacheStream = Info.CacheFile.OpenRead())
            {
                var renderModelContext = new TagSerializationContext(cacheStream, Info.Cache, Info.StringIDs, Definition.RenderModel);
                renderModel = Info.Deserializer.Deserialize<RenderModel>(renderModelContext);
            }

            if (renderModel.Geometry.Resource == null)
            {
                Console.WriteLine("Render model does not have a resource associated with it");
                return true;
            }

            // Deserialize the resource definition
            var resourceContext = new ResourceSerializationContext(renderModel.Geometry.Resource);
            var definition = Info.Deserializer.Deserialize<RenderGeometryResourceDefinition>(resourceContext);

            using (var resourceStream = new MemoryStream())
            {
                // Extract the resource data
                resourceManager.Extract(renderModel.Geometry.Resource, resourceStream);

                Directory.CreateDirectory(Path.GetDirectoryName(fileName));

                using (var objFile = new StreamWriter(File.Open(fileName, FileMode.Create, FileAccess.Write)))
                {
                    var objExtractor = new ObjExtractor(objFile);
                    var vertexCompressor = new VertexCompressor(renderModel.Geometry.Compression[0]); // Create a (de)compressor from the first compression block

                    if (variant != null)
                    {
                        // Extract each region in the variant
                        foreach (var region in variant.Regions)
                        {
                            // Get the corresonding region in the render model tag
                            if (region.RenderModelRegionIndex >= renderModel.Regions.Count)
                                continue;

                            var renderModelRegion = renderModel.Regions[region.RenderModelRegionIndex];

                            // Get the corresponding permutation in the render model tag
                            // (Just extract the first permutation for now)
                            if (region.Permutations.Count == 0)
                                continue;

                            var permutation = region.Permutations[0];

                            if (permutation.RenderModelPermutationIndex < 0 ||
                                permutation.RenderModelPermutationIndex >= renderModelRegion.Permutations.Count)
                                continue;

                            var renderModelPermutation = renderModelRegion.Permutations[permutation.RenderModelPermutationIndex];

                            // Extract each mesh in the permutation
                            var meshIndex = renderModelPermutation.MeshIndex;
                            var meshCount = renderModelPermutation.MeshCount;
                            var regionName = Info.StringIDs.GetString(region.Name) ?? region.Name.ToString();
                            var permutationName = Info.StringIDs.GetString(permutation.Name) ?? permutation.Name.ToString();

                            Console.WriteLine("Extracting {0} mesh(es) for {1}:{2}...", meshCount, regionName, permutationName);

                            for (var i = 0; i < meshCount; i++)
                            {
                                // Create a MeshReader for the mesh and pass it to the obj extractor
                                var meshReader = new MeshReader(Info.Version, renderModel.Geometry.Meshes[meshIndex + i], definition);
                                objExtractor.ExtractMesh(meshReader, vertexCompressor, resourceStream);
                            }
                        }
                    }
                    else
                    {
                        // No variant - just extract every mesh
                        Console.WriteLine("Extracting {0} mesh(es)...", renderModel.Geometry.Meshes.Count);

                        foreach (var mesh in renderModel.Geometry.Meshes)
                        {
                            // Create a MeshReader for the mesh and pass it to the obj extractor
                            var meshReader = new MeshReader(Info.Version, mesh, definition);
                            objExtractor.ExtractMesh(meshReader, vertexCompressor, resourceStream);
                        }
                    }

                    objExtractor.Finish();
                }
            }
            Console.WriteLine("Done!");
            return true;
        }
예제 #13
0
        private bool ExtractAMF(Model.Variant variant, string fileName)
        {
            // Load resource caches
            Console.WriteLine("Loading resource caches...");
            var resourceManager = new ResourceDataManager();
            try
            {
                resourceManager.LoadCachesFromDirectory(Info.CacheFile.DirectoryName);
            }
            catch
            {
                Console.WriteLine("Unable to load the resource .dat files.");
                Console.WriteLine("Make sure that they all exist and are valid.");
                return true;
            }

            // Deserialize the render model tag
            Console.WriteLine("Reading model data...");
            RenderModel renderModel;
            using (var cacheStream = Info.CacheFile.OpenRead())
            {
                var renderModelContext = new TagSerializationContext(cacheStream, Info.Cache, Info.StringIDs, Definition.RenderModel);
                renderModel = Info.Deserializer.Deserialize<RenderModel>(renderModelContext);
            }

            if (renderModel.Geometry.Resource == null)
            {
                Console.WriteLine("Render model does not have a resource associated with it");
                return true;
            }

            // Deserialize the resource definition
            var resourceContext = new ResourceSerializationContext(renderModel.Geometry.Resource);
            var definition = Info.Deserializer.Deserialize<RenderGeometryResourceDefinition>(resourceContext);

            using (var resourceStream = new MemoryStream())
            {
                // Extract the resource data
                resourceManager.Extract(renderModel.Geometry.Resource, resourceStream);

                var regionMeshes = new Dictionary<string, Mesh>();

                foreach (var region in variant.Regions)
                {
                    regionMeshes[Info.StringIDs.GetString(region.Name)] = renderModel.Geometry.Meshes[region.RenderModelRegionIndex];
                }

                var headerAddressList = new List<int>();
                var headerValueList = new List<int>();
                var markerAddressList = new List<int>();
                var markerValueList = new List<int>();
                var permAddressList = new List<int>();
                var permValueList = new List<int>();
                var vertAddressList = new List<int>();
                var indxAddressList = new List<int>();
                var meshAddressList = new List<int>();

                using (var bw = new BinaryWriter(File.Create(fileName)))
                {
                    #region Header
                    bw.Write("AMF!".ToCharArray());
                    bw.Write(2.0f); //format version
                    bw.Write((Info.StringIDs.GetString(renderModel.Name) + "\0").ToCharArray());

                    bw.Write(renderModel.Nodes.Count);
                    headerAddressList.Add((int)bw.BaseStream.Position);
                    bw.Write(0);

                    bw.Write(renderModel.MarkerGroups.Count);
                    headerAddressList.Add((int)bw.BaseStream.Position);
                    bw.Write(0);

                    bw.Write(regionMeshes.Count);
                    headerAddressList.Add((int)bw.BaseStream.Position);
                    bw.Write(0);

                    bw.Write(renderModel.Materials.Count);
                    headerAddressList.Add((int)bw.BaseStream.Position);
                    bw.Write(0);
                    #endregion
                    #region Nodes
                    headerValueList.Add((int)bw.BaseStream.Position);
                    foreach (var node in renderModel.Nodes)
                    {
                        bw.Write((Info.StringIDs.GetString(node.Name) + "\0").ToCharArray());
                        bw.Write((short)node.ParentNode);
                        bw.Write((short)node.FirstChildNode);
                        bw.Write((short)node.NextSiblingNode);
                        bw.Write(node.DefaultTranslation.X * 100);
                        bw.Write(node.DefaultTranslation.Y * 100);
                        bw.Write(node.DefaultTranslation.Z * 100);
                        bw.Write(node.DefaultRotation.X);
                        bw.Write(node.DefaultRotation.Y);
                        bw.Write(node.DefaultRotation.Z);
                        bw.Write(node.DefaultRotation.W);
                    }
                    #endregion
                    #region Marker Groups
                    headerValueList.Add((int)bw.BaseStream.Position);
                    foreach (var group in renderModel.MarkerGroups)
                    {
                        bw.Write((Info.StringIDs.GetString(group.Name) + "\0").ToCharArray());
                        bw.Write(group.Markers.Count);
                        markerAddressList.Add((int)bw.BaseStream.Position);
                        bw.Write(0);
                    }
                    #endregion
                    #region Markers
                    foreach (var group in renderModel.MarkerGroups)
                    {
                        markerValueList.Add((int)bw.BaseStream.Position);
                        foreach (var marker in group.Markers)
                        {
                            bw.Write((byte)marker.RegionIndex);
                            bw.Write((byte)marker.PermutationIndex);
                            bw.Write((short)marker.NodeIndex);
                            bw.Write(marker.Translation.X * 100);
                            bw.Write(marker.Translation.Y * 100);
                            bw.Write(marker.Translation.Z * 100);
                            bw.Write(marker.Rotation.X);
                            bw.Write(marker.Rotation.Y);
                            bw.Write(marker.Rotation.Z);
                            bw.Write(marker.Rotation.W);
                        }
                    }
                    #endregion
                    #region Regions
                    headerValueList.Add((int)bw.BaseStream.Position);
                    foreach (var region in renderModel.Regions)
                    {
                        bw.Write((Info.StringIDs.GetString(region.Name) + "\0").ToCharArray());
                        bw.Write(regionMeshes.Count);
                        permAddressList.Add((int)bw.BaseStream.Position);
                        bw.Write(0);
                    }
                    #endregion
                    #region Permutations
                    foreach (var part in regionMeshes)
                    {
                        permValueList.Add((int)bw.BaseStream.Position);
                        bw.Write((Info.StringIDs.GetString(variant.Name) + "\0").ToCharArray());

                        if (part.Value.Type == VertexType.Rigid)
                            bw.Write((byte)1);
                        else if (part.Value.Type == VertexType.Skinned)
                            bw.Write((byte)2);
                        else
                            throw new NotImplementedException();

                        bw.Write((byte)part.Value.RigidNodeIndex);

                        bw.Write(definition.VertexBuffers[part.Value.VertexBuffers[0]].Definition.Count);
                        vertAddressList.Add((int)bw.BaseStream.Position);
                        bw.Write(0);

                        int count = 0;
                        foreach (var submesh in part.Value.SubParts)
                            count += submesh.IndexCount;

                        bw.Write(count);
                        indxAddressList.Add((int)bw.BaseStream.Position);
                        bw.Write(0);

                        bw.Write(part.Value.SubParts.Count);
                        meshAddressList.Add((int)bw.BaseStream.Position);
                        bw.Write(0);

                        bw.Write(float.NaN); //no transforms (render_models are pre-transformed)
                    }
                    #endregion
                }
            }

            return true;
        }
        public override bool Execute(List<string> args)
        {
            //Arguments needed: filepath, <new>|<tagIndex>
            if (args.Count < 2)
            {
                return false;
            }

            TagInstance tag = null;
            bool b_duplicate;
            // optional argument: forces overwriting of tags that are not type: phmo
            bool b_force = (args.Count >= 3 && args[2].ToLower().Equals("force"));

            if (args[1].ToLower().Equals("new"))
            {
                b_duplicate = true;
            }
            else
            {
                tag = ArgumentParser.ParseTagIndex(_info, args[1]);
                if (tag == null)
                {
                    return false;
                }
                b_duplicate = false;
            }

            if (!b_force && !b_duplicate && !tag.IsInGroup("phmo"))
            {
                Console.WriteLine("Tag to override was not of class- 'phmo'. Use third argument- 'force' to inject.");
                return false;
            }

            var filename = args[0];

            var modelbuilder = new PhysicsModelBuilder();
            if (!modelbuilder.ParseFromFile(filename))
            {
                return false;
            }
            //modelbuilder must also make a node for the physics model
            var phmo = modelbuilder.Build();

            if (phmo == null)
            {
                return false;
            }

            using (var stream = _info.OpenCacheReadWrite())
            {

                if (b_duplicate)
                {
                    //duplicate an existing tag, trashcan phmo
                    tag = _info.Cache.DuplicateTag(stream, _info.Cache.Tags[0x4436]);
                    if (tag == null)
                    {
                        Console.WriteLine("Failed tag duplication.");
                        return false;
                    }
                }

                var context = new TagSerializationContext(stream, _info.Cache, _info.StringIDs, tag);
                _info.Serializer.Serialize(context, phmo);

            }

            Console.Write("Successfully imported phmo to: ");
            TagPrinter.PrintTagShort(tag);

            return true;
        }
        public override bool Execute(List<string> args)
        {
            if (args.Count < 1 || args.Count > 2)
                return false;

            string palette = "all";

            if (args.Count == 2)
            {
                palette = args[0].ToLower();
                args.RemoveAt(0);
            }

            if (ValidPalettes.Find(i => i == palette) == null)
            {
                Console.WriteLine($"ERROR: invalid forge palette specified: {palette}");
                return false;
            }

            var destinationTag = ArgumentParser.ParseTagIndex(Info, args[0]);

            if (destinationTag == null || destinationTag.Group.Tag.ToString() != "scnr")
            {
                Console.WriteLine($"ERROR: invalid destination scenario index: {args[0]}");
                return false;
            }

            Console.Write("Loading destination scenario...");

            Scenario destinationScenario = null;

            using (var cacheStream = Info.CacheFile.Open(FileMode.Open, FileAccess.ReadWrite))
            {
                var scenarioContext = new TagSerializationContext(cacheStream, Info.Cache, Info.StringIDs, destinationTag);
                destinationScenario = Info.Deserializer.Deserialize<Scenario>(scenarioContext);
            }

            Console.WriteLine("done.");

            Console.Write("Copying specified forge palettes...");

            destinationScenario.SandboxBudget = Definition.SandboxBudget;

            if (palette == "all" || palette == "equipment")
                destinationScenario.SandboxEquipment = Definition.SandboxEquipment;

            if (palette == "all" || palette == "goal_objects")
                destinationScenario.SandboxGoalObjects = Definition.SandboxGoalObjects;

            if (palette == "all" || palette == "scenery")
                destinationScenario.SandboxScenery = Definition.SandboxScenery;

            if (palette == "all" || palette == "spawning")
                destinationScenario.SandboxSpawning = Definition.SandboxSpawning;

            if (palette == "all" || palette == "teleporters")
                destinationScenario.SandboxTeleporters = Definition.SandboxTeleporters;

            if (palette == "all" || palette == "vehicles")
                destinationScenario.SandboxVehicles = Definition.SandboxVehicles;

            if (palette == "all" || palette == "weapons")
                destinationScenario.SandboxWeapons = Definition.SandboxWeapons;

            Console.WriteLine("done.");

            Console.Write("Serializing destination scenario...");

            using (var cacheStream = Info.CacheFile.Open(FileMode.Open, FileAccess.ReadWrite))
            {
                var scenarioContext = new TagSerializationContext(cacheStream, Info.Cache, Info.StringIDs, destinationTag);
                Info.Serializer.Serialize(scenarioContext, destinationScenario);
            }

            Console.WriteLine("done.");

            return true;
        }
예제 #16
0
        private bool ImportModelResource(TagInstance tagIndex, string cachePath, string dataPath)
        {
            RenderModel renderModel;
            ResourceCache resourceCache;
            uint compressedSize = 0;
            var data = File.ReadAllBytes(dataPath);

            using (var cacheStream = _info.OpenCacheReadWrite())
            {
                var tagContext = new TagSerializationContext(cacheStream, _info.Cache, _info.StringIDs, tagIndex);
                renderModel = _info.Deserializer.Deserialize<RenderModel>(tagContext);
            }
            using (var stream = File.Open(_info.CacheFile.DirectoryName + "\\" + cachePath, FileMode.Open, FileAccess.ReadWrite))
            {
                resourceCache = new ResourceCache(stream);
                renderModel.Geometry.Resource.Index = resourceCache.Add(stream, data, out compressedSize);
                renderModel.Geometry.Resource.CompressedSize = compressedSize;
            }
            using (var cacheStream = _fileInfo.Open(FileMode.Open, FileAccess.ReadWrite))
            {
                var context = new TagSerializationContext(cacheStream, _cache, _stringIds, tagIndex);
                _info.Serializer.Serialize(context, renderModel);
            }
            Console.WriteLine("{1}: Imported 0x{0}.", compressedSize, tagIndex);
            return true;
        }
예제 #17
0
        public override bool Execute(List<string> args)
        {
            if (args.Count != 2)
                return false;
            int imageIndex;
            if (!int.TryParse(args[0], NumberStyles.HexNumber, null, out imageIndex))
                return false;
            if (imageIndex < 0 || imageIndex >= Bitmap.Images.Count)
            {
                Console.Error.WriteLine("Invalid image index.");
                return true;
            }
            var imagePath = args[1];

            Console.WriteLine("Loading resource caches...");
            var resourceManager = new ResourceDataManager();
            try
            {
                resourceManager.LoadCachesFromDirectory(Info.CacheFile.DirectoryName);
            }
            catch
            {
                Console.WriteLine("Unable to load the resource .dat files.");
                Console.WriteLine("Make sure that they all exist and are valid.");
                return true;
            }
            Console.WriteLine("Importing image data...");
            try
            {
                using (var imageStream = File.OpenRead(imagePath))
                {
                    var injector = new BitmapDdsInjector(resourceManager);
                    injector.InjectDds(Info.Serializer, Info.Deserializer, Bitmap, imageIndex, imageStream);
                }
                using (var tagsStream = Info.OpenCacheReadWrite())
                {
                    var tagContext = new TagSerializationContext(tagsStream, Info.Cache, Info.StringIDs, Tag);
                    Info.Serializer.Serialize(tagContext, Bitmap);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Importing image data failed: " + ex.Message);
                return true;
            }
            Console.WriteLine("Done!");
            return true;
        }
예제 #18
0
        private bool ImportBitmapResource(TagInstance tagIndex, string cachePath, string dataPath)
        {
            Bitmap bitmap;
            ResourceCache resourceCache;
            uint compressedSize = 0;

            using (var cacheStream = _info.OpenCacheRead())
            {
                var tagContext = new TagSerializationContext(cacheStream, _info.Cache, _info.StringIDs, tagIndex);
                bitmap = _info.Deserializer.Deserialize<Bitmap>(tagContext);
            }
            using (var stream = File.Open(_info.CacheFile.DirectoryName + "\\" + cachePath, FileMode.Open, FileAccess.ReadWrite))
            {
                int imageIndex = 0;
                foreach (string file in Directory.EnumerateFiles(dataPath, "*.bitm"))
                {
                    byte[] inBitmapData = File.ReadAllBytes(file);
                    resourceCache = new ResourceCache(stream);
                    bitmap.Resources[imageIndex].Resource.Index = resourceCache.Add(stream, inBitmapData, out compressedSize);
                    bitmap.Resources[imageIndex].Resource.CompressedSize = compressedSize;
                    imageIndex++;
                }
            }
            using (var cacheStream = _fileInfo.Open(FileMode.Open, FileAccess.ReadWrite))
            {
                var context = new TagSerializationContext(cacheStream, _cache, _stringIds, tagIndex);
                _info.Serializer.Serialize(context, bitmap);
            }
            Console.WriteLine("{1}: Imported 0x{0}.", compressedSize, tagIndex);
            return true;
        }
예제 #19
0
        public override bool Execute(List<string> args)
        {
            if (args.Count < 1 || args.Count > 3)
                return false;

            ResourceLocation location = ResourceLocation.Resources;
            TagInstance destination = Info.Cache.Tags[0x3317];

            if (args.Count == 3)
            {
                var value = args[0];

                switch (value)
                {
                    case "resources":
                        location = ResourceLocation.Resources;
                        break;

                    case "textures":
                        location = ResourceLocation.Textures;
                        break;

                    case "textures_b":
                        location = ResourceLocation.TexturesB;
                        break;

                    case "audio":
                        location = ResourceLocation.Audio;
                        break;

                    case "video":
                        location = ResourceLocation.Video;
                        break;

                    case "render_models":
                        location = ResourceLocation.RenderModels;
                        break;

                    case "lightmaps":
                        location = ResourceLocation.Lightmaps;
                        break;

                    default:
                        Console.WriteLine("Invalid resource location: " + value);
                        return false;
                }

                args.RemoveAt(0);
            }

            if (args.Count == 2)
            {
                destination = ArgumentParser.ParseTagIndex(Info, args[0]);

                if (!destination.IsInGroup("mode"))
                {
                    Console.WriteLine("Specified tag is not a render_model: " + args[0]);
                    return false;
                }

                args.RemoveAt(0);
            }

            var builder = new RenderModelBuilder(Info.Version);

            // Add a root node
            var node = builder.AddNode(new RenderModel.Node
            {
                Name = Info.StringIDs.GetStringID("street_cone"),
                ParentNode = -1,
                FirstChildNode = -1,
                NextSiblingNode = -1,
                DefaultRotation = new Vector4(0, 0, 0, -1),
                DefaultScale = 1,
                InverseForward = new Vector3(1, 0, 0),
                InverseLeft = new Vector3(0, 1, 0),
                InverseUp = new Vector3(0, 0, 1),
            });

            // Begin building the default region and permutation
            builder.BeginRegion(Info.StringIDs.GetStringID("default"));
            builder.BeginPermutation(Info.StringIDs.GetStringID("default"));

            using (var importer = new AssimpContext())
            {
                Scene model;
                using (var logStream = new LogStream((msg, userData) => Console.WriteLine(msg)))
                {
                    logStream.Attach();
                    model = importer.ImportFile(args[0],
                        PostProcessSteps.CalculateTangentSpace |
                        PostProcessSteps.GenerateNormals |
                        PostProcessSteps.JoinIdenticalVertices |
                        PostProcessSteps.SortByPrimitiveType |
                        PostProcessSteps.PreTransformVertices |
                        PostProcessSteps.Triangulate);
                    logStream.Detach();
                }

                Console.WriteLine("Assembling vertices...");

                // Build a multipart mesh from the model data,
                // with each model mesh mapping to a part of one large mesh and having its own material
                builder.BeginMesh();
                ushort partStartVertex = 0;
                ushort partStartIndex = 0;
                var vertices = new List<RigidVertex>();
                var indices = new List<ushort>();
                foreach (var mesh in model.Meshes)
                {
                    for (var i = 0; i < mesh.VertexCount; i++)
                    {
                        var position = mesh.Vertices[i];
                        var normal = mesh.Normals[i];
                        var uv = mesh.TextureCoordinateChannels[0][i];
                        var tangent = mesh.Tangents[i];
                        var bitangent = mesh.BiTangents[i];
                        vertices.Add(new RigidVertex
                        {
                            Position = new Vector4(position.X, position.Y, position.Z, 1),
                            Normal = new Vector3(normal.X, normal.Y, normal.Z),
                            Texcoord = new Vector2(uv.X, uv.Y),
                            Tangent = new Vector4(tangent.X, tangent.Y, tangent.Z, 1),
                            Binormal = new Vector3(bitangent.X, bitangent.Y, bitangent.Z),
                        });
                    }

                    // Build the index buffer
                    var meshIndices = mesh.GetIndices();
                    indices.AddRange(meshIndices.Select(i => (ushort)(i + partStartVertex)));

                    // Define a material and part for this mesh
                    var material = builder.AddMaterial(new RenderMaterial
                    {
                        RenderMethod = Info.Cache.Tags[0x101F],
                    });

                    builder.BeginPart(material, partStartIndex, (ushort)meshIndices.Length, (ushort)mesh.VertexCount);
                    builder.DefineSubPart(partStartIndex, (ushort)meshIndices.Length, (ushort)mesh.VertexCount);
                    builder.EndPart();

                    // Move to the next part
                    partStartVertex += (ushort)mesh.VertexCount;
                    partStartIndex += (ushort)meshIndices.Length;
                }

                // Bind the vertex and index buffers
                builder.BindRigidVertexBuffer(vertices, node);
                builder.BindIndexBuffer(indices, PrimitiveType.TriangleList);
                builder.EndMesh();
            }

            builder.EndPermutation();
            builder.EndRegion();

            Console.WriteLine("Building Blam mesh data...");

            var resourceStream = new MemoryStream();
            var renderModel = builder.Build(Info.Serializer, resourceStream);

            Console.WriteLine("Writing resource data...");

            // Add a new resource for the model data
            var resources = new ResourceDataManager();
            resources.LoadCachesFromDirectory(Info.CacheFile.DirectoryName);
            resourceStream.Position = 0;
            resources.Add(renderModel.Geometry.Resource, location, resourceStream);

            Console.WriteLine("Writing tag data...");

            using (var cacheStream = Info.OpenCacheReadWrite())
            {
                var tag = destination;
                var context = new TagSerializationContext(cacheStream, Info.Cache, Info.StringIDs, tag);
                Info.Serializer.Serialize(context, renderModel);
            }

            Console.WriteLine("Model imported successfully!");

            return true;
        }
 public TagDataBlock(TagSerializationContext context)
 {
     _context = context;
     Stream = new MemoryStream();
     Writer = new BinaryWriter(Stream);
 }
예제 #21
0
        public override bool Execute(List<string> args)
        {
            if (args.Count != 2)
                return false;

            //
            // Verify the xbox scenario_structure_bsp tag
            //

            var bspName = args[0];
            var newTagIndex = ArgumentParser.ParseTagIndex(Info, args[1]);

            CacheFile.IndexItem item = null;

            Console.WriteLine("Verifying xbox tag...");

            foreach (var tag in BlamCache.IndexItems)
            {
                if (tag.ClassCode == "sbsp" && tag.Filename == bspName)
                {
                    item = tag;
                    break;
                }
            }

            if (item == null)
            {
                Console.WriteLine("Xbox tag does not exist: " + args[0]);
                return false;
            }

            //
            // Load the xbox scenario_structure_bsp tag
            //

            var xboxContext = new XboxSerializationContext(item);
            var deserializer = new TagDeserializer(BlamCache.Version);
            var sbsp = deserializer.Deserialize<ScenarioStructureBsp>(xboxContext);

            // blank resources that will be generated/converted from ODST automatically later
            var Resource1 = new ResourceReference() { Index = 1337, Owner = newTagIndex }; // render geo 1
            var Resource2 = new ResourceReference() { Index = 1337, Owner = newTagIndex }; // render geo 2
            var Resource3 = new ResourceReference() { Index = 1337, Owner = newTagIndex }; // collision BSP tag data
            var Resource4 = new ResourceReference() { Index = 1337, Owner = newTagIndex }; // other tag data and shit (unknown raw 3rd in halo 3, etc.)

            // Set the resource refs in the tag to the blank ones we just made
            sbsp.Geometry.Resource = Resource1;
            sbsp.Geometry2.Resource = Resource2;
            sbsp.CollisionBSPResource = Resource3;
            sbsp.Resource4 = Resource4;

            using (var cacheStream = Info.CacheFile.Open(FileMode.Open, FileAccess.ReadWrite))
            {
                Console.WriteLine("Writing ElDewrito tag to tag " + newTagIndex+"...");

                var context = new TagSerializationContext(cacheStream, Info.Cache, Info.StringIDs, Info.Cache.Tags[newTagIndex.Index]);
                Info.Serializer.Serialize(context, sbsp);
            }

            return true;
        }