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; } using (Stream stream = File.OpenRead(options.Source)) { var packfile = Packfile.FromStream(stream, Path.GetExtension(options.Source) == ".str2_pc"); string folderName = (options.Output != null) ? options.Output : "extracted-" + Path.GetFileName(options.Source); Console.WriteLine("Extracting {0} to {1}.", options.Source, folderName); Directory.CreateDirectory(folderName); int currentFile = 0; foreach (IPackfileEntry entry in packfile.Files) { currentFile++; Console.Write("[{0}/{1}] Extracting {2}... ", currentFile, packfile.Files.Count, entry.Name); using (Stream outputStream = File.Create(Path.Combine(folderName, entry.Name))) { using (Stream inputStream = entry.GetStream()) { inputStream.CopyTo(outputStream); } outputStream.Flush(); } Console.WriteLine("done."); } #if DEBUG Console.ReadLine(); #endif } }
private void DoExtract(object o) { DisableButton(); ExtractOptions options = (ExtractOptions)o; SetProgressBarSettings(0, 100, 1, ProgressBarStyle.Marquee); SetText("Opening packfile..."); using (Stream stream = File.OpenRead(options.Source)) { var packfile = Packfile.FromStream(stream, Path.GetExtension(options.Source) == ".str2_pc"); string filename = Path.GetFileName(options.Source); string outputDir = Path.Combine(options.Destination, filename); if (File.Exists(outputDir)) { outputDir = Path.Combine(options.Destination, "extracted-" + filename); } Directory.CreateDirectory(outputDir); SetProgressBarSettings(0, packfile.Files.Count, 1, ProgressBarStyle.Continuous); SetText("Extracting {0}...", filename); foreach (IPackfileEntry entry in packfile.Files) { using (Stream outputStream = File.Create(Path.Combine(outputDir, entry.Name))) { using (Stream inputStream = entry.GetStream()) { inputStream.CopyTo(outputStream); } outputStream.Flush(); } 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)); Console.ReadLine(); return; } if (options.Source == null) { string srtt = ThomasJepp.SaintsRow.Utility.GetGamePath(GameSteamID.SaintsRowTheThird); string sriv = ThomasJepp.SaintsRow.Utility.GetGamePath(GameSteamID.SaintsRowIV); string srgooh = ThomasJepp.SaintsRow.Utility.GetGamePath(GameSteamID.SaintsRowGatOutOfHell); int gameCount = 0, srttNum = 0, srivNum = 0, srgoohNum = 0; Console.WriteLine("Detected the following games:"); if (srtt != null) { gameCount++; srttNum = gameCount; Console.WriteLine("{0}. Saints Row The Third: {1}", gameCount, srtt); } 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); } if (gameCount == 0) { Console.WriteLine("Couldn't find any installed games?"); Console.WriteLine(); Console.WriteLine("Press enter to exit."); Console.ReadLine(); return; } 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 (srttNum == 1) { options.Source = srtt; Console.WriteLine("Updating Saints Row: The Third files."); } else 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 (srttNum == 2) { options.Source = srtt; Console.WriteLine("Updating Saints Row: The Third files."); } else 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."); } } else if (input.Key == ConsoleKey.D3 || input.Key == ConsoleKey.NumPad3) { if (srttNum == 3) { options.Source = srtt; Console.WriteLine("Updating Saints Row: The Third files."); } else if (srivNum == 3) { options.Source = sriv; Console.WriteLine("Updating Saints Row IV files."); } else if (srgoohNum == 3) { 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 a Saints Row 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, IAssetAssemblerFile> asmsToSave = new Dictionary <string, IAssetAssemblerFile>(); 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()) { IAssetAssemblerFile asm = AssetAssemblerFile.FromStream(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(); }
static bool ClonePackfile(IGameInstance sriv, string packfileName, string clothSimFilename, string outputFolder, IAssetAssemblerFile newAsm, string oldName, string newName, string newStr2Filename) { using (Stream oldStream = sriv.OpenPackfileFile(packfileName)) { if (oldStream == null) { return(false); } IContainer oldContainer = FindContainer(sriv, packfileName); if (oldContainer == null) { return(false); } oldContainer.Name = Path.GetFileNameWithoutExtension(newStr2Filename); using (IPackfile oldPackfile = Packfile.FromStream(oldStream, true)) { using (IPackfile newPackfile = Packfile.FromVersion(0x0A, true)) { newPackfile.IsCompressed = true; newPackfile.IsCondensed = true; Stream pegStream = null; var pegEntry = FindPackfileEntry(oldPackfile, ".cpeg_pc"); if (pegEntry != null) { pegStream = ProcessPeg(pegEntry, newName); } foreach (var file in oldPackfile.Files) { string extension = Path.GetExtension(file.Name); IPrimitive primitive = FindPrimitive(oldContainer, file.Name); switch (extension) { case ".ccmesh_pc": { Stream newCcmeshStream = ProcessCCMesh(file, oldName, newName); string newMeshName = newName + extension; newPackfile.AddFile(newCcmeshStream, newMeshName); primitive.Name = newMeshName; break; } case ".cpeg_pc": { string newPegName = newName + extension; newPackfile.AddFile(pegStream, newPegName); primitive.Name = newPegName; break; } case ".cmorph_pc": { string morphSuffix = Path.GetFileNameWithoutExtension(file.Name).Split('_').Last(); string newFilename = newName + "_" + morphSuffix + extension; Stream fStream = file.GetStream(); // copy the morph to the output folder (fixes some odd issues with the morph not applying when loaded from save) using (Stream s = File.Create(Path.Combine(outputFolder, newFilename))) { fStream.CopyTo(s); } fStream.Seek(0, SeekOrigin.Begin); newPackfile.AddFile(fStream, newFilename); primitive.Name = newFilename; break; } case ".sim_pc": { string newFilename = newName + extension; Stream newStream = ProcessClothSim(file, newName); newPackfile.AddFile(newStream, newFilename); primitive.Name = newFilename; break; } case ".gcmesh_pc": case ".gpeg_pc": case ".rig_pc": { string newFilename = newName + extension; newPackfile.AddFile(file.GetStream(), newFilename); if (primitive != null) { primitive.Name = newFilename; } break; } default: throw new Exception(String.Format("Unrecognised extension: {0}", extension)); } } newAsm.Containers.Add(oldContainer); using (Stream s = File.Create(newStr2Filename)) { newPackfile.Save(s); } newPackfile.Update(oldContainer); } } } return(true); }
static void Main(string[] args) { if (args.Length < 3) { Console.WriteLine("Usage:"); Console.WriteLine("EditPackfile <source> <destination> <new file 1> <new file 2>..."); return; } string sourcePath = args[0]; string destinationPath = args[1]; List <string> newFiles = new List <string>(); for (int i = 2; i < args.Length; i++) { newFiles.Add(args[i]); } string sourceExtension = Path.GetExtension(sourcePath); bool sourceIsStr2 = sourceExtension.ToLowerInvariant() == ".str2_pc"; Dictionary <string, NewFileEntry> filenameToPathMap = new Dictionary <string, NewFileEntry>(StringComparer.OrdinalIgnoreCase); foreach (string newFile in newFiles) { filenameToPathMap.Add(Path.GetFileName(newFile), new NewFileEntry(newFile)); } using (Stream sourceStream = File.OpenRead(sourcePath)) { using (IPackfile source = Packfile.FromStream(sourceStream, sourceIsStr2)) { using (IPackfile destination = Packfile.FromVersion(source.Version, sourceIsStr2)) { destination.IsCompressed = source.IsCompressed; destination.IsCondensed = source.IsCondensed; foreach (IPackfileEntry entry in source.Files) { string filename = entry.Name; if (filenameToPathMap.ContainsKey(filename)) { NewFileEntry newFilePath = filenameToPathMap[filename]; destination.AddFile(File.OpenRead(newFilePath.Path), entry.Name); newFilePath.Inserted = true; Console.WriteLine("Replaced {0}.", filename); } else { destination.AddFile(entry.GetStream(), entry.Name); } } foreach (var pair in filenameToPathMap) { NewFileEntry nfe = pair.Value; if (!nfe.Inserted) { string filename = Path.GetFileName(nfe.Path); destination.AddFile(File.OpenRead(nfe.Path), filename); Console.WriteLine("Inserted {0}.", filename); } } using (Stream destinationStream = File.Create(destinationPath)) { destination.Save(destinationStream); } } } } #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; } Directory.CreateDirectory(options.Output); string[] files = Directory.GetFiles(options.Source); Dictionary <string, IPackfile> packfiles = new Dictionary <string, IPackfile>(); int totalFiles = 0; Console.Write("Looking for packfiles... "); foreach (string file in files) { if (Path.GetExtension(file) == ".vpp_pc") { var packfile = Packfile.FromStream(File.OpenRead(file), false); totalFiles += packfile.Files.Count; packfiles.Add(Path.GetFileName(file), packfile); } } Console.WriteLine("found {0} packfiles, containing {1} files.", packfiles.Count, totalFiles); int currentFile = 0; foreach (var packfilePair in packfiles) { Console.WriteLine("{0} Compressed: {1} Condensed: {2}", packfilePair.Key, packfilePair.Value.IsCompressed, packfilePair.Value.IsCondensed); Directory.CreateDirectory(Path.Combine(options.Output, packfilePair.Key)); foreach (var file in packfilePair.Value.Files) { currentFile++; if (Path.GetExtension(file.Name) == ".str2_pc") { string strOutputFolder = Path.Combine(options.Output, packfilePair.Key, file.Name); Directory.CreateDirectory(strOutputFolder); Console.WriteLine("[{0}/{1}] Extracting {2}: packfile {3} to {4}:", currentFile, totalFiles, packfilePair.Key, file.Name, strOutputFolder); using (Stream strStream = file.GetStream()) { using (var strPackfile = Packfile.FromStream(strStream, true)) { int strCurrentFile = 0; foreach (var strFile in strPackfile.Files) { strCurrentFile++; Console.Write("[{0}/{1}] [{2}/{3}] Extracting {4}\\{5}: {6}", currentFile, totalFiles, strCurrentFile, strPackfile.Files.Count, packfilePair.Key, file.Name, strFile.Name); using (Stream outputStream = File.Create(Path.Combine(strOutputFolder, strFile.Name))) { using (Stream inputStream = strFile.GetStream()) { inputStream.CopyTo(outputStream); } outputStream.Flush(); } Console.WriteLine("done."); } } } } else { Console.Write("[{0}/{1}] Extracting {2}: {3}... ", currentFile, totalFiles, packfilePair.Key, file.Name); using (Stream outputStream = File.Create(Path.Combine(options.Output, packfilePair.Key, file.Name))) { using (Stream inputStream = file.GetStream()) { inputStream.CopyTo(outputStream); } outputStream.Flush(); } 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)); #if DEBUG Console.ReadLine(); #endif return; } switch (options.Action) { case "toxml": { using (Stream stream = File.OpenRead(options.Source)) { IAssetAssemblerFile file = AssetAssemblerFile.FromStream(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.WriteAttributeString("Version", file.Version.ToString()); 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.Type]); xml.WriteAttributeString("Allocator", file.AllocatorTypes.ContainsKey(primitive.Allocator) ? file.AllocatorTypes[primitive.Allocator] : primitive.Allocator.ToString()); xml.WriteAttributeString("Flags", primitive.Flags.ToString()); xml.WriteAttributeString("ExtensionIndex", primitive.ExtensionIndex.ToString()); xml.WriteAttributeString("CPUSize", primitive.CPUSize.ToString()); xml.WriteAttributeString("GPUSize", primitive.GPUSize.ToString()); xml.WriteAttributeString("AllocationGroup", primitive.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); var asmNode = xml.Element("AssetAssembler"); uint version = uint.Parse(asmNode.Attribute("Version").Value); IAssetAssemblerFile file = AssetAssemblerFile.Create(version); 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")) { IContainer container = file.CreateContainer(); 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")) { IPrimitive p = container.CreatePrimitive(); p.Name = pNode.Attribute("Name").Value; p.Type = primitiveTypesLookup[pNode.Attribute("Type").Value]; byte allocatorType = 0; if (byte.TryParse(pNode.Attribute("Allocator").Value, out allocatorType)) { p.Allocator = allocatorType; } else { p.Allocator = allocatorTypesLookup[pNode.Attribute("Allocator").Value]; } p.Flags = byte.Parse(pNode.Attribute("Flags").Value); p.ExtensionIndex = byte.Parse(pNode.Attribute("ExtensionIndex").Value); p.CPUSize = uint.Parse(pNode.Attribute("CPUSize").Value); p.GPUSize = uint.Parse(pNode.Attribute("GPUSize").Value); p.AllocationGroup = byte.Parse(pNode.Attribute("AllocationGroup").Value); container.Primitives.Add(p); } container.PrimitiveCount = (short)container.Primitives.Count; file.Containers.Add(container); } using (Stream outputStream = File.Create(options.Output)) { file.Save(outputStream); } } break; } case "update": { IAssetAssemblerFile file = null; using (Stream stream = File.OpenRead(options.Source)) { file = AssetAssemblerFile.FromStream(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; } default: { Console.WriteLine("Unrecogised action!"); break; } } #if DEBUG Console.ReadLine(); #endif }