public static TagInstance ParseTagName(OpenTagCache info, string name) { if (name.Length == 0 || !char.IsLetter(name[0]) || !name.Contains('.')) throw new Exception($"Invalid tag name: {name}"); var namePieces = name.Split('.'); var groupTag = ParseGroupTag(info.StringIDs, namePieces[1]); if (groupTag == Tag.Null) throw new Exception($"Invalid tag name: {name}"); var tagName = namePieces[0]; foreach (var nameEntry in info.TagNames) { if (nameEntry.Value == tagName) { var instance = info.Cache.Tags[nameEntry.Key]; if (instance.Group.Tag == groupTag) return instance; } } Console.WriteLine($"Invalid tag name: {name}"); return null; }
public static CommandContext Create(CommandContextStack stack, OpenTagCache info) { var context = new CommandContext(null, info.CacheFile.Name); context.AddCommand(new HelpCommand(stack)); context.AddCommand(new ClearCommand()); context.AddCommand(new DumpLogCommand()); context.AddCommand(new EchoCommand()); context.AddCommand(new DependencyCommand(info)); context.AddCommand(new ExtractCommand(info)); context.AddCommand(new ImportCommand(info)); context.AddCommand(new InfoCommand(info)); context.AddCommand(new ListCommand(info)); context.AddCommand(new MapCommand()); context.AddCommand(new DuplicateTagCommand(info)); context.AddCommand(new AddressCommand()); context.AddCommand(new ResourceDataCommand()); if (info.StringIds != null) { context.AddCommand(new EditCommand(stack, info)); context.AddCommand(new ExtractBitmapsCommand(info)); context.AddCommand(new ImportBitmapCommand(info)); context.AddCommand(new CollisionGeometryTestCommand(info)); context.AddCommand(new PhysicsModelTestCommand(info)); context.AddCommand(new StringIdCommand(info)); context.AddCommand(new ListStringsCommand(info)); context.AddCommand(new GenerateLayoutsCommand(info)); context.AddCommand(new ModelTestCommand(info)); context.AddCommand(new ConvertPluginsCommand(info)); context.AddCommand(new GenerateTagNamesCommand(info)); context.AddCommand(new MatchTagsCommand(info)); context.AddCommand(new ConvertCommand(info)); } return context; }
public static CommandContext Create(CommandContext parent, OpenTagCache info, HaloTag tag, Model model) { var context = new CommandContext(parent, string.Format("{0:X8}.hlmt", tag.Index)); context.AddCommand(new HlmtListVariantsCommand(info, model)); context.AddCommand(new HlmtExtractModeCommand(info, model)); return context; }
public static CommandContext Create(CommandContextStack stack, OpenTagCache info) { var context = new CommandContext(null, info.CacheFile.Name); context.AddCommand(new HelpCommand(stack)); context.AddCommand(new DependencyCommand(info)); context.AddCommand(new FixupCommand(info)); context.AddCommand(new ExtractCommand(info)); context.AddCommand(new ImportCommand(info)); context.AddCommand(new InfoCommand(info)); context.AddCommand(new InsertCommand(info)); context.AddCommand(new ListCommand(info)); context.AddCommand(new MapCommand()); context.AddCommand(new EditCommand(stack, info)); context.AddCommand(new DuplicateTagCommand(info)); context.AddCommand(new AddressCommand()); context.AddCommand(new ExtractBitmapsCommand(info)); context.AddCommand(new ResourceDataCommand()); context.AddCommand(new TagBlockCommand(info)); if (info.StringIds != null) { context.AddCommand(new StringIdCommand(info)); context.AddCommand(new ListStringsCommand(info)); context.AddCommand(new GenerateLayoutsCommand(info)); context.AddCommand(new ModelTestCommand(info)); } return context; }
public static void Populate(CommandContext context, OpenTagCache info, TagInstance tag) { RenderMethod renderMethod = null; using (var cacheStream = info.OpenCacheReadWrite()) { var tagContext = new TagSerializationContext(cacheStream, info.Cache, info.StringIds, tag); switch (tag.Group.Tag.ToString()) { case "rm ": // render_method renderMethod = info.Deserializer.Deserialize<RenderMethod>(tagContext); break; case "rmsh": // shader renderMethod = info.Deserializer.Deserialize<Shader>(tagContext); break; case "rmd ": // shader_decal renderMethod = info.Deserializer.Deserialize<ShaderDecal>(tagContext); break; case "rmfl": // shader_foliage renderMethod = info.Deserializer.Deserialize<ShaderFoliage>(tagContext); break; case "rmhg": // shader_halogram renderMethod = info.Deserializer.Deserialize<ShaderHalogram>(tagContext); break; case "rmss": // shader_screen renderMethod = info.Deserializer.Deserialize<ShaderScreen>(tagContext); break; case "rmtr": // shader_terrain renderMethod = info.Deserializer.Deserialize<ShaderTerrain>(tagContext); break; case "rmw ": // shader_water renderMethod = info.Deserializer.Deserialize<ShaderWater>(tagContext); break; case "rmzo": // shader_zonly renderMethod = info.Deserializer.Deserialize<ShaderZonly>(tagContext); break; case "rmcs": // shader_custom renderMethod = info.Deserializer.Deserialize<ShaderCustom>(tagContext); break; default: throw new NotImplementedException(); } } context.AddCommand(new ListArgumentsCommand(info, tag, renderMethod)); context.AddCommand(new ListBitmapsCommand(info, tag, renderMethod)); context.AddCommand(new SpecifyBitmapsCommand(info, tag, renderMethod)); }
public static CommandContext Create(CommandContext parent, OpenTagCache info, CacheBase blamCache) { var context = new CommandContext(parent, blamCache.Build); context.AddCommand(new PortShaderCommand(info, blamCache)); context.AddCommand(new PortModelCommand(info, blamCache)); context.AddCommand(new ListBitmapsCommand(info, blamCache)); return context; }
public static void Populate(CommandContext context, OpenTagCache info, TagInstance tag, VFilesList vfsl) { context.AddCommand(new ListCommand(vfsl)); context.AddCommand(new ExtractCommand(vfsl)); context.AddCommand(new ExtractAllCommand(vfsl)); context.AddCommand(new ImportCommand(info, tag, vfsl)); context.AddCommand(new ImportAllCommand(info, tag, vfsl)); }
public static void Populate(CommandContext context, OpenTagCache info, TagInstance tag, MultilingualUnicodeStringList unic) { if (info.StringIds == null) return; context.AddCommand(new ListCommand(info, unic)); context.AddCommand(new SetCommand(info, tag, unic)); }
public ExportTagsCommand(OpenTagCache info) : base(CommandFlags.None, "exporttags", "Exports all tags in the current tag cache to a specific directory.", "exporttags <output directory>", "Exports all tags in the current tag cache to a specific directory.") { Info = info; }
public ListUnreferencedTagsCommand(OpenTagCache info) : base(CommandFlags.None, "listunreferencedtags", "Lists all unreferenced tags in the current tag cache", "listunreferencedtags", "Lists all unreferenced tags in the current tag cache") { Info = info; }
public ListNullTagsCommand(OpenTagCache info) : base(CommandFlags.None, "listnulltags", "Lists all null tag indices in the current tag cache", "listnulltags", "Lists all null tag indices in the current tag cache") { Info = info; }
public GenerateTagNamesCommand(OpenTagCache info) : base(CommandFlags.Inherit, "gentagnames", "Generates tag names into a csv file (overwriting existing entries).", "gentagnames <csv file>", "Generates tag names into a csv file (overwriting existing entries).") { Info = info; }
public SetVarCommand(OpenTagCache info) : base(CommandFlags.Inherit, "setvar", "Assigns a value to a variable.", "setvar <name> <value>", "Assigns a value to a tag tool global variable, which can be accessed via $name") { Info = info; }
public GenerateCacheCommand(OpenTagCache info) : base(CommandFlags.Inherit, "generatecache", "Generates an empty set of cache files.", "generatecache <output directory>", "Generates an empty set of cache files.") { Info = info; }
public NullTagCommand(OpenTagCache info) : base(CommandFlags.None, "nulltag", "Nulls a tag in the current tag cache.", "nulltag <tag index>", "Nulls a tag in the current tag index. The tag's data will be removed from cache.") { Info = info; }
public static CommandContext Create(CommandContext parent, OpenTagCache info, TagInstance tag, VFilesList vfsl) { var groupName = info.StringIds.GetString(tag.GroupName); var context = new CommandContext(parent, string.Format("{0:X8}.{1}", tag.Index, groupName)); return context; }
public ImportCommand(OpenTagCache info) : base(CommandFlags.None, "import", "", "import [all] <index> <path>", "") { Info = info; }
public NewTagCommand(OpenTagCache info) : base(CommandFlags.Inherit, "newtag", "Creates a new tag of the specified tag group in the current tag cache.", "newtag <group tag>", "Creates a new tag of the specified tag group in the current tag cache.") { Info = info; }
public ExtractCommand(OpenTagCache info) : base(CommandFlags.Inherit, "extract", "", "extract [all] <index|group> <path>", "") { Info = info; }
public CopyForgePaletteCommand(OpenTagCache info, Scenario definition) : base(CommandFlags.Inherit, "copyforgepalette", "Copies the forge palette from the current scenario to another scenario", "copyforgepalette [palette = all] <destination scenario>", "Copies the forge palette from the current scenario to another scenario") { Info = info; Definition = definition; }
public ListBitmapsCommand(OpenTagCache info, CacheFile blamCache) : base(CommandFlags.None, "listbitmaps", "", "listbitmaps <blam tag path>", "") { Info = info; BlamCache = blamCache; }
public PortShaderCommand(OpenTagCache info, CacheFile blamCache) : base(CommandFlags.None, "portshader", "", "portshader <blam tag path>", "") { Info = info; BlamCache = blamCache; }
public static CommandContext Create(CommandContext parent, OpenTagCache info, HaloTag tag, MultilingualUnicodeStringList unic) { var context = new CommandContext(parent, string.Format("{0:X8}.unic", tag.Index)); if (info.StringIds != null) { context.AddCommand(new UnicListCommand(info, unic)); context.AddCommand(new UnicSetCommand(info, tag, unic)); } return context; }
public PortModelCommand(OpenTagCache info, CacheFile blamCache) : base(CommandFlags.Inherit, "portmodel", "", "portmodel [new] <blam tag path> <eldorado tag index>", "") { Info = info; BlamCache = blamCache; }
private static void EditBitmap(CommandContext context, OpenTagCache info, TagInstance tag) { Bitmap bitmap; using (var stream = info.OpenCacheRead()) bitmap = info.Deserializer.Deserialize<Bitmap>( new TagSerializationContext(stream, info.Cache, info.StringIds, tag)); BitmapContextFactory.Populate(context, info, tag, bitmap); }
private static void EditVFilesList(CommandContext context, OpenTagCache info, TagInstance tag) { VFilesList vfsl; using (var stream = info.OpenCacheRead()) vfsl = info.Deserializer.Deserialize<VFilesList>( new TagSerializationContext(stream, info.Cache, info.StringIds, tag)); VFilesContextFactory.Populate(context, info, tag, vfsl); }
public OpenCacheCommand(CommandContextStack stack, OpenTagCache info) : base(CommandFlags.Inherit, "opencache", "Opens a cache file format comparison and porting", "opencache <cache file>", "Opens a cache file format comparison and porting") { Stack = stack; Info = info; }
public PortBspCommand(OpenTagCache info, CacheFile blamCache) : base(CommandFlags.Inherit, "portbsp", "", "portbsp <blam tag path> <Halo Online tag index>", "") { Info = info; BlamCache = blamCache; }
public ListVariantsCommand(OpenTagCache info, Model model) : base(CommandFlags.Inherit, "listvariants", "List available variants of the current model definition.", "listvariants", "Lists available variants of the current model definition which can be used with \"extractmodel\".") { Info = info; Definition = model; }
public static CommandContext Create(CommandContext parent, OpenTagCache info, HaloTag tag, VFilesList vfsl) { var context = new CommandContext(parent, string.Format("{0:X8}.vfsl", tag.Index)); context.AddCommand(new VfslListCommand(vfsl)); context.AddCommand(new VfslExtractCommand(vfsl)); context.AddCommand(new VfslExtractAllCommand(vfsl)); context.AddCommand(new VfslImportCommand(info, tag, vfsl)); context.AddCommand(new VfslImportAllCommand(info, tag, vfsl)); return context; }
public MatchTagsCommand(OpenTagCache info) : base( CommandFlags.Inherit, "matchtags", "Find equivalent tags in different engine versions", "matchtags <output csv> <tags.dat...>", "The tags in the current tag cache will be compared with the tags in each of the\n" + "listed tags.dat files to find tags that are the same in all of them. Results\n" + "will be written to a CSV which can be used to convert tags between the\n" + "different versions.") { _info = info; }
public ImportResourceCommand(OpenTagCache info) : base( CommandFlags.Inherit, "importresource", "Import as a new resource for a specified tag.", "importresource <cache file> <tag> <input file>\n", "For bitm, it only works with permutations. The path must end with a folder, and not a file.\n") { _info = info; _cache = info.Cache; _fileInfo = info.CacheFile; _stringIds = info.StringIDs; }
public ConvertCommand(OpenTagCache info) : base( CommandFlags.None, "convert", "Convert a tag and its dependencies to another engine version", "convert <tag index> <tag map csv> <output csv> <target directory>", "The tag map CSV should be generated using the \"matchtags\" command.\n" + "If a tag is listed in the CSV file, it will not be converted.\n" + "The output CSV file is used for converting multiple maps.\n" + "Subsequent convert commands should use the new CSV.\n" + "The target directory should be the maps folder for the target engine.") { _info = info; }
public ModelTestCommand(OpenTagCache info) : base( CommandFlags.Inherit, "modeltest", "Model injection test", "modeltest [tag index] <model file>", "Injects the model over the traffic cone.\n" + "The model must only have a single material and no nodes.") { _info = info; _cache = info.Cache; _fileInfo = info.CacheFile; _stringIds = info.StringIds; }
public ConvertPluginsCommand(OpenTagCache info) : base( CommandFlags.Inherit, "convertplugins", "Convert Assembly plugins to tag layout structures", "convertplugins <input dir> <output type> <output dir>", "Only plugins for groups that are actually used in the tag cache will be converted.\n" + "Layouts will be written to the output directory in the chosen format.\n" + "\n" + "Supported output types: csharp, cpp") { _cache = info.Cache; _info = info; }
public SetCommand(OpenTagCache info, TagInstance tag, MultilingualUnicodeStringList unic) : base( CommandFlags.None, "set", "Set the value of a string", "set <language> <stringid> <value>", "Sets the string associated with a stringID in a language.\n" + "Remember to put the string value in quotes if it contains spaces.\n" + "If the string does not exist, it will be added.") { Info = info; Tag = tag; Definition = unic; }
public ImportCommand(OpenTagCache info, TagInstance tag, Bitmap bitmap) : base( CommandFlags.None, "import", "Import an image from a DDS file", "import <image index> <path>", "The image index must be in hexadecimal.\n" + "No conversion will be done on the data in the DDS file.\n" + "The pixel format must be supported by the game.") { _info = info; _tag = tag; _bitmap = bitmap; }
public GenerateLayoutsCommand(OpenTagCache info) : base( CommandFlags.Inherit, "genlayouts", "Generate tag layouts", "genlayouts <type> <output dir>", "Scans all tags in the file to guess tag layouts.\n" + "Layouts will be written to the output directory in the chosen format.\n" + "\n" + "Supported types: csharp, cpp") { _cache = info.Cache; _info = info; }
public ListCommand(OpenTagCache info, MultilingualUnicodeStringList definition) : base(CommandFlags.Inherit, "list", "List strings", "list <language> [filter]", "Lists the strings belonging to a language.\n" + "If a filter is specified, only strings containing the filter will be listed.\n" + "\n" + "Available languages:\n" + "\n" + "english, japanese, german, french, spanish, mexican, italian, korean,\n" + "chinese-trad, chinese-simp, portuguese, russian") { // TODO: Can we dynamically generate the language list from the dictionary in ArgumentParser? Info = info; Definition = definition; }
public StringIdCommand(OpenTagCache info) : base( CommandFlags.Inherit, "stringid", "Add, look up, or find stringID values", "stringid add <string>\n" + "stringid get <id>\n" + "stringid list [filter]", "\"stringid add\" will add a new stringID.\n" + "\"stringid get\" will display the string corresponding to an ID value.\n" + "\"stringid list\" will list stringIDs, optionally filtering them.") { _info = info; _stringIds = info.StringIds; }
public ExtractModelCommand(OpenTagCache info, Model model) : base( CommandFlags.Inherit, "extractmodel", "Extracts a render model from the current model definition.", "extractmodel <variant> <filetype> <filename>", "Extracts a variant of the render model to a file.\n" + "Use the \"listvariants\" command to list available variants.\n" + "If the model does not have any variants, just use \"default\"." + "\n" + "Supported file types: obj") { Info = info; Definition = model; }
public ListStringsCommand(OpenTagCache info) : base( CommandFlags.Inherit, "liststrings", "Scan unic tags to find a localized string", "liststrings <language> [filter]", "Scans all unic tags to find the strings belonging to a language.\n" + "If a filter is specified, only strings containing the filter will be listed.\n" + "\n" + "Available languages:\n" + "\n" + "english, japanese, german, french, spanish, mexican, italian, korean,\n" + "chinese-trad, chinese-simp, portuguese, russian") { _info = info; }
public EditCommand(CommandContextStack stack, OpenTagCache info) : base( CommandFlags.None, "edit", "Edit tag-specific data", "edit <tag index>", "If the tag contains data which is supported by this program,\n" + "this command will make special tag-specific commands available\n" + "which can be used to edit or view the data in the tag.\n" + "\n" + "Currently-supported tag types: bitm, hlmt, unic, vfsl") { _stack = stack; _cache = info.Cache; _info = info; }
public static object ConvertList(object list, Type type, OpenTagCache srcInfo, Stream srcStream, ResourceDataManager srcResources, OpenTagCache destInfo, Stream destStream, ResourceDataManager destResources, TagCacheMap tagMap) { if (type.GenericTypeArguments[0].IsPrimitive) { return(list); } var count = (int)type.GetProperty("Count").GetValue(list); var getItem = type.GetMethod("get_Item"); var setItem = type.GetMethod("set_Item"); for (var i = 0; i < count; i++) { var oldValue = getItem.Invoke(list, new object[] { i }); var newValue = Convert(oldValue, srcInfo, srcStream, srcResources, destInfo, destStream, destResources, tagMap); setItem.Invoke(list, new object[] { i, newValue }); } return(list); }
public static object Convert(object data, OpenTagCache srcInfo, Stream srcStream, ResourceDataManager srcResources, OpenTagCache destInfo, Stream destStream, ResourceDataManager destResources, TagCacheMap tagMap) { if (data == null) { return(null); } var type = data.GetType(); if (type.IsPrimitive) { return(data); } if (type == typeof(StringID)) { return(ConvertStringID((StringID)data, srcInfo, destInfo)); } if (type == typeof(TagInstance)) { return(ConvertTag((TagInstance)data, srcInfo, srcStream, srcResources, destInfo, destStream, destResources, tagMap)); } if (type == typeof(ResourceReference)) { return(ConvertResource((ResourceReference)data, srcInfo, srcResources, destInfo, destResources)); } if (type == typeof(GeometryReference)) { return(ConvertGeometry((GeometryReference)data, srcInfo, srcResources, destInfo, destResources)); } if (type.IsArray) { return(ConvertArray((Array)data, srcInfo, srcStream, srcResources, destInfo, destStream, destResources, tagMap)); } if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List <>)) { return(ConvertList(data, type, srcInfo, srcStream, srcResources, destInfo, destStream, destResources, tagMap)); } if (type.GetCustomAttributes(typeof(TagStructureAttribute), false).Length > 0) { return(ConvertStructure(data, type, srcInfo, srcStream, srcResources, destInfo, destStream, destResources, tagMap)); } return(data); }
private static List <QueuedTag> FindScenarios(OpenTagCache info, Stream stream) { // Get a dictionary of scenarios by map ID var scenarios = new Dictionary <int, QueuedTag>(); foreach (var scenarioTag in info.Cache.Tags.FindAllInGroup("scnr")) { var context = new TagSerializationContext(stream, info.Cache, info.StringIds, scenarioTag); var scenario = info.Deserializer.Deserialize <Scenario>(context); scenarios[scenario.MapId] = new QueuedTag { Tag = scenarioTag, Data = scenario }; } var tags = from id in MapIdsToCompare where scenarios.ContainsKey(id) select scenarios[id]; return(tags.ToList()); }
public static StringID ConvertStringID(StringID stringId, OpenTagCache srcInfo, OpenTagCache destInfo) { if (stringId == StringID.Null) { return(stringId); } var srcString = srcInfo.StringIDs.GetString(stringId); if (srcString == null) { return(StringID.Null); } var destStringID = destInfo.StringIDs.GetStringID(srcString); if (destStringID == StringID.Null) { destStringID = destInfo.StringIDs.Add(srcString); } return(destStringID); }
private StringId ConvertStringId(StringId stringId, OpenTagCache srcInfo, OpenTagCache destInfo) { if (stringId == StringId.Null) { return(stringId); } var srcString = srcInfo.StringIds.GetString(stringId); if (srcString == null) { return(StringId.Null); } var destStringId = destInfo.StringIds.GetStringId(srcString); if (destStringId == StringId.Null) { destStringId = destInfo.StringIds.Add(srcString); } return(destStringId); }
public DependencyCommand(OpenTagCache info) : base( CommandFlags.None, "dep", "Manage tag loading", "dep add <tag index> <dependency index...>\n" + "dep remove <tag index> <dependency index...>\n" + "dep list <tag index>\n" + "dep listall <tag index>\n" + "dep liston <tag index>", "\"dep add\" will cause the first tag to load the other tags.\n" + "\"dep remove\" will prevent the first tag from loading the other tags.\n" + "\"dep list\" will list all immediate dependencies of a tag.\n" + "\"dep listall\" will recursively list all dependencies of a tag.\n" + "\"dep liston\" will list all tags that depend on a tag.\n" + "\n" + "To add dependencies to a map, use the \"map\" command to get its scenario tag\n" + "index and then add dependencies to the scenario tag.") { Info = info; }
public static object ConvertStructure(object data, Type type, OpenTagCache srcInfo, Stream srcStream, ResourceDataManager srcResources, OpenTagCache destInfo, Stream destStream, ResourceDataManager destResources, TagCacheMap tagMap) { // Convert each field var enumerator = new TagFieldEnumerator(new TagStructureInfo(type, destInfo.Version)); while (enumerator.Next()) { var oldValue = enumerator.Field.GetValue(data); var newValue = Convert(oldValue, srcInfo, srcStream, srcResources, destInfo, destStream, destResources, tagMap); enumerator.Field.SetValue(data, newValue); } // Perform fixups FixObjectTypes(data, type, srcInfo); FixShaders(data, srcInfo); var scenario = data as Scenario; if (scenario != null) { FixScenario(scenario); } return(data); }
public override bool Execute(List <string> args) { if (args.Count != 2) { return(false); } var destDir = new DirectoryInfo(args[1]); if (!destDir.Exists) { WriteLine($"Destination cache directory does not exist: {destDir.FullName}"); return(false); } var destTagsFile = new FileInfo(Combine(destDir.FullName, "tags.dat")); if (!destTagsFile.Exists) { WriteLine($"Destination tag cache file does not exist: {destTagsFile.FullName}"); return(false); } var destStringIDsFile = new FileInfo(Combine(destDir.FullName, "string_ids.dat")); if (!destStringIDsFile.Exists) { WriteLine($"Destination string id cache file does not exist: {destStringIDsFile.FullName}"); return(false); } var destResourcesFile = new FileInfo(Combine(destDir.FullName, "resources.dat")); if (!destResourcesFile.Exists) { WriteLine($"Destination resource cache file does not exist: {destResourcesFile.FullName}"); return(false); } var destTexturesFile = new FileInfo(Combine(destDir.FullName, "textures.dat")); if (!destTexturesFile.Exists) { WriteLine($"Destination texture cache file does not exist: {destTexturesFile.FullName}"); return(false); } var destTexturesBFile = new FileInfo(Combine(destDir.FullName, "textures_b.dat")); if (!destTexturesBFile.Exists) { WriteLine($"Destination texture cache file does not exist: {destTexturesBFile.FullName}"); return(false); } var destAudioFile = new FileInfo(Combine(destDir.FullName, "audio.dat")); if (!destAudioFile.Exists) { WriteLine($"Destination audio cache file does not exist: {destAudioFile.FullName}"); return(false); } TagCache destTagCache; using (var stream = destTagsFile.OpenRead()) destTagCache = new TagCache(stream); DefinitionSet guessedVersion; var destVersion = Detect(destTagCache, out guessedVersion); if (destVersion == Unknown) { WriteLine($"Unrecognized target version! (guessed {GetVersionString(guessedVersion)})"); return(true); } WriteLine($"Destination cache version: {GetVersionString(destVersion)}"); StringIDCache destStringIDCache; using (var stream = destStringIDsFile.OpenRead()) destStringIDCache = new StringIDCache(stream, Create(destVersion)); var destResources = new ResourceDataManager(); destResources.LoadCachesFromDirectory(destDir.FullName); var srcResources = new ResourceDataManager(); srcResources.LoadCachesFromDirectory(Info.CacheFile.DirectoryName); var destSerializer = new TagSerializer(destVersion); var destDeserializer = new TagDeserializer(destVersion); var destInfo = new OpenTagCache { Cache = destTagCache, CacheFile = destTagsFile, StringIDs = destStringIDCache, StringIDsFile = destStringIDsFile, Version = destVersion, Serializer = destSerializer, Deserializer = destDeserializer }; var destTag = ParseTagIndex(destInfo, args[0]); if (destTag == null || !destTag.IsInGroup(new Tag("mode"))) { WriteLine("Destination tag must be of group 'mode'."); return(false); } RenderModel destDefinition; using (var destStream = destInfo.OpenCacheRead()) { var context = new TagSerializationContext(destStream, destInfo.Cache, destInfo.StringIDs, destTag); destDefinition = destInfo.Deserializer.Deserialize <RenderModel>(context); } using (MemoryStream inStream = new MemoryStream(), outStream = new MemoryStream()) { // First extract the model data srcResources.Extract(Definition.Geometry.Resource, inStream); // Now open source and destination vertex streams inStream.Position = 0; var inVertexStream = VertexStreamFactory.Create(Info.Version, inStream); var outVertexStream = VertexStreamFactory.Create(destInfo.Version, outStream); // Deserialize the definition data var resourceContext = new ResourceSerializationContext(Definition.Geometry.Resource); var definition = Info.Deserializer.Deserialize <RenderGeometryResourceDefinition>(resourceContext); // Convert each vertex buffer foreach (var buffer in definition.VertexBuffers) { TagConverter.ConvertVertexBuffer(buffer.Definition, inStream, inVertexStream, outStream, outVertexStream); } // Copy each index buffer over foreach (var buffer in definition.IndexBuffers) { if (buffer.Definition.Data.Size == 0) { continue; } inStream.Position = buffer.Definition.Data.Address.Offset; buffer.Definition.Data.Address = new ResourceAddress(ResourceAddressType.Resource, (int)outStream.Position); var bufferData = new byte[buffer.Definition.Data.Size]; inStream.Read(bufferData, 0, bufferData.Length); outStream.Write(bufferData, 0, bufferData.Length); StreamUtil.Align(outStream, 4); } destInfo.Serializer.Serialize(resourceContext, definition); outStream.Position = 0; destResources.Replace(destDefinition.Geometry.Resource, outStream); } return(true); }
public static CommandContext Create(CommandContextStack stack, OpenTagCache info, TagInstance tag) { var groupName = info.StringIDs.GetString(tag.Group.Name); var tagName = $"0x{tag.Index:X4}"; if (info.TagNames.ContainsKey(tag.Index)) { tagName = info.TagNames[tag.Index]; tagName = $"(0x{tag.Index:X4}) {tagName.Substring(tagName.LastIndexOf('\\') + 1)}"; } var context = new CommandContext(stack.Context, string.Format("{0}.{1}", tagName, groupName)); switch (tag.Group.Tag.ToString()) { case "vfsl": // vfiles_list EditVFilesList(context, info, tag); break; case "unic": // multilingual_unicode_string_list EditMultilingualUnicodeStringList(context, info, tag); break; case "bitm": // bitmap EditBitmap(context, info, tag); break; case "hlmt": // model EditModel(context, info, tag); break; case "mode": // render_model EditRenderModel(context, info, tag); break; case "jmad": EditAnimation(context, info, tag); break; case "rm ": // render_method case "rmsh": // shader case "rmd ": // shader_decal case "rmfl": // shader_foliage case "rmhg": // shader_halogram case "rmss": // shader_screen case "rmtr": // shader_terrain case "rmw ": // shader_water case "rmzo": // shader_zonly case "rmcs": // shader_custom EditRenderMethod(context, info, tag); break; case "scnr": EditScenario(context, info, tag); break; } object value = null; using (var stream = info.OpenCacheRead()) value = info.Deserializer.Deserialize( new TagSerializationContext(stream, info.Cache, info.StringIDs, tag), TagStructureTypes.FindByGroupTag(tag.Group.Tag)); var structure = new TagStructureInfo( TagStructureTypes.FindByGroupTag(tag.Group.Tag)); context.AddCommand(new ListFieldsCommand(info, structure, value)); context.AddCommand(new SetFieldCommand(stack, info, tag, structure, value)); context.AddCommand(new EditBlockCommand(stack, info, tag, value)); context.AddCommand(new AddToCommand(stack, info, tag, structure, value)); context.AddCommand(new RemoveFromCommand(stack, info, tag, structure, value)); context.AddCommand(new CopyElementsCommand(stack, info, tag, structure, value)); context.AddCommand(new PasteElementsCommand(stack, info, tag, structure, value)); context.AddCommand(new SaveChangesCommand(info, tag, value)); context.AddCommand(new ExitToCommand(stack)); return(context); }
public override bool Execute(List <string> args) { if (args.Count != 1) { return(false); } var destDir = new DirectoryInfo(args[0]); if (!destDir.Exists) { Write("Destination directory does not exist. Create it? [y/n] "); var answer = ReadLine().ToLower(); if (answer.Length == 0 || !(answer.StartsWith("y") || answer.StartsWith("n"))) { return(false); } if (answer.StartsWith("y")) { destDir.Create(); } else { return(false); } } WriteLine($"Generating cache files in \"{destDir.FullName}\"..."); var destTagsFile = new FileInfo(Combine(destDir.FullName, "tags.dat")); Write($"Generating {destTagsFile.FullName}..."); using (var tagCacheStream = destTagsFile.Create()) using (var writer = new BinaryWriter(tagCacheStream)) { writer.Write((int)0); // padding writer.Write((int)0); // tag list offset writer.Write((int)0); // tag count writer.Write((int)0); // padding writer.Write((long)130713360239499012); // timestamp writer.Write((long)0); // padding } WriteLine("done."); var destStringIDsFile = new FileInfo(Combine(destDir.FullName, "string_ids.dat")); Write($"Generating {destStringIDsFile.FullName}..."); using (var stringIDCacheStream = destStringIDsFile.Create()) using (var writer = new BinaryWriter(stringIDCacheStream)) { writer.Write((int)0); // string count writer.Write((int)0); // data size } WriteLine("done."); var resourceCachePaths = new string[] { Combine(destDir.FullName, "audio.dat"), Combine(destDir.FullName, "resources.dat"), Combine(destDir.FullName, "textures.dat"), Combine(destDir.FullName, "textures_b.dat"), Combine(destDir.FullName, "video.dat") }; foreach (var resourceCachePath in resourceCachePaths) { Write($"Generating {resourceCachePath}..."); using (var resourceCacheStream = File.Create(resourceCachePath)) using (var writer = new BinaryWriter(resourceCacheStream)) { writer.Write((int)0); // padding writer.Write((int)0); // table offset writer.Write((int)0); // resource count writer.Write((int)0); // padding } WriteLine("done."); } var dependencies = new Dictionary <int, TagInstance>(); LoadTagDependencies(0, ref dependencies); LoadTagDependencies(0x16, ref dependencies); LoadTagDependencies(0x27D7, ref dependencies); var destResourcesFile = new FileInfo(Combine(destDir.FullName, "resources.dat")); if (!destResourcesFile.Exists) { WriteLine($"Destination resource cache file does not exist: {destResourcesFile.FullName}"); return(false); } var destTexturesFile = new FileInfo(Combine(destDir.FullName, "textures.dat")); if (!destTexturesFile.Exists) { WriteLine($"Destination texture cache file does not exist: {destTexturesFile.FullName}"); return(false); } var destTexturesBFile = new FileInfo(Combine(destDir.FullName, "textures_b.dat")); if (!destTexturesBFile.Exists) { WriteLine($"Destination texture cache file does not exist: {destTexturesBFile.FullName}"); return(false); } var destAudioFile = new FileInfo(Combine(destDir.FullName, "audio.dat")); if (!destAudioFile.Exists) { WriteLine($"Destination audio cache file does not exist: {destAudioFile.FullName}"); return(false); } TagCache destTagCache; using (var stream = destTagsFile.OpenRead()) destTagCache = new TagCache(stream); DefinitionSet guessedVersion; var destVersion = Detect(destTagCache, out guessedVersion); if (destVersion == Unknown) { WriteLine($"Unrecognized target version! (guessed {GetVersionString(guessedVersion)})"); return(true); } WriteLine($"Destination cache version: {GetVersionString(destVersion)}"); StringIDCache destStringIDCache; using (var stream = destStringIDsFile.OpenRead()) destStringIDCache = new StringIDCache(stream, Create(destVersion)); var destResources = new ResourceDataManager(); destResources.LoadCachesFromDirectory(destDir.FullName); var srcResources = new ResourceDataManager(); srcResources.LoadCachesFromDirectory(Info.CacheFile.DirectoryName); var destSerializer = new TagSerializer(destVersion); var destDeserializer = new TagDeserializer(destVersion); var destInfo = new OpenTagCache { Cache = destTagCache, CacheFile = destTagsFile, StringIDs = destStringIDCache, StringIDsFile = destStringIDsFile, Version = destVersion, Serializer = destSerializer, Deserializer = destDeserializer }; using (Stream srcStream = Info.OpenCacheRead(), destStream = destInfo.OpenCacheReadWrite()) { var maxDependency = dependencies.Keys.Max(); for (var i = 0; i <= maxDependency; i++) { var srcTag = Info.Cache.Tags[i]; if (srcTag == null) { destInfo.Cache.AllocateTag(); continue; } var srcData = Info.Cache.ExtractTagRaw(srcStream, srcTag); var destTag = destInfo.Cache.AllocateTag(srcTag.Group); destInfo.Cache.SetTagDataRaw(destStream, destTag, srcData); srcData = new byte[0]; } } WriteLine($"Done generating cache files in \"{destDir.FullName}\"."); return(true); }
private static void EditRenderMethod(CommandContext context, OpenTagCache info, TagInstance tag) { RenderMethodContextFactory.Populate(context, info, tag); }
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); }
public static Array ConvertArray(Array array, OpenTagCache srcInfo, Stream srcStream, ResourceDataManager srcResources, OpenTagCache destInfo, Stream destStream, ResourceDataManager destResources, TagCacheMap tagMap) { if (array.GetType().GetElementType().IsPrimitive) { return(array); } for (var i = 0; i < array.Length; i++) { var oldValue = array.GetValue(i); var newValue = Convert(oldValue, srcInfo, srcStream, srcResources, destInfo, destStream, destResources, tagMap); array.SetValue(newValue, i); } return(array); }
private static void EditMultilingualUnicodeStringList(CommandContext context, OpenTagCache info, TagInstance tag) { MultilingualUnicodeStringList unic; using (var stream = info.OpenCacheRead()) unic = info.Deserializer.Deserialize <MultilingualUnicodeStringList>( new TagSerializationContext(stream, info.Cache, info.StringIDs, tag)); UnicodeContextFactory.Populate(context, info, tag, unic); }
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); }
public static GeometryReference ConvertGeometry(GeometryReference geometry, OpenTagCache srcInfo, ResourceDataManager srcResources, OpenTagCache destInfo, ResourceDataManager destResources) { if (geometry == null || geometry.Resource == null || geometry.Resource.Index < 0) { return(geometry); } // The format changed starting with version 1.235640, so if both versions are on the same side then they can be converted normally var srcCompare = Definition.Compare(srcInfo.Version, DefinitionSet.HaloOnline235640); var destCompare = Definition.Compare(destInfo.Version, DefinitionSet.HaloOnline235640); if ((srcCompare < 0 && destCompare < 0) || (srcCompare >= 0 && destCompare >= 0)) { geometry.Resource = ConvertResource(geometry.Resource, srcInfo, srcResources, destInfo, destResources); return(geometry); } Console.WriteLine("- Rebuilding geometry resource {0} in {1}...", geometry.Resource.Index, geometry.Resource.GetLocation()); using (MemoryStream inStream = new MemoryStream(), outStream = new MemoryStream()) { // First extract the model data srcResources.Extract(geometry.Resource, inStream); // Now open source and destination vertex streams inStream.Position = 0; var inVertexStream = VertexStreamFactory.Create(srcInfo.Version, inStream); var outVertexStream = VertexStreamFactory.Create(destInfo.Version, outStream); // Deserialize the definition data var resourceContext = new ResourceSerializationContext(geometry.Resource); var definition = srcInfo.Deserializer.Deserialize <RenderGeometryResourceDefinition>(resourceContext); // Convert each vertex buffer foreach (var buffer in definition.VertexBuffers) { ConvertVertexBuffer(buffer.Definition, inStream, inVertexStream, outStream, outVertexStream); } // Copy each index buffer over foreach (var buffer in definition.IndexBuffers) { if (buffer.Definition.Data.Size == 0) { continue; } inStream.Position = buffer.Definition.Data.Address.Offset; buffer.Definition.Data.Address = new ResourceAddress(ResourceAddressType.Resource, (int)outStream.Position); var bufferData = new byte[buffer.Definition.Data.Size]; inStream.Read(bufferData, 0, bufferData.Length); outStream.Write(bufferData, 0, bufferData.Length); StreamUtil.Align(outStream, 4); } // Update the definition data destInfo.Serializer.Serialize(resourceContext, definition); // Now inject the new resource data var newLocation = FixResourceLocation(geometry.Resource.GetLocation(), srcInfo.Version, destInfo.Version); outStream.Position = 0; destResources.Add(geometry.Resource, newLocation, outStream); } return(geometry); }
public static ResourceReference ConvertResource(ResourceReference resource, OpenTagCache srcInfo, ResourceDataManager srcResources, OpenTagCache destInfo, ResourceDataManager destResources) { if (resource == null) { return(null); } Console.WriteLine("- Copying resource {0} in {1}...", resource.Index, resource.GetLocation()); var data = srcResources.ExtractRaw(resource); var newLocation = FixResourceLocation(resource.GetLocation(), srcInfo.Version, destInfo.Version); destResources.AddRaw(resource, newLocation, data); return(resource); }