Пример #1
0
        private static void OperationExtractCPK()
        {
            string filename = ConsolePath("Full path to CPK archive..?");

            if (filename.IsEmpty())
            {
                return;
            }
            Stream stream = new CachedReadStream(new FileStream(filename, FileMode.Open, FileAccess.Read));
            CPK    cpk    = new CPK(stream);
            string path   = Path.Combine(Path.GetDirectoryName(filename), Path.GetFileName(filename) + ".ext");

            cpk.Root.Extract(path);
            stream.Close();
        }
Пример #2
0
        private static void OperationExtractFPS4()
        {
            string filename = ConsolePath("Full path to FPS4 archive..?");

            if (filename.IsEmpty())
            {
                return;
            }
            Stream stream = new CachedReadStream(new FileStream(filename, FileMode.Open, FileAccess.Read));
            FPS4   fps    = new FPS4(stream);
            string path   = Path.Combine(Path.GetDirectoryName(filename), Path.GetFileName(filename) + ".ext");

            fps.Root.Extract(path);
            stream.Close();

            File.WriteAllText(Path.Combine(path, "fps4.type"), fps.Type);
        }
Пример #3
0
        private static void OperationPackFPS4()
        {
            string dirname = ConsolePath("Full path to FPS4 file contents..?");
            string filename;

            if (dirname.EndsWith(".ext"))
            {
                filename = dirname.Substring(0, dirname.Length - 4);
            }
            else
            {
                filename = ConsolePath("Full path to FPS4 archive..?");
            }

            if (!File.Exists(filename))
            {
                Console.WriteLine("FPS4 file does not exist.");
                return;
            }

            Stream stream = new CachedReadStream(new FileStream(filename, FileMode.Open, FileAccess.Read));

            FPS4 fps = new FPS4(stream);

            DelayedStreamCache cache = new DelayedStreamCache();

            string[] files = Directory.GetFiles(dirname, "*", SearchOption.TopDirectoryOnly);
            foreach (string file in files)
            {
                string        fname = Path.GetFileName(file);
                FPS4Base.Node node  = fps.Base.Nodes.FirstOrDefault(n => n.Filename == fname);

                Stream data = new FileStream(file, FileMode.Open, FileAccess.Read);
                cache.AddStream(data);

                if (node == null)
                {
                    continue;

                    /* TODO: Only add when we want to
                     * node = new FPS4Base.Node(0, (uint)data.Length, (uint)data.Length, fname, 0, 0, data);
                     * fps.Base.Nodes.Insert((int)fps.Base.Files - 1, node);
                     * fps.Base.Files++;
                     */
                }
                else
                {
                    node.Data = data;
                }
            }

            fps.Base.Reorder();

            Stream ostream = new FileStream(filename + ".new", FileMode.Create, FileAccess.Write);

            fps.Base.Save(ostream);
            ostream.Close();

            stream.Close();

            cache.Dispose();
        }
Пример #4
0
        private static void OperationPatchCPK(bool sub)
        {
            bool togf = false;

            uint   cpkoffset  = 0;
            string cpkname    = ConsolePath("Full path to CPK archive..?");
            string subcpkname = cpkname;

            if (cpkname.IsEmpty())
            {
                return;
            }

            Stream stream    = new CachedReadStream(new FileStream(cpkname, FileMode.Open, FileAccess.Read, FileShare.Read));
            Stream substream = stream;
            CPK    cpk       = new CPK(stream);

            if (sub)
            {
                string subname = ConsolePath("Filename of CPK sub-archive..?");
                if (subname.IsEmpty())
                {
                    return;
                }
                FileNode subfile = cpk.Root.Find(subname, SearchOption.AllDirectories) as FileNode;
                if (subfile == null)
                {
                    Console.WriteLine("Could not find the specified file in the parent CPK archive.");
                    return;
                }
                substream = subfile.Data;

                cpkoffset = (uint)(substream as Substream).Offset;

                subcpkname = cpkname + "-" + Path.GetFileNameWithoutExtension(subname);

                cpk = new CPK(substream);
            }

            togf = (cpk.Version == 7);

            UTF.ShortValue align      = cpk.Header.Rows[0].FindValue("Align") as UTF.ShortValue;
            ushort         alignment  = align == null ? (ushort)0x20 : align.Value;
            ulong          cpklen     = Util.RoundUp((ulong)Math.Max(stream.Length, togf ? stream.Length : 0x70000000), alignment);
            string         cpklenfile = cpkname + ".patch";

            if (File.Exists(cpklenfile))
            {
                cpklen = ulong.Parse(File.ReadAllText(cpklenfile));
            }

            long         tocoffset = (long)(cpk.Header.Rows[0].FindValue("TocOffset") as UTF.LongValue).Value;
            long         rowoffset = tocoffset + 0x10;
            EndianReader reader    = new EndianReader(substream, Endianness.BigEndian);

            reader.Position = rowoffset + 0x1A;
            uint rowsize = reader.ReadUInt16();

            reader.Position = rowoffset + 0x08;
            rowoffset      += reader.ReadUInt32() + 0x08;

            ulong baseoffset = cpkoffset + (togf ? (ulong)tocoffset : (cpk.Header.Rows[0].FindValue("ContentOffset") as UTF.LongValue).Value);

            string       tocname = subcpkname + ".toc";
            Stream       toc     = new FileStream(tocname, FileMode.OpenOrCreate);
            EndianReader writer  = new EndianReader(toc, Endianness.BigEndian);
            long         begin   = Util.RoundDown(rowoffset, 4);
            long         end     = Util.RoundUp(rowoffset + rowsize * cpk.ToC.Rows.Count, 4);

            if (toc.Length == 0)
            {
                reader.Position = begin;
                Util.StreamCopy(toc, reader, end - begin);
            }

            while (true)
            {
                string filename = ConsolePath("Full path to file to patch in..?");
                if (filename.IsEmpty())
                {
                    break;
                }

                string path = filename;
                if (path.EndsWith(".new"))
                {
                    path = path.Substring(0, path.Length - 4);
                }

                bool dirstr = cpk.ToC.Columns.Find(r => r.Name == "DirName") != null;

rowsearch:
                string shortname = Path.GetFileName(path);
                string dirname = Path.GetDirectoryName(path).Replace('\\', '/');

                UTF.Row filerow = cpk.ToC.Rows.Find(r => (r.FindValue("FileName") as UTF.StringValue).Value == shortname && (!dirstr || dirname.EndsWith((r.FindValue("DirName") as UTF.StringValue).Value)));
                if (filerow == null)
                {
                    path = ConsolePath("A matching filename was not found. Please enter the original filename now...");
                    if (path.IsEmpty())
                    {
                        break;
                    }

                    goto rowsearch;
                }

                uint filelen = (uint)new FileInfo(filename).Length;

                ulong fileoffset = baseoffset + (filerow.FindValue("FileOffset") as UTF.LongValue).Value;
                if (filelen > (filerow.FindValue("FileSize") as UTF.IntValue).Value)
                {
                    fileoffset = cpklen;
                }

                writer.Position = rowoffset - begin + rowsize * cpk.ToC.Rows.IndexOf(filerow);

                foreach (UTF.Value value in filerow.Values)
                {
                    switch (value.Type.Name)
                    {
                    case "FileSize":
                        writer.Write(filelen);
                        break;

                    case "ExtractSize":
                        writer.Write(filelen);
                        break;

                    case "FileOffset":
                        writer.Write((ulong)(fileoffset - baseoffset));
                        break;

                    default:
                        writer.Position += value.Type.Size;
                        break;
                    }
                }

                if (fileoffset == cpklen)
                {
                    cpklen = Util.RoundUp(fileoffset + filelen, alignment);
                    File.WriteAllText(cpklenfile, cpklen.ToString());
                }

                Console.WriteLine("The following patches will need to be applied.");

                Console.WriteLine("<file resize=\"false\" offset=\"0x" + Util.ToString((uint)begin + cpkoffset) + "\" disc=\"" + Path.GetFileName(cpkname) + "\" external=\"" + Path.GetFileName(tocname) + "\" />");
                Console.WriteLine("<file resize=\"false\" offset=\"0x" + Util.ToString((uint)fileoffset) + "\" disc=\"" + Path.GetFileName(cpkname) + "\" external=\"" + Path.GetFileName(filename) + "\" />");
            }

            stream.Close();
            toc.Close();
        }