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; }
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; }
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; }
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; }
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; }
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; }
public TagDataBlock(TagSerializationContext context) { _context = context; Stream = new MemoryStream(); Writer = new BinaryWriter(Stream); }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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 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; }