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
        }