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(); }
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); }
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(); }
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(); }