public static SoundCacheFileGestalt LoadSoundGestalt(HaloOnlineCacheContext cacheContext, ref CacheFile blamCache) { CacheFile.IndexItem blamTag = null; foreach (var tag in blamCache.IndexItems) { if (tag.GroupTag == "ugh!") { blamTag = tag; break; } } if (blamTag == null) { return(null); } var blamContext = new CacheSerializationContext(ref blamCache, blamTag); var ugh = blamCache.Deserializer.Deserialize <SoundCacheFileGestalt>(blamContext); // // Apply conversion to ugh! data (gain increase and such) // return(ugh); }
public CacheSerializationContext(ref CacheFile blamCache, CacheFile.IndexItem blamTag) { if (blamCache.Version < CacheVersion.Halo3Retail) { var oldBlamCache = blamCache; var oldBlamTag = blamTag; if (blamTag.External) { try { blamCache = CacheFileGen2.MainMenuCache; blamTag = blamCache.IndexItems[blamTag.GroupTag, blamTag.Name]; } catch (KeyNotFoundException) { blamCache = oldBlamCache; blamTag = oldBlamTag; } } if (blamTag.External) { try { blamCache = CacheFileGen2.SharedCache; blamTag = blamCache.IndexItems[blamTag.GroupTag, blamTag.Name]; } catch (KeyNotFoundException) { blamCache = oldBlamCache; blamTag = oldBlamTag; } } if (blamTag.External) { try { blamCache = CacheFileGen2.SinglePlayerSharedCache; blamTag = blamCache.IndexItems[blamTag.GroupTag, blamTag.Name]; } catch (KeyNotFoundException) { blamCache = oldBlamCache; blamTag = oldBlamTag; } } if (blamTag.External) { throw new KeyNotFoundException($"[{blamTag.GroupTag}] {blamTag.Name}"); } } BlamCache = blamCache; BlamTag = blamTag; }
private Bitmap ConvertBitmap(CacheFile.IndexItem blamTag, Bitmap bitmap, Dictionary <ResourceLocation, Stream> resourceStreams) { bitmap.Flags = BitmapRuntimeFlags.UsingTagInteropAndTagResource; bitmap.UnknownB4 = 0; if (BlamCache.Version == CacheVersion.HaloReach) { bitmap.TightBoundsOld = bitmap.TightBoundsNew; foreach (var image in bitmap.Images) { // For all formats above #38 (reach DXN, CTX1, DXT3a_mono, DXT3a_alpha, DXT5a_mono, DXT5a_alpha, DXN_mono_alpha), subtract 5 to match with H3/ODST/HO enum if (image.Format >= (BitmapFormat)38) { image.Format = image.Format - 5; } } } // // For each bitmaps, apply conversion process and create a new list of resources that will replace the one from H3. // var tagName = blamTag.Name; var resourceList = new List <Bitmap.BitmapResource>(); for (int i = 0; i < bitmap.Images.Count(); i++) { var resource = ConvertBitmap(bitmap, resourceStreams, i, tagName); if (resource == null) { return(null); } Bitmap.BitmapResource bitmapResource = new Bitmap.BitmapResource { Resource = resource }; resourceList.Add(bitmapResource); } bitmap.Resources = resourceList; bitmap.InterleavedResourcesOld = null; //fixup for HO expecting 6 sequences in sensor_blips bitmap if (tagName == "ui\\chud\\bitmaps\\sensor_blips") { bitmap.Sequences.Add(bitmap.Sequences[3]); bitmap.Sequences.Add(bitmap.Sequences[3]); } return(bitmap); }
public void ExtractXMA(CacheFile.IndexItem blamTag, string directory) { if (BlamSoundGestalt == null) { BlamSoundGestalt = PortingContextFactory.LoadSoundGestalt(CacheContext, ref BlamCache); } var blamContext = new CacheSerializationContext(ref BlamCache, blamTag); var sound = BlamCache.Deserializer.Deserialize <Sound>(blamContext); var xmaFileSize = BlamSoundGestalt.GetFileSize(sound.SoundReference.PitchRangeIndex, sound.SoundReference.PitchRangeCount); if (xmaFileSize < 0) { return; } var xmaData = BlamCache.GetSoundRaw(sound.SoundReference.ZoneAssetHandle, xmaFileSize); if (xmaData == null) { Console.WriteLine($"ERROR: Failed to find sound data!"); return; } var parts = blamTag.Name.Split('\\'); string baseName = parts[parts.Length - 1]; for (int pitchRangeIndex = sound.SoundReference.PitchRangeIndex; pitchRangeIndex < sound.SoundReference.PitchRangeIndex + sound.SoundReference.PitchRangeCount; pitchRangeIndex++) { var relativePitchRangeIndex = pitchRangeIndex - sound.SoundReference.PitchRangeIndex; var permutationCount = BlamSoundGestalt.GetPermutationCount(pitchRangeIndex); for (int i = 0; i < permutationCount; i++) { BlamSound blamSound = SoundConverter.GetXMA(BlamCache, BlamSoundGestalt, sound, relativePitchRangeIndex, i, xmaData); string permutationName = $"{baseName}_{relativePitchRangeIndex}_{i}"; var fileName = $"{directory}\\{permutationName}.xma"; using (EndianWriter output = new EndianWriter(new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None), EndianFormat.BigEndian)) { XMAFile XMAfile = new XMAFile(blamSound); XMAfile.Write(output); } } } }
private void ExtractBitmap(CacheFile.IndexItem blamTag, string directory) { Console.WriteLine($"{blamTag.Name}"); // // Load the Blam tag definition // var blamContext = new CacheSerializationContext(ref BlamCache, blamTag); var bitmap = BlamCache.Deserializer.Deserialize <Bitmap>(blamContext); var ddsOutDir = directory; string bitmap_name = blamTag.Name.Replace('\\', '_'); if (bitmap.Images.Count > 1) { ddsOutDir = Path.Combine(directory, bitmap_name); Directory.CreateDirectory(ddsOutDir); } for (var i = 0; i < bitmap.Images.Count; i++) { var outPath = Path.Combine(ddsOutDir, ((bitmap.Images.Count > 1) ? i.ToString() : bitmap_name) + ".dds"); var image = bitmap.Images[i]; // // Get bitmap data and write file // BaseBitmap baseBitmap = ExtractBitmapData(bitmap, i); // Bitmap is not valid (not a failure to convert, tag data is not valid / no data to convert if (baseBitmap == null) { return; } var header = new DDSHeader(baseBitmap); using (var outStream = File.Open(outPath, FileMode.Create, FileAccess.Write)) { header.Write(new EndianWriter(outStream)); var dataStream = new MemoryStream(baseBitmap.Data); StreamUtil.Copy(dataStream, outStream, baseBitmap.Data.Length); } } }
public EditBlockCommand(CommandContextStack contextStack, CacheFile blamCache, CacheFile.IndexItem tag, object value) : base(true, "EditBlock", "Edit the fields of a particular block element.", "EditBlock <name> [element-index (if block)]", "Edit the fields of a particular block element.") { BlamCache = blamCache; ContextStack = contextStack; Tag = tag; Structure = TagStructure.GetTagStructureInfo(value.GetType(), BlamCache.Version); Owner = value; }
public CopyBlockElementsCommand(CommandContextStack contextStack, CacheFile blamCache, CacheFile.IndexItem tag, TagStructureInfo structure, object owner) : base(false, "CopyBlockElements", "Copies block elements from one tag to another.", "CopyBlockElements <block name> [index = 0] [count = *]", "Copies block elements from one tag to another.") { ContextStack = contextStack; BlamCache = blamCache; Tag = tag; Structure = structure; Owner = owner; }
public void ExtractWAV(CacheFile.IndexItem blamTag, string directory) { Console.WriteLine($"Extracting {blamTag.Name}.sound"); if (BlamSoundGestalt == null) { BlamSoundGestalt = PortingContextFactory.LoadSoundGestalt(CacheContext, ref BlamCache); } var blamContext = new CacheSerializationContext(ref BlamCache, blamTag); var sound = BlamCache.Deserializer.Deserialize <Sound>(blamContext); var xmaFileSize = BlamSoundGestalt.GetFileSize(sound.SoundReference.PitchRangeIndex, sound.SoundReference.PitchRangeCount); var xmaData = BlamCache.GetSoundRaw(sound.SoundReference.ZoneAssetHandle, xmaFileSize); if (xmaData == null) { Console.WriteLine($"ERROR: Failed to find sound data!"); return; } var OutDir = directory; string sound_name = blamTag.Name.Replace('\\', '_'); sound_name = Path.Combine(directory, sound_name); for (int pitchRangeIndex = sound.SoundReference.PitchRangeIndex; pitchRangeIndex < sound.SoundReference.PitchRangeIndex + sound.SoundReference.PitchRangeCount; pitchRangeIndex++) { var relativePitchRangeIndex = pitchRangeIndex - sound.SoundReference.PitchRangeIndex; var permutationCount = BlamSoundGestalt.GetPermutationCount(pitchRangeIndex); for (int i = 0; i < permutationCount; i++) { string permutationName = $"{sound_name}_{relativePitchRangeIndex}_{i}"; permutationName += ".mp3"; BlamSound blamSound = SoundConverter.ConvertGen3Sound(BlamCache, BlamSoundGestalt, sound, relativePitchRangeIndex, i, xmaData); using (EndianWriter output = new EndianWriter(new FileStream(permutationName, FileMode.Create, FileAccess.Write, FileShare.None), EndianFormat.BigEndian)) { output.WriteBlock(blamSound.Data); } } } }
private void CopyTagNames(Stream cacheStream, CachedTagInstance edTag, CacheFile.IndexItem blamTag) { if (CopiedTags.ContainsKey(blamTag.GroupTag)) { foreach (var name in CopiedTags[blamTag.GroupTag]) { if (name == blamTag.Name) { return; } } } else { CopiedTags[blamTag.GroupTag] = new List <string>(); } CopiedTags[blamTag.GroupTag].Add(blamTag.Name); var edDef = CacheContext.Deserialize(cacheStream, edTag); var blamDef = BlamCache.Deserializer.Deserialize( new CacheSerializationContext(ref BlamCache, blamTag), TagDefinition.Find(blamTag.GroupTag)); var edInfo = TagStructure.GetTagStructureInfo(edDef.GetType(), CacheContext.Version); var blamInfo = TagStructure.GetTagStructureInfo(blamDef.GetType(), BlamCache.Version); var oldName = edTag.Name; edTag.Name = blamTag.Name; if (edTag.Name != oldName) { NewNameCount++; } CopyTagNames(cacheStream, edDef, edInfo, blamDef, blamInfo); }
private void MergeMultiplayerGlobals(Stream cacheStream, Dictionary <ResourceLocation, Stream> resourceStreams, CachedTagInstance edTag, CacheFile.IndexItem h3Tag) { var edDef = CacheContext.Deserialize <MultiplayerGlobals>(cacheStream, edTag); var h3Def = BlamCache.Deserializer.Deserialize <MultiplayerGlobals>( new CacheSerializationContext(ref BlamCache, h3Tag)); if (h3Def.Runtime == null || h3Def.Runtime.Count == 0) { return; } for (var i = 0; i < h3Def.Runtime[0].GeneralEvents.Count; i++) { var h3Event = h3Def.Runtime[0].GeneralEvents[i]; if (h3Event.DisplayString == StringId.Invalid) { continue; } var h3String = BlamCache.Strings.GetString(h3Event.DisplayString); for (var j = 0; j < edDef.Runtime[0].GeneralEvents.Count; j++) { var edEvent = edDef.Runtime[0].GeneralEvents[j]; var edString = CacheContext.GetString(edEvent.DisplayString); if (edString == h3String) { MergeMultiplayerEvent(cacheStream, resourceStreams, edEvent, h3Event); } } } for (var i = 0; i < h3Def.Runtime[0].FlavorEvents.Count; i++) { var h3Event = h3Def.Runtime[0].FlavorEvents[i]; if (h3Event.DisplayString == StringId.Invalid) { continue; } var h3String = BlamCache.Strings.GetString(h3Event.DisplayString); for (var j = 0; j < edDef.Runtime[0].FlavorEvents.Count; j++) { var edEvent = edDef.Runtime[0].FlavorEvents[j]; var edString = CacheContext.GetString(edEvent.DisplayString); if (edString == h3String) { MergeMultiplayerEvent(cacheStream, resourceStreams, edEvent, h3Event); } } } for (var i = 0; i < h3Def.Runtime[0].SlayerEvents.Count; i++) { var h3Event = h3Def.Runtime[0].SlayerEvents[i]; if (h3Event.DisplayString == StringId.Invalid) { continue; } var h3String = BlamCache.Strings.GetString(h3Event.DisplayString); for (var j = 0; j < edDef.Runtime[0].SlayerEvents.Count; j++) { var edEvent = edDef.Runtime[0].SlayerEvents[j]; var edString = CacheContext.GetString(edEvent.DisplayString); if (edString == h3String) { MergeMultiplayerEvent(cacheStream, resourceStreams, edEvent, h3Event); } } } for (var i = 0; i < h3Def.Runtime[0].CtfEvents.Count; i++) { var h3Event = h3Def.Runtime[0].CtfEvents[i]; if (h3Event.DisplayString == StringId.Invalid) { continue; } var h3String = BlamCache.Strings.GetString(h3Event.DisplayString); for (var j = 0; j < edDef.Runtime[0].CtfEvents.Count; j++) { var edEvent = edDef.Runtime[0].CtfEvents[j]; var edString = CacheContext.GetString(edEvent.DisplayString); if (edString == h3String) { MergeMultiplayerEvent(cacheStream, resourceStreams, edEvent, h3Event); } } } for (var i = 0; i < h3Def.Runtime[0].OddballEvents.Count; i++) { var h3Event = h3Def.Runtime[0].OddballEvents[i]; if (h3Event.DisplayString == StringId.Invalid) { continue; } var h3String = BlamCache.Strings.GetString(h3Event.DisplayString); for (var j = 0; j < edDef.Runtime[0].OddballEvents.Count; j++) { var edEvent = edDef.Runtime[0].OddballEvents[j]; var edString = CacheContext.GetString(edEvent.DisplayString); if (edString == h3String) { MergeMultiplayerEvent(cacheStream, resourceStreams, edEvent, h3Event); } } } for (var i = 0; i < h3Def.Runtime[0].KingOfTheHillEvents.Count; i++) { var h3Event = h3Def.Runtime[0].KingOfTheHillEvents[i]; if (h3Event.DisplayString == StringId.Invalid) { continue; } var h3String = BlamCache.Strings.GetString(h3Event.DisplayString); for (var j = 0; j < edDef.Runtime[0].KingOfTheHillEvents.Count; j++) { var edEvent = edDef.Runtime[0].KingOfTheHillEvents[j]; var edString = CacheContext.GetString(edEvent.DisplayString); if (edString == h3String) { MergeMultiplayerEvent(cacheStream, resourceStreams, edEvent, h3Event); } } } for (var i = 0; i < h3Def.Runtime[0].VipEvents.Count; i++) { var h3Event = h3Def.Runtime[0].VipEvents[i]; if (h3Event.DisplayString == StringId.Invalid) { continue; } var h3String = BlamCache.Strings.GetString(h3Event.DisplayString); for (var j = 0; j < edDef.Runtime[0].VipEvents.Count; j++) { var edEvent = edDef.Runtime[0].VipEvents[j]; var edString = CacheContext.GetString(edEvent.DisplayString); if (edString == h3String) { MergeMultiplayerEvent(cacheStream, resourceStreams, edEvent, h3Event); } } } for (var i = 0; i < h3Def.Runtime[0].JuggernautEvents.Count; i++) { var h3Event = h3Def.Runtime[0].JuggernautEvents[i]; if (h3Event.DisplayString == StringId.Invalid) { continue; } var h3String = BlamCache.Strings.GetString(h3Event.DisplayString); for (var j = 0; j < edDef.Runtime[0].JuggernautEvents.Count; j++) { var edEvent = edDef.Runtime[0].JuggernautEvents[j]; var edString = CacheContext.GetString(edEvent.DisplayString); if (edString == h3String) { MergeMultiplayerEvent(cacheStream, resourceStreams, edEvent, h3Event); } } } for (var i = 0; i < h3Def.Runtime[0].TerritoriesEvents.Count; i++) { var h3Event = h3Def.Runtime[0].TerritoriesEvents[i]; if (h3Event.DisplayString == StringId.Invalid) { continue; } var h3String = BlamCache.Strings.GetString(h3Event.DisplayString); for (var j = 0; j < edDef.Runtime[0].TerritoriesEvents.Count; j++) { var edEvent = edDef.Runtime[0].TerritoriesEvents[j]; var edString = CacheContext.GetString(edEvent.DisplayString); if (edString == h3String) { MergeMultiplayerEvent(cacheStream, resourceStreams, edEvent, h3Event); } } } for (var i = 0; i < h3Def.Runtime[0].AssaultEvents.Count; i++) { var h3Event = h3Def.Runtime[0].AssaultEvents[i]; if (h3Event.DisplayString == StringId.Invalid) { continue; } var h3String = BlamCache.Strings.GetString(h3Event.DisplayString); for (var j = 0; j < edDef.Runtime[0].AssaultEvents.Count; j++) { var edEvent = edDef.Runtime[0].AssaultEvents[j]; var edString = CacheContext.GetString(edEvent.DisplayString); if (edString == h3String) { MergeMultiplayerEvent(cacheStream, resourceStreams, edEvent, h3Event); } } } for (var i = 0; i < h3Def.Runtime[0].InfectionEvents.Count; i++) { var h3Event = h3Def.Runtime[0].InfectionEvents[i]; if (h3Event.DisplayString == StringId.Invalid) { continue; } var h3String = BlamCache.Strings.GetString(h3Event.DisplayString); for (var j = 0; j < edDef.Runtime[0].InfectionEvents.Count; j++) { var edEvent = edDef.Runtime[0].InfectionEvents[j]; var edString = CacheContext.GetString(edEvent.DisplayString); if (edString == h3String) { MergeMultiplayerEvent(cacheStream, resourceStreams, edEvent, h3Event); } } } CacheContext.Serialize(cacheStream, edTag, edDef); }
public override object Execute(List <string> args) { if (args.Count < 2) { return(false); } // // Verify Blam tag instance // var unitName = args[0].ToLower(); if (unitName != "spartan" && unitName != "elite") { Console.WriteLine("ERROR: Only 'spartan' and 'elite' armor variants are allowed."); return(false); } args.RemoveAt(0); var blamTagName = unitName == "spartan" ? @"objects\characters\masterchief\mp_masterchief\mp_masterchief" : @"objects\characters\elite\mp_elite\mp_elite"; Console.Write($"Verifying {blamTagName}.render_model..."); CacheFile.IndexItem blamTag = null; foreach (var tag in BlamCache.IndexItems) { if ((tag.GroupTag == "mode") && (tag.Name == blamTagName)) { blamTag = tag; break; } } if (blamTag == null) { Console.WriteLine($"ERROR: Blam tag does not exist: {blamTagName}.render_model"); return(true); } Console.WriteLine("done."); // // Load the Blam tag definition // var variantName = args[0]; args.RemoveAt(0); CachedTagInstance edModeTag = null; var isScenery = false; var regionNames = new List <string>(); while (args.Count != 0) { switch (args[0].ToLower()) { case "scenery": isScenery = true; args.RemoveAt(0); break; case "replace:": edModeTag = CacheContext.GetTag(args[1]); args.RemoveAt(1); args.RemoveAt(0); break; case "regions:": regionNames.AddRange(args.Skip(1)); args.Clear(); break; default: throw new InvalidDataException($"{args}"); } } var blamContext = new CacheSerializationContext(ref BlamCache, blamTag); var edModeDefinition = BlamCache.Deserializer.Deserialize <RenderModel>(blamContext); var materials = edModeDefinition.Materials.Select(i => new RenderMaterial { BreakableSurfaceIndex = i.BreakableSurfaceIndex, Properties = i.Properties, RenderMethod = i.RenderMethod, Skins = i.Skins, Unknown = i.Unknown, Unknown2 = i.Unknown2, Unknown3 = i.Unknown3, Unknown4 = i.Unknown4 }).ToList(); edModeDefinition = (RenderModel)ConvertData(null, edModeDefinition, false); var variantRegions = new List <RenderModel.Region>(); foreach (var region in edModeDefinition.Regions) { if (regionNames.Count != 0 && !regionNames.Contains(CacheContext.GetString(region.Name))) { continue; } var variantRegion = new RenderModel.Region { Name = region.Name, Permutations = new List <RenderModel.Region.Permutation>() }; foreach (var permutation in region.Permutations) { if (variantName == CacheContext.GetString(permutation.Name)) { variantRegion.Permutations.Add(permutation); } } variantRegions.Add(variantRegion); } var variantMeshes = new List <int>(); var variantMaterials = new List <int>(); var variantVertexBuffers = new List <int>(); var variantIndexBuffers = new List <int>(); foreach (var region in variantRegions) { foreach (var permutation in region.Permutations) { for (var i = permutation.MeshIndex; i < (short)(permutation.MeshIndex + permutation.MeshCount); i++) { var mesh = edModeDefinition.Geometry.Meshes[i]; foreach (var part in mesh.Parts) { if (part.MaterialIndex != -1 && !variantMaterials.Contains(part.MaterialIndex)) { variantMaterials.Add(part.MaterialIndex); } } foreach (var vertexBuffer in mesh.VertexBufferIndices) { if (vertexBuffer != ushort.MaxValue && !variantVertexBuffers.Contains(vertexBuffer)) { variantVertexBuffers.Add(vertexBuffer); } } foreach (var indexBuffer in mesh.IndexBufferIndices) { if (indexBuffer != ushort.MaxValue && !variantIndexBuffers.Contains(indexBuffer)) { variantIndexBuffers.Add(indexBuffer); } } if (!variantMeshes.Contains(i)) { variantMeshes.Add(i); } } } } variantMeshes.Sort(); variantMaterials.Sort(); variantVertexBuffers.Sort(); variantIndexBuffers.Sort(); foreach (var meshIndex in variantMeshes) { var mesh = edModeDefinition.Geometry.Meshes[meshIndex]; foreach (var part in mesh.Parts) { if (part.MaterialIndex != -1) { part.MaterialIndex = (short)variantMaterials.IndexOf(part.MaterialIndex); } } } foreach (var region in variantRegions) { foreach (var permutation in region.Permutations) { if (permutation.MeshIndex != -1) { permutation.MeshIndex = (short)variantMeshes.IndexOf(permutation.MeshIndex); } } } foreach (var meshIndex in variantMeshes) { var mesh = edModeDefinition.Geometry.Meshes[meshIndex]; for (var i = 0; i < mesh.VertexBufferIndices.Length; i++) { if (!variantVertexBuffers.Contains(mesh.VertexBufferIndices[i])) { mesh.VertexBufferIndices[i] = ushort.MaxValue; } else { mesh.VertexBufferIndices[i] = (ushort)variantVertexBuffers.IndexOf(mesh.VertexBufferIndices[i]); } } for (var i = 0; i < mesh.IndexBufferIndices.Length; i++) { if (!variantIndexBuffers.Contains(mesh.IndexBufferIndices[i])) { mesh.IndexBufferIndices[i] = ushort.MaxValue; } else { mesh.IndexBufferIndices[i] = (ushort)variantIndexBuffers.IndexOf(mesh.IndexBufferIndices[i]); } } } edModeDefinition.Regions = variantRegions; edModeDefinition.Geometry.Meshes = edModeDefinition.Geometry.Meshes.Where(i => variantMeshes.Contains(edModeDefinition.Geometry.Meshes.IndexOf(i))).ToList(); // // Port Blam render_model materials // materials = materials.Where(i => variantMaterials.Contains(materials.IndexOf(i))).ToList(); using (var stream = CacheContext.OpenTagCacheReadWrite()) { for (var i = 0; i < materials.Count; i++) { var material = materials[i]; if (material.RenderMethod.Index == -1) { continue; } var blamRenderMethod = materials[i].RenderMethod; var blamRenderMethodTag = BlamCache.IndexItems.GetItemByID(blamRenderMethod.Index); var renderMethodExists = false; foreach (var instance in CacheContext.TagCache.Index.FindAllInGroup("rm ")) { if (instance?.Name == blamRenderMethodTag.Name) { renderMethodExists = true; material.RenderMethod = instance; break; } } if (!renderMethodExists) { material.RenderMethod = CacheContext.GetTag <Shader>(@"shaders\invalid"); } } } edModeDefinition.Materials = materials; // // Load Blam resource data // var resourceData = BlamCache.GetRawFromID(edModeDefinition.Geometry.ZoneAssetHandle); if (resourceData == null) { Console.WriteLine("Blam render_geometry resource contains no data."); return(true); } // // Load Blam resource definition // Console.Write("Loading Blam render_geometry resource definition..."); var definitionEntry = BlamCache.ResourceGestalt.TagResources[edModeDefinition.Geometry.ZoneAssetHandle.Index]; var resourceDefinition = new RenderGeometryApiResourceDefinition { VertexBuffers = new List <TagStructureReference <VertexBufferDefinition> >(), IndexBuffers = new List <TagStructureReference <IndexBufferDefinition> >() }; using (var definitionStream = new MemoryStream(BlamCache.ResourceGestalt.FixupInformation)) using (var definitionReader = new EndianReader(definitionStream, EndianFormat.BigEndian)) { var dataContext = new DataSerializationContext(definitionReader, null, CacheResourceAddressType.Definition); definitionReader.SeekTo(definitionEntry.FixupInformationOffset + (definitionEntry.FixupInformationLength - 24)); var vertexBufferCount = definitionReader.ReadInt32(); definitionReader.Skip(8); var indexBufferCount = definitionReader.ReadInt32(); definitionReader.SeekTo(definitionEntry.FixupInformationOffset); for (var i = 0; i < vertexBufferCount; i++) { resourceDefinition.VertexBuffers.Add(new TagStructureReference <VertexBufferDefinition> { Definition = new VertexBufferDefinition { Count = definitionReader.ReadInt32(), Format = (VertexBufferFormat)definitionReader.ReadInt16(), VertexSize = definitionReader.ReadInt16(), Data = new TagData { Size = definitionReader.ReadInt32(), Unused4 = definitionReader.ReadInt32(), Unused8 = definitionReader.ReadInt32(), Address = new CacheResourceAddress(CacheResourceAddressType.Memory, definitionReader.ReadInt32()), Unused10 = definitionReader.ReadInt32() } } }); } definitionReader.Skip(vertexBufferCount * 12); for (var i = 0; i < indexBufferCount; i++) { resourceDefinition.IndexBuffers.Add(new TagStructureReference <IndexBufferDefinition> { Definition = new IndexBufferDefinition { Format = (IndexBufferFormat)definitionReader.ReadInt32(), Data = new TagData { Size = definitionReader.ReadInt32(), Unused4 = definitionReader.ReadInt32(), Unused8 = definitionReader.ReadInt32(), Address = new CacheResourceAddress(CacheResourceAddressType.Memory, definitionReader.ReadInt32()), Unused10 = definitionReader.ReadInt32() } } }); } } Console.WriteLine("done."); // // Convert Blam resource data // using (var edResourceStream = new MemoryStream()) { // // Convert Blam render_geometry_api_resource_definition // using (var blamResourceStream = new MemoryStream(resourceData)) { // // Convert Blam vertex buffers // Console.Write("Converting vertex buffers..."); var previousVertexBufferCount = -1; for (var i = 0; i < resourceDefinition.VertexBuffers.Count; i++) { if (!variantVertexBuffers.Contains(i)) { continue; } blamResourceStream.Position = definitionEntry.ResourceFixups[i].Offset; if (i > 0) { previousVertexBufferCount = resourceDefinition.VertexBuffers[i - 1].Definition.Count; } GeometryConverter.ConvertVertexBuffer(resourceDefinition, blamResourceStream, edResourceStream, i, previousVertexBufferCount); } Console.WriteLine("done."); // // Convert Blam index buffers // Console.Write("Converting index buffers..."); for (var i = 0; i < resourceDefinition.IndexBuffers.Count; i++) { if (!variantIndexBuffers.Contains(i)) { continue; } blamResourceStream.Position = definitionEntry.ResourceFixups[resourceDefinition.VertexBuffers.Count * 2 + i].Offset; GeometryConverter.ConvertIndexBuffer(resourceDefinition, blamResourceStream, edResourceStream, i); } Console.WriteLine("done."); } resourceDefinition.VertexBuffers = resourceDefinition.VertexBuffers.Where(i => variantVertexBuffers.Contains(resourceDefinition.VertexBuffers.IndexOf(i))).ToList(); resourceDefinition.IndexBuffers = resourceDefinition.IndexBuffers.Where(i => variantIndexBuffers.Contains(resourceDefinition.IndexBuffers.IndexOf(i))).ToList(); // // Finalize the new ElDorado geometry resource // Console.Write("Writing resource data..."); edModeDefinition.Geometry.Resource = new PageableResource { Page = new RawPage(), Resource = new TagResourceGen3 { ResourceType = TagResourceTypeGen3.RenderGeometry, ResourceFixups = new List <TagResourceGen3.ResourceFixup>(), ResourceDefinitionFixups = new List <TagResourceGen3.ResourceDefinitionFixup>(), Unknown2 = 1 } }; edResourceStream.Position = 0; var resourceContext = new ResourceSerializationContext(CacheContext, edModeDefinition.Geometry.Resource); CacheContext.Serializer.Serialize(resourceContext, resourceDefinition); edModeDefinition.Geometry.Resource.ChangeLocation(ResourceLocation.ResourcesB); CacheContext.AddResource(edModeDefinition.Geometry.Resource, edResourceStream); Console.WriteLine("done."); } edModeDefinition.Name = CacheContext.GetStringId(variantName); if (edModeTag == null) { for (var i = 0; i < CacheContext.TagCache.Index.Count; i++) { if (CacheContext.TagCache.Index[i] == null) { CacheContext.TagCache.Index[i] = edModeTag = new CachedTagInstance(i, TagGroup.Instances[new Tag("mode")]); break; } } if (edModeTag == null) { edModeTag = CacheContext.TagCache.AllocateTag(TagGroup.Instances[new Tag("mode")]); } } // // Create a new armor model tag // Model edHlmtDefinition = null; CachedTagInstance edHlmtTag = null; if (isScenery) { Console.Write($"Verifying {blamTagName}.model..."); CacheFile.IndexItem blamHlmtTag = null; foreach (var tag in BlamCache.IndexItems) { if ((tag.GroupTag == "hlmt") && (tag.Name == blamTagName)) { blamHlmtTag = tag; break; } } if (blamHlmtTag == null) { Console.WriteLine($"ERROR: Blam tag does not exist: {blamTagName}.model"); return(true); } Console.WriteLine("done."); blamContext = new CacheSerializationContext(ref BlamCache, blamHlmtTag); edHlmtDefinition = (Model)ConvertData(null, BlamCache.Deserializer.Deserialize <Model>(blamContext), false); edHlmtDefinition.RenderModel = edModeTag; edHlmtDefinition.ReduceToL1SuperLow = 36.38004f; edHlmtDefinition.ReduceToL2Low = 27.28503f; edHlmtDefinition.Variants = new List <Model.Variant>(); edHlmtDefinition.Materials = new List <Model.Material>(); edHlmtDefinition.NewDamageInfo = new List <Model.GlobalDamageInfoBlock>(); edHlmtDefinition.Targets = new List <Model.Target>(); var collisionRegions = new List <Model.CollisionRegion>(); foreach (var collisionRegion in edHlmtDefinition.CollisionRegions) { var found = false; foreach (var variantRegion in variantRegions) { if (collisionRegion.Name == variantRegion.Name) { found = true; break; } } if (!found) { continue; } found = false; foreach (var permutation in collisionRegion.Permutations) { if (permutation.Name == CacheContext.GetStringId(variantName)) { found = true; break; } } if (found) { collisionRegions.Add(collisionRegion); } } foreach (var collisionRegion in collisionRegions) { Model.CollisionRegion.Permutation permutation = null; foreach (var collisionPermutation in collisionRegion.Permutations) { if (collisionPermutation.Name == CacheContext.GetStringId(variantName)) { permutation = collisionPermutation; break; } } if (permutation == null) { throw new KeyNotFoundException(); } collisionRegion.Permutations = new List <Model.CollisionRegion.Permutation> { permutation }; } edHlmtDefinition.CollisionRegions = collisionRegions; for (var i = 0; i < CacheContext.TagCache.Index.Count; i++) { if (CacheContext.TagCache.Index[i] == null) { CacheContext.TagCache.Index[i] = edHlmtTag = new CachedTagInstance(i, TagGroup.Instances[new Tag("hlmt")]); break; } } if (edHlmtTag == null) { edHlmtTag = CacheContext.TagCache.AllocateTag(TagGroup.Instances[new Tag("hlmt")]); } } // // Create a new armor scenery tag // Scenery edScenDefinition = null; CachedTagInstance edScenTag = null; if (isScenery) { edScenDefinition = new Scenery { ObjectType = new GameObjectType { Halo2 = GameObjectTypeHalo2.Scenery, Halo3Retail = GameObjectTypeHalo3Retail.Scenery, Halo3ODST = GameObjectTypeHalo3ODST.Scenery, HaloOnline = GameObjectTypeHaloOnline.Scenery }, BoundingRadius = 0.44f, BoundingOffset = new RealPoint3d(-0.02f, 0.0f, 0.0f), AccelerationScale = 1.2f, SweetenerSize = GameObject.SweetenerSizeValue.Medium, Model = edHlmtTag, ChangeColors = new List <GameObject.ChangeColor> { new GameObject.ChangeColor(), new GameObject.ChangeColor(), new GameObject.ChangeColor(), new GameObject.ChangeColor(), new GameObject.ChangeColor() }, NodeMaps = new List <GameObject.NodeMap>() }; for (sbyte i = 0; i < 51; i++) { edScenDefinition.NodeMaps.Add(new GameObject.NodeMap { TargetNode = i }); } for (var i = 0; i < CacheContext.TagCache.Index.Count; i++) { if (CacheContext.TagCache.Index[i] == null) { CacheContext.TagCache.Index[i] = edScenTag = new CachedTagInstance(i, TagGroup.Instances[new Tag("scen")]); break; } } if (edScenTag == null) { edScenTag = CacheContext.TagCache.AllocateTag(TagGroup.Instances[new Tag("scen")]); } } // // Serialize new ElDorado tag definitions // using (var cacheStream = CacheContext.OpenTagCacheReadWrite()) { CacheContext.Serialize(cacheStream, edModeTag, edModeDefinition); edModeTag.Name = isScenery ? (unitName == "spartan" ? $@"objects\characters\masterchief\mp_masterchief\armor\{variantName}" : $@"objects\characters\elite\mp_elite\armor\{variantName}") : (unitName == "spartan" ? @"objects\characters\masterchief\mp_masterchief\mp_masterchief" : @"objects\characters\elite\mp_elite\mp_elite"); if (isScenery) { CacheContext.Serialize(cacheStream, edHlmtTag, edHlmtDefinition); CacheContext.Serialize(cacheStream, edScenTag, edScenDefinition); edScenTag.Name = unitName == "spartan" ? $@"objects\characters\masterchief\mp_masterchief\armor\{variantName}" : $@"objects\characters\elite\mp_elite\armor\{variantName}"; } } return(true); }
public override object Execute(List <string> args) { if (args.Count != 2) { return(false); } var groupTagInput = args[0]; var blamTagName = args[1]; var groupTag = Tag.Null; if (TagDefinition.Exists(groupTagInput)) { groupTag = new Tag(groupTagInput); } else { foreach (var tagGroup in BlamCache.IndexItems.ClassList) { if (groupTagInput == BlamCache.Strings.GetItemByID(tagGroup.StringID)) { var chars = new char[4] { ' ', ' ', ' ', ' ' }; for (var i = 0; i < 4; i++) { chars[i] = tagGroup.ClassCode[i]; } groupTag = new Tag(new string(chars)); break; } } } CacheFile.IndexItem tag = null; foreach (var blamTag in BlamCache.IndexItems) { if ((blamTag.GroupTag == groupTag.ToString()) && (blamTagName == "*" || blamTag.Name == blamTagName)) { tag = blamTag; break; } } if (tag == null) { throw new Exception(); } var tagName = $"(0x{tag.ID:X8}) {tag.Name.Substring(tag.Name.LastIndexOf('\\') + 1)}"; var tagType = TagDefinition.Find(groupTag); var definition = (TagStructure)BlamCache.Deserializer.Deserialize(new CacheSerializationContext(ref BlamCache, tag), tagType); var structure = definition.GetTagStructureInfo(BlamCache.Version); var oldContext = ContextStack.Context; var commandContext = new CommandContext(ContextStack.Context, string.Format("{0}.{1}", tagName, groupTagInput)); commandContext.AddCommand(new ListFieldsCommand(BlamCache, structure, definition)); commandContext.AddCommand(new EditBlockCommand(ContextStack, BlamCache, tag, definition)); commandContext.AddCommand(new CopyBlockElementsCommand(ContextStack, BlamCache, tag, structure, definition)); commandContext.AddCommand(new Editing.ExitToCommand(ContextStack)); ContextStack.Push(commandContext); Console.WriteLine($"Tag {tagName}.{groupTagInput} has been opened for editing."); Console.WriteLine("New commands are now available. Enter \"help\" to view them."); Console.WriteLine("Use \"exit\" to return to {0}.", oldContext.Name); return(true); }
private void MergeMultilingualUnicodeStringList(Stream cacheStream, Dictionary <ResourceLocation, Stream> resourceStreams, CachedTagInstance edTag, CacheFile.IndexItem h3Tag) { var edDef = CacheContext.Deserialize <MultilingualUnicodeStringList>(cacheStream, edTag); var h3Def = BlamCache.Deserializer.Deserialize <MultilingualUnicodeStringList>( new CacheSerializationContext(ref BlamCache, h3Tag)); ConvertMultilingualUnicodeStringList(cacheStream, resourceStreams, h3Def); var mergedStringCount = 0; for (var i = 0; i < h3Def.Strings.Count; i++) { var found = false; for (var j = 0; j < edDef.Strings.Count; j++) { if (h3Def.Strings[i].StringID == edDef.Strings[j].StringID) { found = true; break; } } if (!found) { var localizedStr = new LocalizedString { StringID = h3Def.Strings[i].StringID, StringIDStr = h3Def.Strings[i].StringIDStr }; edDef.Strings.Add(localizedStr); for (var x = 0; x < 12; x++) { edDef.SetString( localizedStr, (GameLanguage)x, h3Def.GetString( h3Def.Strings[i], (GameLanguage)x)); } mergedStringCount++; } } if (mergedStringCount > 0) { Console.WriteLine($"Merged {mergedStringCount} localized strings."); CacheContext.Serialize(cacheStream, edTag, edDef); } }
public CachedTagInstance FixRmt2Reference(Stream cacheStream, string blamTagName, CacheFile.IndexItem blamRmt2Tag, RenderMethodTemplate blamRmt2Definition, List <string> bmMaps, List <string> bmArgs) { switch (blamTagName) { case @"levels\multi\snowbound\shaders\cov_grey_icy": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_2_0_1_7_2_0_0_0_0_0")); } catch { } break; case @"objects\vehicles\ghost\shaders\ghost_damage": case @"objects\vehicles\wraith\shaders\wraith_blown_open": case @"objects\vehicles\banshee\shaders\banshee_damage": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_2_0_1_2_2_2_0_1_1_0")); } catch { } break; case @"objects\vehicles\ghost\shaders\ghost_torn": case @"objects\vehicles\banshee\shaders\banshee_torn": case @"objects\vehicles\wraith\shaders\wraith_torn": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_2_1_1_2_2_0_0_0_1_0")); } catch { } break; case @"objects\vehicles\wraith\shaders\wraith_torn_metal": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_2_1_1_1_2_0_0_0_1_0")); } catch { } break; case @"objects\vehicles\ghost\shaders\ghost_dash_zcam": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\halogram_templates\_0_11_0_1_0_2_0")); } catch { } break; case @"fx\particles\energy\electric_arcs_blue": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\particle_templates\_2_8_0_0_0_0_1_0_0_0")); } catch { } break; case @"objects\weapons\melee\energy_blade\fx\particles\plasma_wispy": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\particle_templates\_5_8_0_0_0_1_0_0_0_0")); } catch { } break; case @"objects\weapons\melee\energy_blade\fx\particles\energy_pulse": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\particle_templates\_3_7_0_0_1_0_0_0_0_0")); } catch { } break; case @"levels\dlc\fortress\shaders\panel_platform_center": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_1_0_1_2_2_5_0_1_0_0")); } catch { try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_1_0_1_2_2_5_0_1_0_0_0")); } catch { } } break; case @"levels\dlc\sidewinder\shaders\side_tree_branch_snow": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_1_1_0_0_2_5_0_0_0_0_0")); } catch { try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_1_1_0_0_2_5_0_0_0_0")); } catch { } } break; case @"levels\dlc\sidewinder\shaders\justin\sw_ground_ice1": case @"levels\dlc\sidewinder\shaders\justin\sw_ground_rock1": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\terrain_templates\_0_0_1_1_1_2")); } catch { try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\terrain_templates\_0_0_1_1_1_2_0")); } catch { } } break; case @"levels\multi\snowbound\sky\shaders\skydome": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_0_0_0_0_0_0_0_0_0_0_0")); } catch { try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_0_0_0_0_0_0_0_0_0_0")); } catch { } } break; case @"levels\solo\020_base\lights\light_volume_hatlight": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\halogram_templates\_0_5_1_0_0_1_1")); } catch { } break; case @"levels\dlc\armory\shaders\metal_doodad_a": case @"levels\dlc\armory\shaders\metal_doodad_a_illum_blue": case @"levels\dlc\armory\shaders\metal_doodad_a_illum_cool": case @"levels\dlc\armory\shaders\metal_doodad_a_illum_red": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_7_2_0_1_1_0_1_0_0_0_0")); } catch { } break; case @"levels\dlc\armory\shaders\razor_wire": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_1_1_2_5_2_0_1_0_1_0")); } catch { } break; case @"levels\multi\deadlock\shaders\deadlock_concrete_wall_a_rubble": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_2_0_0_0_0_0_0_0_0_0")); } catch { } break; case @"levels\multi\snowbound\shaders\rock_cliffs": case @"levels\multi\snowbound\shaders\rock_rocky": case @"levels\multi\snowbound\shaders\rock_rocky_icy": case @"levels\solo\020_base\shaders\hb_metal_arch_unwrap_a": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_7_2_0_1_2_1_0_0_1_0_0")); } catch { } break; case @"levels\dlc\armory\shaders\concrete_wall_01": case @"levels\dlc\armory\shaders\concrete_wall_01_blue": case @"levels\dlc\armory\shaders\concrete_wall_01_red": case @"levels\dlc\armory\shaders\concrete_wall_02_blue": case @"levels\dlc\armory\shaders\concrete_wall_02_red": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_7_2_0_1_7_0_0_0_0_0_0")); } catch { } break; case @"objects\levels\solo\010_jungle\shaders\dam_fence": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_1_1_1_1_2_0_0_0_1_0")); } catch { } break; case @"levels\dlc\chillout\shaders\chillout_capsule_liquid": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\halogram_templates\_2_5_1_0_1_2_1")); } catch { } break; case @"levels\dlc\chillout\shaders\chillout_flood_godrays": case @"levels\dlc\chillout\shaders\chillout_invis_godrays": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\halogram_templates\_0_5_1_0_0_1_1")); } catch { } break; case @"objects\levels\dlc\chillout\shaders\chill_energy_blocker_small": case @"objects\levels\dlc\chillout\shaders\chill_viewing_area_blocker": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\halogram_templates\_0_8_1_0_0_4_1")); } catch { } break; case @"levels\dlc\chillout\shaders\chillout_floodroom01": case @"levels\dlc\chillout\shaders\chillout_floodroom02": case @"levels\dlc\chillout\shaders\chillout_floodroom03": case @"levels\dlc\chillout\shaders\chillout_transporter": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_2_0_1_1_2_5_0_0_1_0")); } catch { } break; case @"levels\dlc\chillout\shaders\chillout_flood_suckers": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_1_1_2_1_1_0_0_0_0_0")); } catch { } break; case @"levels\shared\shaders\flood\flood_sackyb": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_1_0_0_1_0_0_3_1_1_0")); } catch { } break; case @"objects\characters\flood_infection\shaders\flood_fronds": case @"objects\characters\flood_tank\shaders\flood_fronds": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_1_1_0_0_2_5_0_0_0_0")); } catch { } break; case @"objects\characters\flood_infection\shaders\flood_infection": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_2_0_1_1_0_1_0_0_1")); } catch { } break; case @"objects\weapons\melee\energy_blade\shaders\energy_blade": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_2_0_1_1_0_3_3_1_1_0")); } catch { try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_2_0_1_1_0_3_3_1_1_0_0")); } catch { } } break; case @"objects\weapons\rifle\plasma_rifle_red\shaders\plasma_rifle_red": case @"objects\weapons\rifle\plasma_rifle\shaders\plasma_rifle": case @"objects\weapons\rifle\covenant_carbine\shaders\carbine": case @"objects\weapons\rifle\covenant_carbine\shaders\carbine_dull": case @"objects\weapons\pistol\plasma_pistol\shaders\plasma_pistol_metal": case @"objects\weapons\pistol\needler\shaders\needler_blue": case @"objects\weapons\pistol\needler\shaders\needler_pink": case @"objects\weapons\support_high\flak_cannon\shaders\flak_cannon": case @"objects\weapons\rifle\beam_rifle\shaders\beam_rifle": case @"objects\weapons\rifle\beam_rifle\shaders\beam_rifle2": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_2_0_1_2_1_1_0_0_0_0")); } catch { try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_2_0_1_2_1_1_0_0_0_0_0")); } catch { } } break; case @"objects\weapons\pistol\needler\shaders\needler_glass": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_0_0_0_0_1_0_3_0_0_0")); } catch { try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_0_0_0_0_1_0_3_0_0_0_0")); } catch { } } break; case @"objects\weapons\rifle\sniper_rifle\shaders\scope_alpha": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\halogram_templates\_0_11_0_1_0_2_0")); } catch { } break; //Vehicles case @"objects\vehicles\scorpion\turrets\cannon\shaders\turret_cannon": try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_3_2_0_1_1_0_0_0_0_0_0")); } catch { } break; } // Find existing rmt2 tags // If tagnames are not fixed, ms30 tags have an additional _0 or _0_0. This shouldn't happen if the tags have proper names, so it's mostly to preserve compatibility with older tagnames using (var reader = new EndianReader(cacheStream, true)) { foreach (var instance in CacheContext.TagCache.Index) { if (instance == null || !instance.IsInGroup("rmt2") || instance.Name == null) { continue; } if (instance.Name.StartsWith(blamRmt2Tag.Name)) { reader.SeekTo(instance.HeaderOffset + instance.DefinitionOffset + 12); var vertexShaderIndex = reader.ReadInt32(); reader.SeekTo(instance.HeaderOffset + instance.DefinitionOffset + 28); var pixelShaderIndex = reader.ReadInt32(); if (!UseMS30 && (vertexShaderIndex >= 0x4455 || pixelShaderIndex >= 0x4455)) { continue; } return(instance); } } } // if no tagname matches, find rmt2 tags based on the most common values in the name return(FindEquivalentRmt2(cacheStream, blamRmt2Tag, blamRmt2Definition, bmMaps, bmArgs)); }
public CachedTagInstance FindEquivalentRmt2(Stream cacheStream, CacheFile.IndexItem blamRmt2Tag, RenderMethodTemplate blamRmt2Definition, List <string> bmMaps, List <string> bmArgs) { // Find similar shaders by finding tags with as many common bitmaps and arguments as possible. var edRmt2Temp = new List <ShaderTemplateItem>(); // Make a new dictionary with rmt2 of the same shader type var edRmt2BestStats = new List <ShaderTemplateItem>(); edRmt2BestStats = CollectRmt2Info(cacheStream, blamRmt2Tag, bmMaps, bmArgs); // rmt2 tagnames have a bunch of values, they're tagblock indexes in rmdf methods.ShaderOptions foreach (var d in edRmt2BestStats) { var dInstance = CacheContext.GetTag(d.rmt2TagIndex); if (dInstance == null || dInstance.Name == null) { continue; } var edSplit = dInstance.Name.Split("\\".ToCharArray()); var edType = edSplit[1]; var edRmdfValues = edSplit[2].Split("_".ToCharArray()).ToList(); edRmdfValues.RemoveAt(0); var bmSplit = blamRmt2Tag.Name.Split("\\".ToCharArray()); var bmType = bmSplit[1]; var bmRmdfValues = bmSplit[2].Split("_".ToCharArray()).ToList(); bmRmdfValues.RemoveAt(0); int matchingValues = 0; for (int i = 0; i < bmRmdfValues.Count; i++) { var weight = 0; if (bmRmdfValues[i] == edRmdfValues[i]) { switch (i) { case 00: case 06: weight = 1; break; } matchingValues = matchingValues + 1 + weight; } } d.rmdfValuesMatchingCount = matchingValues; if (edType != bmType) { d.rmdfValuesMatchingCount = 0; } } var edRmt2BestStatsSorted = edRmt2BestStats.OrderBy(x => x.rmdfValuesMatchingCount); if (edRmt2BestStats.Count == 0) { try { return(CacheContext.GetTag <RenderMethodTemplate>(@"shaders\shader_templates\_0_0_0_0_0_0_0_0_0_0_0")); } catch (KeyNotFoundException) { return(null); } } return(CacheContext.GetTag(edRmt2BestStatsSorted.Last().rmt2TagIndex)); }
private List <ShaderTemplateItem> CollectRmt2Info(Stream cacheStream, CacheFile.IndexItem bmRmt2Instance, List <string> bmMaps, List <string> bmArgs) { var edRmt2BestStats = new List <ShaderTemplateItem>(); var bmRmt2Context = new CacheSerializationContext(ref BlamCache, bmRmt2Instance); var bmRmt2 = BlamCache.Deserializer.Deserialize <RenderMethodTemplate>(bmRmt2Context); var bmPixlContext = new CacheSerializationContext(ref BlamCache, BlamCache.IndexItems.GetItemByID(bmRmt2.PixelShader.Index)); var bmPixl = BlamCache.Deserializer.Deserialize <PixelShader>(bmPixlContext); // loop trough all rmt2 and find the closest foreach (var edRmt2_ in Rmt2TagsInfo) { var rmt2Type = bmRmt2Instance.Name.Split("\\".ToArray())[1]; var edRmt2Tag = CacheContext.GetTag(edRmt2_.Key); // Ignore all rmt2 that are not of the same type. if (edRmt2Tag == null || !(edRmt2Tag.Name?.Contains(rmt2Type) ?? false)) { continue; } using (var reader = new EndianReader(cacheStream, true)) { reader.SeekTo(edRmt2Tag.HeaderOffset + edRmt2Tag.DefinitionOffset + 28); var edPixl = CacheContext.GetTag(reader.ReadInt32()); if (edPixl == null) { continue; } reader.SeekTo(edPixl.HeaderOffset + edPixl.DefinitionOffset + 0x4); var drawModeCount = reader.ReadInt32(); reader.SeekTo(edPixl.HeaderOffset + edPixl.DefinitionOffset + 0x14); var shaderCount = reader.ReadInt32(); if (bmPixl.DrawModes.Count > drawModeCount || bmPixl.Shaders.Count > shaderCount) { continue; } } int mapsCommon = 0; int argsCommon = 0; int mapsUncommon = 0; int argsUncommon = 0; int mapsMissing = 0; int argsMissing = 0; var edMaps_ = new List <string>(); var edArgs_ = new List <string>(); foreach (var a in edRmt2_.Value[0]) { edMaps_.Add(a); } foreach (var a in edRmt2_.Value[1]) { edArgs_.Add(a); } foreach (var a in bmMaps) { if (edMaps_.Contains(a)) { mapsCommon++; } } foreach (var a in bmMaps) { if (!edMaps_.Contains(a)) { mapsMissing++; } } foreach (var a in edMaps_) { if (!bmMaps.Contains(a)) { mapsUncommon++; } } foreach (var a in bmArgs) { if (edArgs_.Contains(a)) { argsCommon++; } } foreach (var a in bmArgs) { if (!edArgs_.Contains(a)) { argsMissing++; } } foreach (var a in edArgs_) { if (!bmArgs.Contains(a)) { argsUncommon++; } } edRmt2BestStats.Add(new ShaderTemplateItem { rmt2TagIndex = edRmt2_.Key, rmdfValuesMatchingCount = 0, mapsCountEd = edRmt2_.Value[0].Count, argsCountEd = edRmt2_.Value[1].Count, mapsCountBm = bmMaps.Count, argsCountBm = bmArgs.Count, mapsCommon = mapsCommon, argsCommon = argsCommon, mapsUncommon = mapsUncommon, argsUncommon = argsUncommon, mapsMissing = mapsMissing, argsMissing = argsMissing }); } return(edRmt2BestStats); }
public override object Execute(List <string> args) { var directory = ""; var blamTagName = ""; bool convertAll = false; if (args.Count == 2) { blamTagName = args[0]; directory = args[1]; } else if (args.Count == 1) { blamTagName = args[0]; directory = "Sounds"; } else { return(false); } if (args[0].ToLower() == "all") { convertAll = true; } if (!Directory.Exists(directory)) { Console.Write("Destination directory does not exist. Create it? [y/n] "); var answer = Console.ReadLine().ToLower(); if (answer.Length == 0 || !(answer.StartsWith("y") || answer.StartsWith("n"))) { return(false); } if (answer.StartsWith("y")) { Directory.CreateDirectory(directory); } else { return(false); } } if (!convertAll) { CacheFile.IndexItem blamTag = null; foreach (var tag in BlamCache.IndexItems) { if ((tag.GroupTag == "snd!") && (tag.Name == blamTagName)) { blamTag = tag; break; } } if (blamTag == null) { Console.WriteLine($"ERROR: Blam tag does not exist: {blamTagName}.sound"); return(true); } ExtractWAV(blamTag, directory); } else { foreach (var tag in BlamCache.IndexItems) { if ((tag.GroupTag == "snd!")) { ExtractWAV(tag, directory); } } } Console.WriteLine("done."); return(true); }
public XboxSerializationContext(CacheFile.IndexItem tag) { _tag = tag; }
private void MergeCharacter(Stream cacheStream, Dictionary <ResourceLocation, Stream> resourceStreams, CachedTagInstance edTag, CacheFile.IndexItem h3Tag) { var edDef = CacheContext.Deserialize <Character>(cacheStream, edTag); var h3Def = BlamCache.Deserializer.Deserialize <Character>( new CacheSerializationContext(ref BlamCache, h3Tag)); var merged = false; if (edDef.WeaponsProperties.Count == h3Def.WeaponsProperties.Count) { for (var i = 0; i < edDef.WeaponsProperties.Count; i++) { if (edDef.WeaponsProperties[i].Weapon != null || h3Def.WeaponsProperties[i].Weapon == null) { continue; } edDef.WeaponsProperties[i].Weapon = ConvertTag(cacheStream, resourceStreams, BlamCache.GetIndexItemFromID(h3Def.WeaponsProperties[i].Weapon.Index)); merged = true; } } if (edDef.VehicleProperties.Count == h3Def.VehicleProperties.Count) { for (var i = 0; i < edDef.VehicleProperties.Count; i++) { if (edDef.VehicleProperties[i].Unit != null || h3Def.VehicleProperties[i].Unit == null) { continue; } edDef.VehicleProperties[i].Unit = ConvertTag(cacheStream, resourceStreams, BlamCache.GetIndexItemFromID(h3Def.VehicleProperties[i].Unit.Index)); merged = true; } } if (edDef.EquipmentProperties.Count == h3Def.EquipmentProperties.Count) { for (var i = 0; i < edDef.EquipmentProperties.Count; i++) { if (edDef.EquipmentProperties[i].Equipment != null || h3Def.EquipmentProperties[i].Equipment == null) { continue; } edDef.EquipmentProperties[i].Equipment = ConvertTag(cacheStream, resourceStreams, BlamCache.GetIndexItemFromID(h3Def.EquipmentProperties[i].Equipment.Index)); merged = true; } } if (merged) { CacheContext.Serialize(cacheStream, edTag, edDef); } }