static void Main(string[] args) { Options options = null; try { options = CommandLine.Parse<Options>(); } catch (CommandLineException exception) { Console.WriteLine(exception.ArgumentHelp.Message); Console.WriteLine(); Console.WriteLine(exception.ArgumentHelp.GetHelpText(Console.BufferWidth)); #if DEBUG Console.ReadLine(); #endif return; } IPackfile packfile = null; Stream2File asm = null; Console.WriteLine("Building {0} using data from {1}.", options.Output, options.Source); IGameInstance instance = GameInstance.GetFromString(options.Game); switch (instance.Game) { case GameSteamID.SaintsRow2: packfile = new Packfiles.Version04.Packfile(); break; case GameSteamID.SaintsRowTheThird: throw new NotImplementedException(); break; case GameSteamID.SaintsRowIV: case GameSteamID.SaintsRowGatOutOfHell: packfile = new Packfiles.Version0A.Packfile(Path.GetExtension(options.Output) == ".str2_pc"); if (Path.GetExtension(options.Output) == ".str2_pc") { packfile.IsCondensed = true; packfile.IsCompressed = true; if (options.AsmFile != null) { Console.WriteLine("Will update asm_pc file {0} with data for new package.", options.AsmFile); using (Stream asmStream = File.OpenRead(options.AsmFile)) { asm = new Stream2File(asmStream); } } } break; default: throw new NotImplementedException(); } if (options.Condensed.ToLowerInvariant() == "true") packfile.IsCondensed = true; else if (options.Condensed.ToLowerInvariant() == "false") packfile.IsCondensed = false; if (options.Compressed.ToLowerInvariant() == "true") packfile.IsCompressed = true; else if (options.Compressed.ToLowerInvariant() == "false") packfile.IsCompressed = false; Container thisContainer = null; if (asm != null) { string containerName = Path.GetFileNameWithoutExtension(options.Output); foreach (var container in asm.Containers) { string tempContainerName = Path.GetFileNameWithoutExtension(container.Name); if (tempContainerName == containerName) { thisContainer = container; break; } } if (thisContainer == null) throw new Exception(String.Format("Unable to find container {0} in asm_pc file {1}.", containerName, options.AsmFile)); foreach (Primitive primitive in thisContainer.Primitives) { string primitiveFile = Path.Combine(options.Source, primitive.Name); if (!File.Exists(primitiveFile)) { Console.WriteLine("Unable to find primitive {0} for container {1}", containerName, primitive.Name); continue; } string filename = Path.GetFileName(primitiveFile); Console.Write("Adding {0}... ", filename); Stream stream = File.OpenRead(primitiveFile); packfile.AddFile(stream, filename); Console.WriteLine("done."); string extension = Path.GetExtension(primitiveFile); string gpuExtension = ""; switch (extension) { default: { if (extension.StartsWith(".c")) gpuExtension = ".g" + extension.Remove(0, 2); break; } } string gpuFile = Path.ChangeExtension(primitiveFile, gpuExtension); if (File.Exists(gpuFile)) { string gpuFilename = Path.GetFileName(gpuFile); Console.Write("Adding {0}... ", gpuFilename); Stream gpuStream = File.OpenRead(gpuFile); packfile.AddFile(gpuStream, gpuFilename); Console.WriteLine("done."); } } } else { string[] files = Directory.GetFiles(options.Source); foreach (string file in files) { string filename = Path.GetFileName(file); Console.Write("Adding {0}... ", filename); Stream stream = File.OpenRead(file); packfile.AddFile(stream, filename); Console.WriteLine("done."); } } using (Stream output = File.Open(options.Output, FileMode.Create, FileAccess.ReadWrite, FileShare.None)) { Console.Write("Writing packfile to {0}... ", options.Output); packfile.Save(output); Console.WriteLine("done."); } if (asm != null) { Console.Write("Updating asm_pc file {0}... ", options.AsmFile); packfile.Update(thisContainer); using (Stream asmStream = File.Create(options.AsmFile)) { asm.Save(asmStream); } Console.WriteLine("done."); } #if DEBUG Console.ReadLine(); #endif }
static void Main(string[] args) { Options options = null; try { options = CommandLine.Parse<Options>(); } catch (CommandLineException exception) { Console.WriteLine(exception.ArgumentHelp.Message); Console.WriteLine(); Console.WriteLine(exception.ArgumentHelp.GetHelpText(Console.BufferWidth)); Console.ReadLine(); return; } if (options.Source == null) { string sriv = ThomasJepp.SaintsRow.Utility.GetGamePath(GameSteamID.SaintsRowIV); string srgooh = ThomasJepp.SaintsRow.Utility.GetGamePath(GameSteamID.SaintsRowGatOutOfHell); int gameCount = 0, srivNum = 0, srgoohNum = 0; Console.WriteLine("Detected the following games:"); if (sriv != null) { gameCount++; srivNum = gameCount; Console.WriteLine("{0}. Saints Row IV: {1}", gameCount, sriv); } if (srgooh != null) { gameCount++; srgoohNum = gameCount; Console.WriteLine("{0}. Saints Row Gat Out Of Hell: {1}", gameCount, srgooh); } Console.WriteLine(); while (true) { Console.Write("Which game do you want to update? (enter the number) "); ConsoleKeyInfo input = Console.ReadKey(); Console.WriteLine(); Console.WriteLine(); if (input.Key == ConsoleKey.D1 || input.Key == ConsoleKey.NumPad1) { if (srivNum == 1) { options.Source = sriv; Console.WriteLine("Updating Saints Row IV files."); } else if (srgoohNum == 1) { options.Source = srgooh; Console.WriteLine("Updating Saints Row: Gat Out Of Hell files."); } } else if (input.Key == ConsoleKey.D2 || input.Key == ConsoleKey.NumPad2) { if (srivNum == 2) { options.Source = sriv; Console.WriteLine("Updating Saints Row IV files."); } else if (srgoohNum == 2) { options.Source = srgooh; Console.WriteLine("Updating Saints Row: Gat Out Of Hell files."); } } if (options.Source != null) break; } } if (options.Source == null) { Console.WriteLine("Couldn't find the Saints Row IV folder?"); Console.WriteLine(); Console.WriteLine("Press enter to exit."); Console.ReadLine(); return; } string str2Dir = options.Source; //if (Directory.Exists(Path.Combine(options.Source, "mods"))) //str2Dir = Path.Combine(options.Source, "mods"); string[] str2Paths = Directory.GetFiles(str2Dir, "*.str2_pc"); List<string> str2Files = new List<string>(); foreach (string str2Path in str2Paths) { str2Files.Add(Path.GetFileName(str2Path)); } if (str2Files.Count == 0) { Console.WriteLine("No str2_pc files found - no update needed."); Console.WriteLine(); Console.WriteLine("Press enter to exit."); Console.ReadLine(); return; } string packfileCache = Path.Combine(options.Source, "packfiles", "pc", "cache"); Dictionary<string, Stream2File> asmsToSave = new Dictionary<string, Stream2File>(); string[] packfiles = Directory.GetFiles(packfileCache, "*.vpp_pc"); int vppCount = 0; foreach (string packfilePath in packfiles) { vppCount ++; Console.WriteLine("[{0}/{1}] Checking {2}...", vppCount, packfiles.Length, Path.GetFileName(packfilePath)); using (Stream stream = File.OpenRead(packfilePath)) { using (IPackfile packfile = Packfile.FromStream(stream, false)) { foreach (var packedFile in packfile.Files) { if (Path.GetExtension(packedFile.Name) != ".asm_pc") continue; using (Stream asmStream = packedFile.GetStream()) { Stream2File asm = new Stream2File(asmStream); foreach (var container in asm.Containers) { string containerName = Path.ChangeExtension(container.Name, ".str2_pc"); if (str2Files.Contains(containerName)) { if (!asmsToSave.ContainsKey(packedFile.Name)) { asmsToSave.Add(packedFile.Name, asm); } Console.Write(" - Updating {0} - {1}...", packedFile.Name, containerName); using (Stream str2Stream = File.OpenRead(Path.Combine(str2Dir, containerName))) { using (IPackfile str2 = Packfile.FromStream(str2Stream, true)) { str2.Update(container); } } Console.WriteLine(" done."); } } } } } } } Console.WriteLine(); Console.WriteLine("Writing updated asm_pc files..."); int count = 0; foreach (var asmPair in asmsToSave) { count++; Console.Write("[{0}/{1}] Saving {2}...", count, asmsToSave.Count, asmPair.Key); string outPath = Path.Combine(str2Dir, asmPair.Key); using (Stream outStream = File.Create(outPath)) { asmPair.Value.Save(outStream); } Console.WriteLine(" done."); } Console.WriteLine("Done."); Console.WriteLine(); Console.WriteLine("Press enter to exit."); Console.ReadLine(); }
private void DoBuild(object o) { DisableButton(); BuildOptions options = (BuildOptions)o; SetProgressBarSettings(0, 100, 1, ProgressBarStyle.Marquee); IPackfile packfile = null; switch (options.Game) { case GameSteamID.SaintsRow2: { packfile = new Packfiles.Version04.Packfile(); break; } case GameSteamID.SaintsRowIV: case GameSteamID.SaintsRowGatOutOfHell: { packfile = new Packfiles.Version0A.Packfile(Path.GetExtension(options.Destination) == ".str2_pc"); break; } default: { throw new NotImplementedException(); } } Stream2File asm = null; Stream2.Container thisContainer = null; SetText("Setting up..."); if (Path.GetExtension(options.Destination) == ".str2_pc") { packfile.IsCondensed = true; packfile.IsCompressed = true; if (options.Asm != null) { using (Stream asmStream = File.OpenRead(options.Asm)) { asm = new Stream2File(asmStream); } } } else { string filename = Path.GetFileName(options.Destination); if (OriginalPackfileInfo.OptionsList.ContainsKey(options.Game) && OriginalPackfileInfo.OptionsList[options.Game].ContainsKey(filename)) { var vppOptions = OriginalPackfileInfo.OptionsList[options.Game][filename]; packfile.IsCondensed = vppOptions.Condense; packfile.IsCompressed = vppOptions.Compress; } } if (asm != null) { string containerName = Path.GetFileNameWithoutExtension(options.Destination); foreach (var container in asm.Containers) { string tempContainerName = Path.GetFileNameWithoutExtension(container.Name); if (tempContainerName == containerName) { thisContainer = container; break; } } if (thisContainer == null) { SetText("Couldn't find a container called {0} in the selected asm_pc file!", containerName); SetProgressBarSettings(0, 100, 0, ProgressBarStyle.Continuous); EnableButton(); return; } SetProgressBarSettings(0, thisContainer.PrimitiveCount, 0, ProgressBarStyle.Continuous); SetText("Adding files..."); foreach (Primitive primitive in thisContainer.Primitives) { string primitiveFile = Path.Combine(options.Source, primitive.Name); if (!File.Exists(primitiveFile)) { SetText("Couldn't find a container called {0} in the selected asm_pc file!", containerName); SetProgressBarSettings(0, 100, 0, ProgressBarStyle.Continuous); EnableButton(); return; } string filename = Path.GetFileName(primitiveFile); Stream stream = File.OpenRead(primitiveFile); packfile.AddFile(stream, filename); string extension = Path.GetExtension(primitiveFile); string gpuExtension = ""; switch (extension) { default: { if (extension.StartsWith(".c")) gpuExtension = ".g" + extension.Remove(0, 2); break; } } string gpuFile = Path.ChangeExtension(primitiveFile, gpuExtension); if (File.Exists(gpuFile)) { string gpuFilename = Path.GetFileName(gpuFile); Stream gpuStream = File.OpenRead(gpuFile); packfile.AddFile(gpuStream, gpuFilename); } Step(); } } else { string[] files = Directory.GetFiles(options.Source); SetProgressBarSettings(0, files.Length, 0, ProgressBarStyle.Continuous); SetText("Adding files..."); foreach (string file in files) { string filename = Path.GetFileName(file); Stream stream = File.OpenRead(file); packfile.AddFile(stream, filename); } } SetProgressBarSettings(0, 100, 0, ProgressBarStyle.Marquee); SetText("Writing output file: {0}", options.Destination); using (Stream output = File.Open(options.Destination, FileMode.Create, FileAccess.ReadWrite, FileShare.None)) { packfile.Save(output); } if (asm != null) { SetText("Updating asm_pc file: {0}", options.Asm); packfile.Update(thisContainer); using (Stream asmStream = File.Create(options.Asm)) { asm.Save(asmStream); } Console.WriteLine("done."); } SetProgressBarSettings(0, 1, 1, ProgressBarStyle.Continuous); Step(); SetText("Finished!"); EnableButton(); }
static void Main(string[] args) { Options options = null; try { options = CommandLine.Parse<Options>(); } catch (CommandLineException exception) { Console.WriteLine(exception.ArgumentHelp.Message); Console.WriteLine(); Console.WriteLine(exception.ArgumentHelp.GetHelpText(Console.BufferWidth)); #if DEBUG Console.ReadLine(); #endif return; } switch (options.Action) { case "toxml": { using (Stream stream = File.OpenRead(options.Source)) { Stream2File file = new Stream2File(stream); if (options.Output == null || options.Output == "") { options.Output = Path.ChangeExtension(options.Source, "xml"); } XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.IndentChars = "\t"; settings.NewLineChars = "\r\n"; using (XmlWriter xml = XmlWriter.Create(options.Output, settings)) { xml.WriteStartDocument(); xml.WriteStartElement("AssetAssembler"); xml.WriteStartElement("AllocatorTypes"); foreach (var pair in file.AllocatorTypes) { xml.WriteStartElement("AllocatorType"); xml.WriteAttributeString("ID", pair.Key.ToString()); xml.WriteAttributeString("Name", pair.Value); xml.WriteEndElement(); } xml.WriteEndElement(); // AllocatorTypes xml.WriteStartElement("ContainerTypes"); foreach (var pair in file.ContainerTypes) { xml.WriteStartElement("ContainerType"); xml.WriteAttributeString("ID", pair.Key.ToString()); xml.WriteAttributeString("Name", pair.Value); xml.WriteEndElement(); } xml.WriteEndElement(); // ContainerTypes xml.WriteStartElement("PrimitiveTypes"); foreach (var pair in file.PrimitiveTypes) { xml.WriteStartElement("PrimitiveType"); xml.WriteAttributeString("ID", pair.Key.ToString()); xml.WriteAttributeString("Name", pair.Value); xml.WriteEndElement(); } xml.WriteEndElement(); // PrimitiveTypes xml.WriteStartElement("Containers"); foreach (var container in file.Containers) { xml.WriteStartElement("Container"); xml.WriteAttributeString("Name", container.Name); xml.WriteAttributeString("Type", file.ContainerTypes[container.ContainerType]); xml.WriteAttributeString("Flags", container.Flags.ToString()); xml.WriteAttributeString("PackfileBaseOffset", container.PackfileBaseOffset.ToString()); xml.WriteAttributeString("CompressionType", container.CompressionType.ToString()); xml.WriteAttributeString("StubContainerParentName", container.StubContainerParentName); xml.WriteAttributeString("TotalCompressedPackfileReadSize", container.TotalCompressedPackfileReadSize.ToString()); if (container.AuxData.Length > 0) { xml.WriteStartElement("AuxData"); xml.WriteString(Convert.ToBase64String(container.AuxData, Base64FormattingOptions.None)); xml.WriteEndElement(); // AuxData } for (int i = 0; i < container.PrimitiveCount; i++) { var primitive = container.Primitives[i]; var sizes = container.PrimitiveSizes[i]; xml.WriteStartElement("Primitive"); xml.WriteAttributeString("Name", primitive.Name); xml.WriteAttributeString("Type", file.PrimitiveTypes[primitive.Data.Type]); xml.WriteAttributeString("Allocator", file.AllocatorTypes.ContainsKey(primitive.Data.Allocator) ? file.AllocatorTypes[primitive.Data.Allocator] : primitive.Data.Allocator.ToString()); xml.WriteAttributeString("Flags", primitive.Data.Flags.ToString()); xml.WriteAttributeString("ExtensionIndex", primitive.Data.ExtensionIndex.ToString()); xml.WriteAttributeString("CPUSize", primitive.Data.CPUSize.ToString()); xml.WriteAttributeString("GPUSize", primitive.Data.GPUSize.ToString()); xml.WriteAttributeString("AllocationGroup", primitive.Data.AllocationGroup.ToString()); xml.WriteAttributeString("WriteTimeCPUSize", sizes.CPUSize.ToString()); xml.WriteAttributeString("WriteTimeGPUSize", sizes.GPUSize.ToString()); xml.WriteEndElement(); // Primitive } xml.WriteEndElement(); // Container } xml.WriteEndElement(); // Containers xml.WriteEndElement(); // AssetAssembler xml.WriteEndDocument(); } } break; } case "toasm": { using (Stream stream = File.OpenRead(options.Source)) { XDocument xml = XDocument.Load(stream); Stream2File file = new Stream2File(); if (options.Output == null || options.Output == "") { options.Output = Path.ChangeExtension(options.Source, "asm_pc"); } Dictionary<string, byte> allocatorTypesLookup = new Dictionary<string, byte>(); Dictionary<string, byte> containerTypesLookup = new Dictionary<string, byte>(); Dictionary<string, byte> primitiveTypesLookup = new Dictionary<string, byte>(); foreach (var node in xml.Descendants("AllocatorType")) { byte id = byte.Parse(node.Attribute("ID").Value); string name = node.Attribute("Name").Value; allocatorTypesLookup.Add(name, id); file.AllocatorTypes.Add(id, name); } foreach (var node in xml.Descendants("ContainerType")) { byte id = byte.Parse(node.Attribute("ID").Value); string name = node.Attribute("Name").Value; containerTypesLookup.Add(name, id); file.ContainerTypes.Add(id, name); } foreach (var node in xml.Descendants("PrimitiveType")) { byte id = byte.Parse(node.Attribute("ID").Value); string name = node.Attribute("Name").Value; primitiveTypesLookup.Add(name, id); file.PrimitiveTypes.Add(id, name); } foreach (var cNode in xml.Descendants("Container")) { Container container = new Container(); container.Name = cNode.Attribute("Name").Value; container.ContainerType = containerTypesLookup[cNode.Attribute("Type").Value]; container.Flags = (ContainerFlags)ushort.Parse(cNode.Attribute("Flags").Value); container.PackfileBaseOffset = uint.Parse(cNode.Attribute("PackfileBaseOffset").Value); container.CompressionType = byte.Parse(cNode.Attribute("CompressionType").Value); container.StubContainerParentName = cNode.Attribute("StubContainerParentName").Value; container.TotalCompressedPackfileReadSize = int.Parse(cNode.Attribute("TotalCompressedPackfileReadSize").Value); var auxData = cNode.Element("AuxData"); if (auxData != null) { container.AuxData = Convert.FromBase64String(auxData.Value); } else { container.AuxData = new byte[0]; } foreach (var pNode in cNode.Descendants("Primitive")) { Primitive p = new Primitive(); p.Name = pNode.Attribute("Name").Value; p.Data = new PrimitiveData(); p.Data.Type = primitiveTypesLookup[pNode.Attribute("Type").Value]; byte allocatorType = 0; if (byte.TryParse(pNode.Attribute("Allocator").Value, out allocatorType)) { p.Data.Allocator = allocatorType; } else { p.Data.Allocator = allocatorTypesLookup[pNode.Attribute("Allocator").Value]; } p.Data.Flags = byte.Parse(pNode.Attribute("Flags").Value); p.Data.ExtensionIndex = byte.Parse(pNode.Attribute("ExtensionIndex").Value); p.Data.CPUSize = uint.Parse(pNode.Attribute("CPUSize").Value); p.Data.GPUSize = uint.Parse(pNode.Attribute("GPUSize").Value); p.Data.AllocationGroup = byte.Parse(pNode.Attribute("AllocationGroup").Value); container.Primitives.Add(p); WriteTimeSizes size = new WriteTimeSizes(); size.CPUSize = uint.Parse(pNode.Attribute("WriteTimeCPUSize").Value); size.GPUSize = uint.Parse(pNode.Attribute("WriteTimeGPUSize").Value); container.PrimitiveSizes.Add(size); } container.PrimitiveCount = (ushort)container.Primitives.Count; file.Containers.Add(container); } file.Header.Signature = (uint)0xBEEFFEED; file.Header.Version = (ushort)0x000C; file.Header.NumContainers = (short)file.Containers.Count; using (Stream outputStream = File.Create(options.Output)) { file.Save(outputStream); } } break; } case "update": { Stream2File file = null; using (Stream stream = File.OpenRead(options.Source)) { file = new Stream2File(stream); string folder = Path.GetDirectoryName(options.Source); foreach (var container in file.Containers) { string str2File = Path.ChangeExtension(container.Name, ".str2_pc"); string filename = Path.Combine(folder, str2File); if (File.Exists(filename)) { Console.Write("Found {0}, updating... ", str2File); using (Stream str2Stream = File.OpenRead(filename)) { IPackfile packfile = Packfile.FromStream(str2Stream, true); packfile.Update(container); } Console.WriteLine("done."); } else { Console.WriteLine("Could not find {0}.", str2File); } } } using (Stream stream = File.Create(options.Source)) { file.Save(stream); } break; } case "clean": { Stream2File file = null; using (Stream stream = File.OpenRead(options.Source)) { file = new Stream2File(stream); string folder = Path.GetDirectoryName(options.Source); List<string> foundContainerNames = new List<string>(); List<Container> duplicates = new List<Container>(); foreach (var container in file.Containers) { if (!foundContainerNames.Contains(container.Name)) { foundContainerNames.Add(container.Name); } else { duplicates.Add(container); } } foreach (var container in duplicates) { file.Containers.Remove(container); } file.Header.NumContainers = (short)file.Containers.Count; } using (Stream stream = File.Create(options.Source)) { file.Save(stream); } break; } default: { Console.WriteLine("Unrecogised action!"); break; } } #if DEBUG Console.ReadLine(); #endif }
static void Main(string[] args) { Options options = null; try { options = CommandLine.Parse <Options>(); } catch (CommandLineException exception) { Console.WriteLine(exception.ArgumentHelp.Message); Console.WriteLine(); Console.WriteLine(exception.ArgumentHelp.GetHelpText(Console.BufferWidth)); #if DEBUG Console.ReadLine(); #endif return; } switch (options.Action) { case "toxml": { using (Stream stream = File.OpenRead(options.Source)) { Stream2File file = new Stream2File(stream); if (options.Output == null || options.Output == "") { options.Output = Path.ChangeExtension(options.Source, "xml"); } XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.IndentChars = "\t"; settings.NewLineChars = "\r\n"; using (XmlWriter xml = XmlWriter.Create(options.Output, settings)) { xml.WriteStartDocument(); xml.WriteStartElement("AssetAssembler"); xml.WriteStartElement("AllocatorTypes"); foreach (var pair in file.AllocatorTypes) { xml.WriteStartElement("AllocatorType"); xml.WriteAttributeString("ID", pair.Key.ToString()); xml.WriteAttributeString("Name", pair.Value); xml.WriteEndElement(); } xml.WriteEndElement(); // AllocatorTypes xml.WriteStartElement("ContainerTypes"); foreach (var pair in file.ContainerTypes) { xml.WriteStartElement("ContainerType"); xml.WriteAttributeString("ID", pair.Key.ToString()); xml.WriteAttributeString("Name", pair.Value); xml.WriteEndElement(); } xml.WriteEndElement(); // ContainerTypes xml.WriteStartElement("PrimitiveTypes"); foreach (var pair in file.PrimitiveTypes) { xml.WriteStartElement("PrimitiveType"); xml.WriteAttributeString("ID", pair.Key.ToString()); xml.WriteAttributeString("Name", pair.Value); xml.WriteEndElement(); } xml.WriteEndElement(); // PrimitiveTypes xml.WriteStartElement("Containers"); foreach (var container in file.Containers) { xml.WriteStartElement("Container"); xml.WriteAttributeString("Name", container.Name); xml.WriteAttributeString("Type", file.ContainerTypes[container.ContainerType]); xml.WriteAttributeString("Flags", container.Flags.ToString()); xml.WriteAttributeString("PackfileBaseOffset", container.PackfileBaseOffset.ToString()); xml.WriteAttributeString("CompressionType", container.CompressionType.ToString()); xml.WriteAttributeString("StubContainerParentName", container.StubContainerParentName); xml.WriteAttributeString("TotalCompressedPackfileReadSize", container.TotalCompressedPackfileReadSize.ToString()); if (container.AuxData.Length > 0) { xml.WriteStartElement("AuxData"); xml.WriteString(Convert.ToBase64String(container.AuxData, Base64FormattingOptions.None)); xml.WriteEndElement(); // AuxData } for (int i = 0; i < container.PrimitiveCount; i++) { var primitive = container.Primitives[i]; var sizes = container.PrimitiveSizes[i]; xml.WriteStartElement("Primitive"); xml.WriteAttributeString("Name", primitive.Name); xml.WriteAttributeString("Type", file.PrimitiveTypes[primitive.Data.Type]); xml.WriteAttributeString("Allocator", file.AllocatorTypes.ContainsKey(primitive.Data.Allocator) ? file.AllocatorTypes[primitive.Data.Allocator] : primitive.Data.Allocator.ToString()); xml.WriteAttributeString("Flags", primitive.Data.Flags.ToString()); xml.WriteAttributeString("ExtensionIndex", primitive.Data.ExtensionIndex.ToString()); xml.WriteAttributeString("CPUSize", primitive.Data.CPUSize.ToString()); xml.WriteAttributeString("GPUSize", primitive.Data.GPUSize.ToString()); xml.WriteAttributeString("AllocationGroup", primitive.Data.AllocationGroup.ToString()); xml.WriteAttributeString("WriteTimeCPUSize", sizes.CPUSize.ToString()); xml.WriteAttributeString("WriteTimeGPUSize", sizes.GPUSize.ToString()); xml.WriteEndElement(); // Primitive } xml.WriteEndElement(); // Container } xml.WriteEndElement(); // Containers xml.WriteEndElement(); // AssetAssembler xml.WriteEndDocument(); } } break; } case "toasm": { using (Stream stream = File.OpenRead(options.Source)) { XDocument xml = XDocument.Load(stream); Stream2File file = new Stream2File(); if (options.Output == null || options.Output == "") { options.Output = Path.ChangeExtension(options.Source, "asm_pc"); } Dictionary <string, byte> allocatorTypesLookup = new Dictionary <string, byte>(); Dictionary <string, byte> containerTypesLookup = new Dictionary <string, byte>(); Dictionary <string, byte> primitiveTypesLookup = new Dictionary <string, byte>(); foreach (var node in xml.Descendants("AllocatorType")) { byte id = byte.Parse(node.Attribute("ID").Value); string name = node.Attribute("Name").Value; allocatorTypesLookup.Add(name, id); file.AllocatorTypes.Add(id, name); } foreach (var node in xml.Descendants("ContainerType")) { byte id = byte.Parse(node.Attribute("ID").Value); string name = node.Attribute("Name").Value; containerTypesLookup.Add(name, id); file.ContainerTypes.Add(id, name); } foreach (var node in xml.Descendants("PrimitiveType")) { byte id = byte.Parse(node.Attribute("ID").Value); string name = node.Attribute("Name").Value; primitiveTypesLookup.Add(name, id); file.PrimitiveTypes.Add(id, name); } foreach (var cNode in xml.Descendants("Container")) { Container container = new Container(); container.Name = cNode.Attribute("Name").Value; container.ContainerType = containerTypesLookup[cNode.Attribute("Type").Value]; container.Flags = (ContainerFlags)ushort.Parse(cNode.Attribute("Flags").Value); container.PackfileBaseOffset = uint.Parse(cNode.Attribute("PackfileBaseOffset").Value); container.CompressionType = byte.Parse(cNode.Attribute("CompressionType").Value); container.StubContainerParentName = cNode.Attribute("StubContainerParentName").Value; container.TotalCompressedPackfileReadSize = int.Parse(cNode.Attribute("TotalCompressedPackfileReadSize").Value); var auxData = cNode.Element("AuxData"); if (auxData != null) { container.AuxData = Convert.FromBase64String(auxData.Value); } else { container.AuxData = new byte[0]; } foreach (var pNode in cNode.Descendants("Primitive")) { Primitive p = new Primitive(); p.Name = pNode.Attribute("Name").Value; p.Data = new PrimitiveData(); p.Data.Type = primitiveTypesLookup[pNode.Attribute("Type").Value]; byte allocatorType = 0; if (byte.TryParse(pNode.Attribute("Allocator").Value, out allocatorType)) { p.Data.Allocator = allocatorType; } else { p.Data.Allocator = allocatorTypesLookup[pNode.Attribute("Allocator").Value]; } p.Data.Flags = byte.Parse(pNode.Attribute("Flags").Value); p.Data.ExtensionIndex = byte.Parse(pNode.Attribute("ExtensionIndex").Value); p.Data.CPUSize = uint.Parse(pNode.Attribute("CPUSize").Value); p.Data.GPUSize = uint.Parse(pNode.Attribute("GPUSize").Value); p.Data.AllocationGroup = byte.Parse(pNode.Attribute("AllocationGroup").Value); container.Primitives.Add(p); WriteTimeSizes size = new WriteTimeSizes(); size.CPUSize = uint.Parse(pNode.Attribute("WriteTimeCPUSize").Value); size.GPUSize = uint.Parse(pNode.Attribute("WriteTimeGPUSize").Value); container.PrimitiveSizes.Add(size); } container.PrimitiveCount = (ushort)container.Primitives.Count; file.Containers.Add(container); } file.Header.Signature = (uint)0xBEEFFEED; file.Header.Version = (ushort)0x000C; file.Header.NumContainers = (short)file.Containers.Count; using (Stream outputStream = File.Create(options.Output)) { file.Save(outputStream); } } break; } case "update": { Stream2File file = null; using (Stream stream = File.OpenRead(options.Source)) { file = new Stream2File(stream); string folder = Path.GetDirectoryName(options.Source); foreach (var container in file.Containers) { string str2File = Path.ChangeExtension(container.Name, ".str2_pc"); string filename = Path.Combine(folder, str2File); if (File.Exists(filename)) { Console.Write("Found {0}, updating... ", str2File); using (Stream str2Stream = File.OpenRead(filename)) { IPackfile packfile = Packfile.FromStream(str2Stream, true); packfile.Update(container); } Console.WriteLine("done."); } else { Console.WriteLine("Could not find {0}.", str2File); } } } using (Stream stream = File.Create(options.Source)) { file.Save(stream); } break; } case "clean": { Stream2File file = null; using (Stream stream = File.OpenRead(options.Source)) { file = new Stream2File(stream); string folder = Path.GetDirectoryName(options.Source); List <string> foundContainerNames = new List <string>(); List <Container> duplicates = new List <Container>(); foreach (var container in file.Containers) { if (!foundContainerNames.Contains(container.Name)) { foundContainerNames.Add(container.Name); } else { duplicates.Add(container); } } foreach (var container in duplicates) { file.Containers.Remove(container); } file.Header.NumContainers = (short)file.Containers.Count; } using (Stream stream = File.Create(options.Source)) { file.Save(stream); } break; } default: { Console.WriteLine("Unrecogised action!"); break; } } #if DEBUG Console.ReadLine(); #endif }