private bool ExecuteListDependsOn(TagInstance tag) { var dependsOn = _cache.Tags.NonNull().Where(t => t.Dependencies.Contains(tag.Index)); TagPrinter.PrintTagsShort(dependsOn); return(true); }
private void FixDecalSystems(GameCacheContextHaloOnline destCacheContext, int firstNewIndex) { // decs tags need to be updated to use the old rmdf for decals, // because the decal planes seem to be generated by the engine and // therefore need to use the old vertex format. // // This could probably be done as a post-processing step in // ConvertStructure to avoid the extra deserialize-reserialize // pass, but we'd have to store the rmdf somewhere and frankly I'm // too lazy to do that... var firstDecalSystemTag = destCacheContext.TagCache.FindFirstInGroup("decs"); if (firstDecalSystemTag == null) { return; } using (var stream = destCacheContext.OpenTagCacheReadWrite()) { var firstDecalSystem = destCacheContext.Deserialize <DecalSystem>(stream, firstDecalSystemTag); foreach (var decalSystemTag in destCacheContext.TagCache.Index.FindAllInGroup("decs").Where(t => t.Index >= firstNewIndex)) { TagPrinter.PrintTagShort(decalSystemTag); var decalSystem = destCacheContext.Deserialize <DecalSystem>(stream, decalSystemTag); foreach (var system in decalSystem.Decal) { system.RenderMethod.BaseRenderMethod = firstDecalSystem.Decal[0].RenderMethod.BaseRenderMethod; } destCacheContext.Serialize(stream, decalSystemTag, decalSystem); } } }
public override bool Execute(List <string> args) { if (args.Count != 0) { return(false); } foreach (var tag in Info.Cache.Tags) { if (tag == null) { continue; } var dependsOn = Info.Cache.Tags.NonNull().Where(t => t.Dependencies.Contains(tag.Index)); if (dependsOn.Count() == 0) { Console.Write($"{Info.TagNames[tag.Index]} "); TagPrinter.PrintTagShort(tag); } } return(true); }
public static TagInstance ConvertTag(TagInstance srcTag, OpenTagCache srcInfo, Stream srcStream, ResourceDataManager srcResources, OpenTagCache destInfo, Stream destStream, ResourceDataManager destResources, TagCacheMap tagMap) { TagPrinter.PrintTagShort(srcTag); // Deserialize the tag from the source cache var structureType = TagStructureTypes.FindByGroupTag(srcTag.Group.Tag); var srcContext = new TagSerializationContext(srcStream, srcInfo.Cache, srcInfo.StringIDs, srcTag); var tagData = srcInfo.Deserializer.Deserialize(srcContext, structureType); // Acquire the destination tag var destTag = destInfo.Cache.AllocateTag(srcTag.Group); tagMap.Add(srcInfo.CacheFile.FullName, srcTag.Index, destInfo.CacheFile.FullName, destTag.Index); if (srcTag.IsInGroup("decs") || srcTag.IsInGroup("rmd ")) { IsDecalShader = true; } // Convert the source tag tagData = Convert(tagData, srcInfo, srcStream, srcResources, destInfo, destStream, destResources, tagMap); if (srcTag.IsInGroup("decs") || srcTag.IsInGroup("rmd ")) { IsDecalShader = false; } // Re-serialize into the destination cache var destContext = new TagSerializationContext(destStream, destInfo.Cache, destInfo.StringIDs, destTag); destInfo.Serializer.Serialize(destContext, tagData); return(destTag); }
private bool ExecuteListDependsOn(HaloTag tag) { var dependsOn = _cache.Tags.Where(t => t != null && t.Dependencies.Contains(tag.Index)); TagPrinter.PrintTagsShort(dependsOn); 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 static void FixDecalSystems(OpenTagCache destInfo, int firstNewIndex) { // decs tags need to be updated to use the old rmdf for decals, // because the decal planes seem to be generated by the engine and // therefore need to use the old vertex format. // // This could probably be done as a post-processing step in // ConvertStructure to avoid the extra deserialize-reserialize // pass, but we'd have to store the rmdf somewhere and frankly I'm // too lazy to do that... var firstDecalSystemTag = destInfo.Cache.Tags.FindFirstInGroup("decs"); if (firstDecalSystemTag == null) { return; } using (var stream = destInfo.OpenCacheReadWrite()) { var firstDecalSystemContext = new TagSerializationContext(stream, destInfo.Cache, destInfo.StringIDs, firstDecalSystemTag); var firstDecalSystem = destInfo.Deserializer.Deserialize <DecalSystem>(firstDecalSystemContext); foreach (var decalSystemTag in destInfo.Cache.Tags.FindAllInGroup("decs").Where(t => t.Index >= firstNewIndex)) { TagPrinter.PrintTagShort(decalSystemTag); var context = new TagSerializationContext(stream, destInfo.Cache, destInfo.StringIDs, decalSystemTag); var decalSystem = destInfo.Deserializer.Deserialize <DecalSystem>(context); foreach (var system in decalSystem.DecalSystem2) { system.BaseRenderMethod = firstDecalSystem.DecalSystem2[0].BaseRenderMethod; } destInfo.Serializer.Serialize(context, decalSystem); } } }
public override bool Execute(List <string> args) { var searchClasses = ArgumentParser.ParseTagClasses(_cache, args); if (searchClasses == null) { return(false); } TagInstance[] tags; if (args.Count > 0) { tags = _cache.Tags.FindAllInGroups(searchClasses).ToArray(); } else { tags = _cache.Tags.NonNull().ToArray(); } if (tags.Length == 0) { Console.Error.WriteLine("No tags found."); return(true); } TagPrinter.PrintTagsShort(tags); return(true); }
public override bool Execute(List <string> args) { if (args.Count != 2) { return(false); } var outDir = args[1]; ITagLayoutWriter writer; switch (args[0]) { case "csharp": writer = new CSharpClassWriter(_stringIds, outDir); break; case "cpp": writer = new CppStructWriter(_stringIds, outDir); break; default: return(false); } Directory.CreateDirectory(outDir); var count = 0; using (var stream = _fileInfo.OpenRead()) { foreach (var tagClass in _cache.TagClasses) { TagLayoutGuess layout = null; HaloTag lastTag = null; foreach (var tag in _cache.Tags.FindAllByClass(tagClass)) { Console.Write("Analyzing "); TagPrinter.PrintTagShort(tag); lastTag = tag; var analyzer = new TagAnalyzer(_cache, tag); var data = _cache.ExtractTag(stream, tag); var tagLayout = analyzer.Analyze(data); if (layout != null) { layout.Merge(tagLayout); } else { layout = tagLayout; } } if (layout != null && lastTag != null) { Console.WriteLine("Writing {0} layout", tagClass); LayoutGuessWriter.Write(lastTag, layout, writer); count++; } } } Console.WriteLine("Successfully generated {0} layouts!", count); 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); }
private TagInstance ConvertTag(TagInstance srcTag, OpenTagCache srcInfo, Stream srcStream, ResourceDataManager srcResources, OpenTagCache destInfo, Stream destStream, ResourceDataManager destResources, TagVersionMap tagMap) { TagPrinter.PrintTagShort(srcTag); // Uncomment this to use 0x101F for all shaders /*if (srcTag.IsClass("rm ")) * return destInfo.Cache.Tags[0x101F];*/ // Check if the tag is in the map, and just return the translated tag if so var destIndex = tagMap.Translate(srcInfo.Version, srcTag.Index, destInfo.Version); if (destIndex >= 0) { Console.WriteLine("- Using already-known index {0:X4}", destIndex); return(destInfo.Cache.Tags[destIndex]); } // Deserialize the tag from the source cache var structureType = TagStructureTypes.FindByGroupTag(srcTag.Group.Tag); var srcContext = new TagSerializationContext(srcStream, srcInfo.Cache, srcInfo.StringIDs, srcTag); var tagData = srcInfo.Deserializer.Deserialize(srcContext, structureType); // Uncomment this to use 0x101F in place of shaders that need conversion /*if (tagData is RenderMethod) * { * var rm = (RenderMethod)tagData; * foreach (var prop in rm.ShaderProperties) * { * if (tagMap.Translate(srcInfo.Version, prop.Template.Index, destInfo.Version) < 0) * return destInfo.Cache.Tags[0x101F]; * } * }*/ // Allocate a new tag and create a mapping for it var newTag = destInfo.Cache.AllocateTag(srcTag.Group); tagMap.Add(srcInfo.Version, srcTag.Index, destInfo.Version, newTag.Index); if (srcTag.IsInGroup("decs") || srcTag.IsInGroup("rmd ")) { _isDecalShader = true; } // Convert it tagData = Convert(tagData, srcInfo, srcStream, srcResources, destInfo, destStream, destResources, tagMap); if (srcTag.IsInGroup("decs") || srcTag.IsInGroup("rmd ")) { _isDecalShader = false; } // Re-serialize into the destination cache var destContext = new TagSerializationContext(destStream, destInfo.Cache, destInfo.StringIDs, newTag); destInfo.Serializer.Serialize(destContext, tagData); return(newTag); }
public override object Execute(List <string> args) { if (args.Count != 1) { return(false); } var outDir = args[0]; Directory.CreateDirectory(outDir); Console.WriteLine("Loading resource caches..."); var count = 0; using (var tagsStream = CacheContext.OpenTagCacheRead()) { var extractor = new BitmapDdsExtractor(CacheContext); foreach (var tag in CacheContext.TagCache.Index.FindAllInGroup("bitm")) { Console.Write("Extracting "); TagPrinter.PrintTagShort(tag); #if !DEBUG try { #endif var bitmap = CacheContext.Deserialize <Bitmap>(tagsStream, tag); 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(bitmap, i, outStream); } count++; #if !DEBUG } catch (Exception ex) { Console.WriteLine("ERROR: Failed to extract bitmap: " + ex.Message); } #endif } } Console.WriteLine("Extracted {0} bitmaps.", count); return(true); }
public override object Execute(List <string> args) { if (args.Count != 0) { return(false); } var depCounts = new Dictionary <int, int>(); foreach (var tag in CacheContext.TagCache.Index) { if (tag == null) { continue; } foreach (var dep in tag.Dependencies) { var depTag = CacheContext.GetTag(dep); if (depTag == null) { continue; } if (!depCounts.ContainsKey(dep)) { depCounts[dep] = 0; } depCounts[dep]++; } } for (var i = 0; i < CacheContext.TagCache.Index.Count; i++) { var tag = CacheContext.GetTag(i); if (tag == null || tag.IsInGroup("cfgt") || tag.IsInGroup("scnr")) { continue; } if (depCounts.ContainsKey(i)) { continue; } var tagName = tag.Name ?? "<unnamed>"; Console.Write($"{tagName} "); TagPrinter.PrintTagShort(tag); } return(true); }
private bool ExecuteList(HaloTag tag, bool all) { if (tag.Dependencies.Count == 0) { Console.Error.WriteLine("Tag {0:X8} has no dependencies.", tag.Index); return(true); } IEnumerable <HaloTag> dependencies; if (all) { dependencies = _cache.Tags.FindDependencies(tag); } else { dependencies = tag.Dependencies.Where(i => _cache.Tags.Contains(i)).Select(i => _cache.Tags[i]); } TagPrinter.PrintTagsShort(dependencies); return(true); }
public override bool Execute(List <string> args) { if (args.Count != 1) { return(false); } var tag = ArgumentParser.ParseTagIndex(_cache, args[0]); if (tag == null) { return(false); } HaloTag newTag; using (var stream = _fileInfo.Open(FileMode.Open, FileAccess.ReadWrite)) newTag = _cache.DuplicateTag(stream, tag); Console.WriteLine("Tag duplicated successfully!"); Console.Write("New tag: "); TagPrinter.PrintTagShort(newTag); return(true); }
public override bool Execute(List <string> args) { if (args.Count != 1) { return(false); } var tag = ArgumentParser.ParseTagIndex(_info.Cache, args[0]); if (tag == null) { return(false); } TagInstance newTag; using (var stream = _info.OpenCacheReadWrite()) newTag = _info.Cache.DuplicateTag(stream, tag); Console.WriteLine("Tag duplicated successfully!"); Console.Write("New tag: "); TagPrinter.PrintTagShort(newTag); return(true); }
public override object Execute(List <string> args) { if (args.Count != 1) { return(false); } if (!CacheContext.TryGetTag(args[0], out var tag)) { return(false); } CachedTagInstance newTag; using (var stream = CacheContext.OpenTagCacheReadWrite()) newTag = CacheContext.TagCache.DuplicateTag(stream, tag); Console.WriteLine("Tag duplicated successfully!"); Console.Write("New tag: "); TagPrinter.PrintTagShort(newTag); return(true); }
public override object Execute(List <string> args) { //Arguments needed: filepath, <new>|<tagIndex> if (args.Count < 2) { return(false); } CachedTagInstance 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 { if (!CacheContext.TryGetTag(args[1], out tag)) { 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 = CacheContext.OpenTagCacheReadWrite()) { if (b_duplicate) { //duplicate an existing tag, trashcan phmo tag = CacheContext.TagCache.DuplicateTag(stream, CacheContext.TagCache.Index[0x4436]); if (tag == null) { Console.WriteLine("Failed tag duplication."); return(false); } } CacheContext.Serialize(stream, tag, 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 object Execute(List <string> args) { if (args.Count != 2) { return(false); } var type = args[0]; var outDir = args[1]; TagLayoutWriter writer; switch (type.ToLower()) { case "c#": case "cs": case "csharp": writer = new CSharpLayoutWriter(); break; case "c++": case "cpp": case "cplusplus": writer = new CppLayoutWriter(); break; default: return(false); } Directory.CreateDirectory(outDir); var count = 0; using (var stream = CacheContext.OpenTagCacheRead()) { foreach (var groupTag in CacheContext.TagCache.Index.NonNull().Select(t => t.Group.Tag).Distinct()) { TagLayoutGuess layout = null; CachedTagInstance lastTag = null; foreach (var tag in CacheContext.TagCache.Index.FindAllInGroup(groupTag)) { Console.Write("Analyzing "); TagPrinter.PrintTagShort(tag); lastTag = tag; var analyzer = new TagAnalyzer(CacheContext.TagCache); var data = CacheContext.TagCache.ExtractTag(stream, tag); var tagLayout = analyzer.Analyze(data); if (layout != null) { layout.Merge(tagLayout); } else { layout = tagLayout; } } if (layout != null && lastTag != null) { Console.WriteLine("Writing {0} layout", groupTag); var name = CacheContext.GetString(lastTag.Group.Name); var tagLayout = LayoutGuessFinalizer.MakeLayout(layout, name, groupTag); var path = Path.Combine(outDir, writer.GetSuggestedFileName(tagLayout)); writer.WriteLayout(tagLayout, path); count++; } } } Console.WriteLine("Successfully generated {0} layouts!", count); return(true); }
public override object Execute(List <string> args) { //Arguments needed: filepath, <new>|<tagIndex> if (args.Count < 2) { return(false); } CachedTagInstance 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 { if (!CacheContext.TryGetTag(args[1], out tag)) { 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 = CacheContext.OpenTagCacheReadWrite()) { if (b_duplicate) { //duplicate an existing tag, trashcan phmo tag = CacheContext.TagCache.DuplicateTag(stream, CacheContext.TagCache.Index[0x4436]); if (tag == null) { Console.WriteLine("Failed tag duplication."); return(false); } } CacheContext.Serialize(stream, tag, phmo); } Console.Write("Successfully imported phmo to: "); TagPrinter.PrintTagShort(tag); return(true); }
public override bool Execute(List <string> args) { if (args.Count < 2) { return(false); } var outputPath = args[0]; // Load each file and do version detection var infos = new List <OpenTagCache>(); foreach (var path in args.Skip(1)) { Console.WriteLine("Loading {0}...", path); // Load the cache file var info = new OpenTagCache { CacheFile = new FileInfo(path) }; using (var stream = info.OpenCacheRead()) info.Cache = new TagCache(stream); // Do version detection, and don't accept the closest version // because that might not work EngineVersion closestVersion; info.Version = VersionDetection.DetectVersion(info.Cache, out closestVersion); if (info.Version == EngineVersion.Unknown) { Console.WriteLine("- Unrecognized version! Ignoring."); continue; } info.Deserializer = new TagDeserializer(info.Version); infos.Add(info); } var result = new TagVersionMap(); using (var baseStream = _info.OpenCacheRead()) { // Get the scenario tags for this cache Console.WriteLine("Finding base scenario tags..."); var baseScenarios = FindScenarios(_info, baseStream); var baseVersion = _info.Version; var baseTagData = new Dictionary <int, object>(); foreach (var scenario in baseScenarios) { baseTagData[scenario.Tag.Index] = scenario.Data; } // Now compare with each of the other caches foreach (var info in infos) { using (var stream = info.OpenCacheRead()) { Console.WriteLine("Finding scenario tags in {0}...", info.CacheFile.FullName); // Get the scenario tags and connect them to the base tags var scenarios = FindScenarios(info, stream); var tagsToCompare = new Queue <QueuedTag>(); for (var i = 0; i < scenarios.Count; i++) { tagsToCompare.Enqueue(scenarios[i]); if (i < baseScenarios.Count) { result.Add(baseVersion, baseScenarios[i].Tag.Index, info.Version, scenarios[i].Tag.Index); } } // Process each tag in the queue, enqueuing all of its dependencies as well while (tagsToCompare.Count > 0) { // Get the tag and its data var tag = tagsToCompare.Dequeue(); TagPrinter.PrintTagShort(tag.Tag); var data = tag.Data; if (data == null) { // No data yet - deserialize it var context = new TagSerializationContext(stream, info.Cache, info.StringIds, tag.Tag); var type = TagStructureTypes.FindByGroupTag(tag.Tag.Group.Tag); data = info.Deserializer.Deserialize(context, type); } // Now get the data for the base tag var baseTag = result.Translate(info.Version, tag.Tag.Index, baseVersion); if (baseTag == -1 || _info.Cache.Tags[baseTag].Group.Tag != tag.Tag.Group.Tag) { continue; } object baseData; if (!baseTagData.TryGetValue(baseTag, out baseData)) { // No data yet - deserialize it var context = new TagSerializationContext(baseStream, _info.Cache, _info.StringIds, _info.Cache.Tags[baseTag]); var type = TagStructureTypes.FindByGroupTag(tag.Tag.Group.Tag); baseData = _info.Deserializer.Deserialize(context, type); baseTagData[baseTag] = baseData; } // Compare the two blocks CompareBlocks(baseData, baseVersion, data, info.Version, result, tagsToCompare); } } } } // Write out the CSV Console.WriteLine("Writing results..."); using (var writer = new StreamWriter(File.Open(outputPath, FileMode.Create, FileAccess.Write))) result.WriteCsv(writer); Console.WriteLine("Done!"); return(true); }
private CachedTagHaloOnline ConvertTag(CachedTagHaloOnline srcTag, GameCacheContextHaloOnline srcCacheContext, Stream srcStream, GameCacheContextHaloOnline destCacheContext, Stream destStream, TagVersionMap tagMap) { TagPrinter.PrintTagShort(srcTag); // Uncomment this to use 0x101F for all shaders /*if (srcTag.IsClass("rm ")) * return destCacheContext.Cache.Tags[0x101F];*/ // Check if the tag is in the map, and just return the translated tag if so var destIndex = tagMap.Translate(srcCacheContext.Version, srcTag.Index, destCacheContext.Version); if (destIndex >= 0) { Console.WriteLine("- Using already-known index {0:X4}", destIndex); return(destCacheContext.TagCache.Index[destIndex]); } // Deserialize the tag from the source cache var tagData = srcCacheContext.Deserialize(srcStream, srcTag); // Uncomment this to use 0x101F in place of shaders that need conversion /*if (tagData is RenderMethod) * { * var rm = (RenderMethod)tagData; * foreach (var prop in rm.ShaderProperties) * { * if (tagMap.Translate(srcCacheContext.Version, prop.Template.Index, destCacheContext.Version) < 0) * return destCacheContext.Cache.Tags[0x101F]; * } * }*/ // Allocate a new tag and create a mapping for it CachedTagHaloOnline instance = null; if (srcCacheContext.Version != destCacheContext.Version) { for (var i = 0; i < destCacheContext.TagCache.Index.Count; i++) { if (destCacheContext.TagCache.Index[i] == null) { destCacheContext.TagCache.Index[i] = instance = new CachedTagHaloOnline(i, TagGroup.Instances[srcTag.Group.Tag]); break; } } } else { if (destCacheContext.TagCache.Index[srcTag.Index] != null) { if (destCacheContext.TagCache.Index[srcTag.Index].IsInGroup(srcTag.Group)) { return(destCacheContext.TagCache.Index[srcTag.Index]); } } else { destCacheContext.TagCache.Index[srcTag.Index] = instance = new CachedTagHaloOnline(srcTag.Index, TagGroup.Instances[srcTag.Group.Tag], srcTag.Name); } } if (instance == null) { instance = destCacheContext.TagCache.AllocateTag(srcTag.Group); } tagMap.Add(srcCacheContext.Version, srcTag.Index, destCacheContext.Version, instance.Index); if (srcTag.IsInGroup("decs") || srcTag.IsInGroup("rmd ")) { IsDecalShader = true; } // Convert it tagData = Convert(tagData, srcCacheContext, srcStream, destCacheContext, destStream, tagMap); if (srcTag.IsInGroup("decs") || srcTag.IsInGroup("rmd ")) { IsDecalShader = false; } // Re-serialize into the destination cache destCacheContext.Serialize(destStream, instance, tagData); return(instance); }
public override object Execute(List <string> args) { if (args.Count != 4) { return(false); } if (!CacheContext.TryGetTag(args[0], out var srcTag)) { return(false); } var csvPath = args[1]; var csvOutPath = args[2]; var targetDir = args[3]; // Load the CSV Console.WriteLine("Reading {0}...", csvPath); TagVersionMap tagMap; using (var reader = new StreamReader(File.Exists(csvPath) ? File.OpenRead(csvPath) : File.Create(csvPath))) tagMap = TagVersionMap.ParseTagVersionMap(reader); // Load destination cache files var destCacheContext = new GameCacheContextHaloOnline(new DirectoryInfo(targetDir)); using (var stream = destCacheContext.OpenTagCacheRead()) destCacheContext.TagCache = new TagCache(stream, destCacheContext.LoadTagNames()); Console.WriteLine(); Console.WriteLine("CONVERTING FROM VERSION {0} TO {1}", CacheVersionDetection.GetBuildName(CacheContext.Version), CacheVersionDetection.GetBuildName(destCacheContext.Version)); Console.WriteLine(); CachedTagHaloOnline resultTag; using (Stream srcStream = CacheContext.TagCache.OpenTagCacheRead(), destStream = destCacheContext.OpenTagCacheReadWrite()) resultTag = ConvertTag(srcTag, CacheContext, srcStream, destCacheContext, destStream, tagMap); Console.WriteLine(); Console.WriteLine("Repairing decal systems..."); if (CacheContext.Version != destCacheContext.Version) { FixDecalSystems(destCacheContext, resultTag.Index); } Console.WriteLine(); Console.WriteLine("Saving stringIDs..."); using (var stream = destCacheContext.OpenStringIdCacheReadWrite()) destCacheContext.StringIdCache.Save(stream); Console.WriteLine("Writing {0}...", csvOutPath); using (var stream = new StreamWriter(File.Open(csvOutPath, FileMode.Create, FileAccess.ReadWrite))) tagMap.WriteCsv(stream); // Uncomment this to add the new tag as a dependency to cfgt to make testing easier /*using (var stream = destCacheContext.OpenCacheReadWrite()) * { * destCacheContext.Cache.Tags[0].Dependencies.Add(resultTag.Index); * destCacheContext.Cache.UpdateTag(stream, destCacheContext.Cache.Tags[0]); * }*/ Console.WriteLine(); Console.WriteLine("All done! The converted tag is:"); TagPrinter.PrintTagShort(resultTag); destCacheContext.SaveTagNames(); return(true); }
public override object Execute(List <string> args) { if (args.Count < 2) { return(false); } var outputPath = args[0]; // Load each file and do version detection var infos = new List <HaloOnlineCacheContext>(); foreach (var path in args.Skip(1)) { Console.WriteLine("Loading {0}...", path); // Load the cache file var cacheContext = new HaloOnlineCacheContext(new FileInfo(path).Directory); infos.Add(cacheContext); } var result = new TagVersionMap(); using (var baseStream = CacheContext.OpenTagCacheRead()) { // Get the scenario tags for this cache Console.WriteLine("Finding base scenario tags..."); var baseScenarios = FindScenarios(CacheContext, baseStream); var baseVersion = CacheContext.Version; var baseTagData = new Dictionary <int, object>(); foreach (var scenario in baseScenarios) { baseTagData[scenario.Tag.Index] = scenario.Data; } // Now compare with each of the other caches foreach (var info in infos) { using (var stream = info.OpenTagCacheRead()) { Console.WriteLine("Finding scenario tags in {0}...", info.TagCacheFile.FullName); // Get the scenario tags and connect them to the base tags var scenarios = FindScenarios(info, stream); var tagsToCompare = new Queue <QueuedTag>(); for (var i = 0; i < scenarios.Count; i++) { tagsToCompare.Enqueue(scenarios[i]); if (i < baseScenarios.Count) { result.Add(baseVersion, baseScenarios[i].Tag.Index, info.Version, scenarios[i].Tag.Index); } } // Process each tag in the queue, enqueuing all of its dependencies as well while (tagsToCompare.Count > 0) { // Get the tag and its data var tag = tagsToCompare.Dequeue(); TagPrinter.PrintTagShort(tag.Tag); var data = tag.Data; if (data == null) { // No data yet - deserialize it var context = new TagSerializationContext(stream, info, tag.Tag); var type = TagDefinition.Find(tag.Tag.Group.Tag); data = info.Deserializer.Deserialize(context, type); } // Now get the data for the base tag var baseTag = result.Translate(info.Version, tag.Tag.Index, baseVersion); if (baseTag == -1 || CacheContext.TagCache.Index[baseTag].Group.Tag != tag.Tag.Group.Tag) { continue; } if (!baseTagData.TryGetValue(baseTag, out object baseData)) { // No data yet - deserialize it var context = new TagSerializationContext(baseStream, CacheContext, CacheContext.TagCache.Index[baseTag]); var type = TagDefinition.Find(tag.Tag.Group.Tag); baseData = CacheContext.Deserializer.Deserialize(context, type); baseTagData[baseTag] = baseData; } // Compare the two blocks CompareBlocks(baseData, baseVersion, data, info.Version, result, tagsToCompare); } } } } // Write out the CSV Console.WriteLine("Writing results..."); using (var writer = new StreamWriter(File.Open(outputPath, FileMode.Create, FileAccess.Write))) result.WriteCsv(writer); Console.WriteLine("Done!"); return(true); }
public override bool Execute(List <string> args) { if (args.Count != 4) { return(false); } var srcTag = ArgumentParser.ParseTagIndex(_info, args[0]); if (srcTag == null) { return(false); } var csvPath = args[1]; var csvOutPath = args[2]; var targetDir = args[3]; // Load the CSV Console.WriteLine("Reading {0}...", csvPath); TagVersionMap tagMap; using (var reader = new StreamReader(File.OpenRead(csvPath))) tagMap = TagVersionMap.ParseTagVersionMap(reader); // Load destination files Console.WriteLine("Loading the target tags.dat..."); var destCachePath = Path.Combine(targetDir, "tags.dat"); var destInfo = new OpenTagCache { CacheFile = new FileInfo(destCachePath) }; using (var stream = destInfo.OpenCacheRead()) destInfo.Cache = new TagCache(stream); // Do version detection DefinitionSet guessedVersion; destInfo.Version = Definition.Detect(destInfo.Cache, out guessedVersion); if (destInfo.Version == DefinitionSet.Unknown) { Console.WriteLine("Unrecognized target version!"); return(true); } Console.WriteLine("- Detected version {0}", Definition.GetVersionString(destInfo.Version)); if (_info.Version != DefinitionSet.HaloOnline498295 && destInfo.Version != DefinitionSet.HaloOnline106708) { Console.Error.WriteLine("Conversion is only supported from 11.1.498295 Live to 1.106708 cert_ms23."); return(true); } // Set up version-specific objects destInfo.Serializer = new TagSerializer(destInfo.Version); destInfo.Deserializer = new TagDeserializer(destInfo.Version); // Load stringIDs Console.WriteLine("Loading the target string_ids.dat..."); var resolver = StringIDResolverFactory.Create(destInfo.Version); var destStringIDsPath = Path.Combine(targetDir, "string_ids.dat"); destInfo.StringIDsFile = new FileInfo(destStringIDsPath); using (var stream = destInfo.StringIDsFile.OpenRead()) destInfo.StringIDs = new StringIDCache(stream, resolver); // Load resources for the target build Console.WriteLine("Loading target resources..."); var destResources = new ResourceDataManager(); destResources.LoadCachesFromDirectory(destInfo.CacheFile.DirectoryName); // Load resources for our build Console.WriteLine("Loading source resources..."); var srcResources = new ResourceDataManager(); srcResources.LoadCachesFromDirectory(_info.CacheFile.DirectoryName); Console.WriteLine(); Console.WriteLine("CONVERTING FROM VERSION {0} TO {1}", Definition.GetVersionString(_info.Version), Definition.GetVersionString(destInfo.Version)); Console.WriteLine(); TagInstance resultTag; using (Stream srcStream = _info.OpenCacheRead(), destStream = destInfo.OpenCacheReadWrite()) resultTag = ConvertTag(srcTag, _info, srcStream, srcResources, destInfo, destStream, destResources, tagMap); Console.WriteLine(); Console.WriteLine("Repairing decal systems..."); FixDecalSystems(destInfo, resultTag.Index); Console.WriteLine(); Console.WriteLine("Saving stringIDs..."); using (var stream = destInfo.StringIDsFile.Open(FileMode.Open, FileAccess.ReadWrite)) destInfo.StringIDs.Save(stream); Console.WriteLine("Writing {0}...", csvOutPath); using (var stream = new StreamWriter(File.Open(csvOutPath, FileMode.Create, FileAccess.ReadWrite))) tagMap.WriteCsv(stream); // Uncomment this to add the new tag as a dependency to cfgt to make testing easier /*using (var stream = destInfo.OpenCacheReadWrite()) * { * destInfo.Cache.Tags[0].Dependencies.Add(resultTag.Index); * destInfo.Cache.UpdateTag(stream, destInfo.Cache.Tags[0]); * }*/ Console.WriteLine(); Console.WriteLine("All done! The converted tag is:"); TagPrinter.PrintTagShort(resultTag); return(true); }
public override bool Execute(List <string> args) { if (args.Count != 3) { return(false); } var entry = args[0]; var type = args[1]; var outDir = args[2]; TagLayoutWriter writer; switch (type) { case "csharp": writer = new CSharpLayoutWriter(); break; case "cpp": writer = new CppLayoutWriter(); break; default: return(false); } Directory.CreateDirectory(outDir); var count = 0; using (var stream = _info.OpenCacheRead()) { //foreach (var groupTag in _cache.Tags.NonNull().Select(t => t.Group.Tag).Distinct()) var groupTag = ArgumentParser.ParseTagIndex(_info, entry).Group.Tag; { TagLayoutGuess layout = null; TagInstance lastTag = null; foreach (var tag in _cache.Tags.FindAllInGroup(groupTag)) { Console.Write("Analyzing "); TagPrinter.PrintTagShort(tag); lastTag = tag; var analyzer = new TagAnalyzer(_cache); var data = _cache.ExtractTag(stream, tag); var tagLayout = analyzer.Analyze(data); if (layout != null) { layout.Merge(tagLayout); } else { layout = tagLayout; } } if (layout != null && lastTag != null) { Console.WriteLine("Writing {0} layout", groupTag); var name = _info.StringIDs.GetString(lastTag.Group.Name); var tagLayout = LayoutGuessFinalizer.MakeLayout(layout, name, groupTag); var path = Path.Combine(outDir, writer.GetSuggestedFileName(tagLayout)); writer.WriteLayout(tagLayout, path); count++; } } } Console.WriteLine("Successfully generated {0} layouts!", count); return(true); }