public static List <PackFileInfo> DetectDuplicates(List <PackFileInfo> files) { List <PackFileInfo> newlist = new List <PackFileInfo>(files.Count); for (int i = 0; i < files.Count; ++i) { var npfi = new PackFileInfo(files[i]); npfi.DuplicateOf = null; for (int j = 0; j < i; ++j) { if (files[i].DataStream != null && files[j].DataStream != null) { using (var istr = files[i].DataStream.Duplicate()) using (var jstr = files[j].DataStream.Duplicate()) { if (StreamUtils.IsIdentical(istr, jstr)) { npfi.DuplicateOf = (ulong)j; break; } } } } newlist.Add(npfi); } return(newlist); }
public PackFileInfo(PackFileInfo other) { Name = other.Name; Length = other.Length; RelativePath = other.RelativePath; DataStream = other.DataStream != null ? other.DataStream.Duplicate() : null; DuplicateOf = other.DuplicateOf; }
//添加Token public PackFileInfo AddToken(List <string> keyWords, string fileID) { List <byte[]> random = new List <byte[]>(); byte[] temp = null; List <string> C = new List <string>(); List <string> searched = new List <string>(); foreach (var item in keyWords) { //temp = tool.WordToHash(item); random.Add(temp); string s1 = tool.HmacHash(temp, k1); if (history.Contains(s1)) { searched.Add(s1); } C.Add(tool.HmacAdd(s1)); } //sort比较器实现 C.Sort(); PackFileInfo info = new PackFileInfo(); info.FileID = fileID; info.historyList = searched; info.tokenList = C; return(info); }
public int AddFile(PackFileInfo info, string filePath) { rf.Add(info.FileID, info.tokenList); foreach (var item in info.historyList) { rw[item].Add(info.FileID); } tool.FileAdd(filePath); return(1); }
public static int Pack(List <string> args) { if (args.Count < 2) { PrintPackUsage(); return(-1); } string dir = null; string outName = null; string outHeaderName = null; ushort?bitmask = null; uint? alignment = null; uint? alignmentFirstFile = null; bool orderByExtension = false; bool includeSubdirs = false; bool littleEndian = false; string originalFps4 = null; string metadata = null; string comment = null; uint multiplier = 1; try { for (int i = 0; i < args.Count; ++i) { switch (args[i]) { case "-a": alignment = HexUtils.ParseDecOrHex(args[++i]); break; case "--firstalign": alignmentFirstFile = HexUtils.ParseDecOrHex(args[++i]); break; case "-b": bitmask = (ushort)HexUtils.ParseDecOrHex(args[++i]); break; case "-l": littleEndian = true; break; case "-m": metadata = args[++i]; break; case "-c": comment = UnEscape(args[++i]); break; case "-e": orderByExtension = true; break; case "-s": includeSubdirs = true; break; case "-h": outHeaderName = args[++i]; break; case "-o": originalFps4 = args[++i]; break; case "--multiplier": multiplier = HexUtils.ParseDecOrHex(args[++i]); break; default: if (dir == null) { dir = args[i]; } else if (outName == null) { outName = args[i]; } else { PrintPackUsage(); return(-1); } break; } } } catch (IndexOutOfRangeException) { PrintPackUsage(); return(-1); } if (dir == null || outName == null) { PrintPackUsage(); return(-1); } FPS4 fps4; if (originalFps4 != null) { fps4 = new FPS4(originalFps4, printProgressToConsole: true); } else { fps4 = new FPS4(); } if (bitmask != null) { fps4.ContentBitmask = new ContentInfo((ushort)bitmask); } if (alignment != null) { fps4.Alignment = (uint)alignment; } if (littleEndian) { fps4.Endian = EndianUtils.Endianness.LittleEndian; } if (comment != null) { fps4.ArchiveName = comment; } string[] files; if (includeSubdirs) { files = System.IO.Directory.GetFiles(dir, "*", System.IO.SearchOption.AllDirectories); } else { files = System.IO.Directory.GetFiles(dir); } if (orderByExtension) { files = files.OrderBy(x => x.Split('.').Last()).ToArray(); } Stream outStream = new FileStream(outName, FileMode.Create); Stream outHeaderStream = outHeaderName == null ? null : new FileStream(outHeaderName, FileMode.Create); List <PackFileInfo> packFileInfos = new List <PackFileInfo>(files.Length); foreach (var file in files) { var fi = new System.IO.FileInfo(file); var p = new PackFileInfo(); p.Name = fi.Name; p.Length = fi.Length; if (metadata.Contains('p')) { try { p.RelativePath = FPS4.GetRelativePath(outHeaderName == null ? outName : outHeaderName, fi.FullName); } catch (Exception) { } } p.DataStream = new DuplicatableFileStream(file); packFileInfos.Add(p); } try { FPS4.Pack( packFileInfos, outStream, fps4.ContentBitmask, fps4.Endian, fps4.Unknown2, originalFps4 != null ? new System.IO.FileStream(originalFps4, System.IO.FileMode.Open) : null, fps4.ArchiveName, fps4.FirstFileStart, fps4.Alignment, outputHeaderStream: outHeaderStream, metadata: metadata, alignmentFirstFile: alignmentFirstFile, fileLocationMultiplier: multiplier, printProgressToConsole: true ); } finally { outStream.Close(); if (outHeaderStream != null) { outHeaderStream.Close(); } } return(0); }
private static void GenerateUndubRoot(string datadir, string voicedir, string outdir, UndubVersion undubVersion) { Console.WriteLine(string.Format("processing {0}", "rootR.cpk")); var datastream = new DuplicatableFileStream(Path.Combine(datadir, "rootR.cpk")); var voicestream = new DuplicatableFileStream(Path.Combine(voicedir, "rootR.cpk")); var datacpk = new HyoutaTools.Tales.CPK.CpkContainer(datastream.Duplicate()); var voicecpk = new HyoutaTools.Tales.CPK.CpkContainer(voicestream); string outfile = Path.Combine(outdir, "rootR.cpk"); var builder = new HyoutaTools.Tales.CPK.CpkBuilder(datastream.Duplicate()); // audio containers: we can direct-copy these, no need to un/repack foreach (string name in new string[] { "RTS.nub", "VOBTL.nub", "VOBTLETC.nub", "VOCHT.nub", "VOSCE01.nub", "VOSCE02.nub", "VOSCE03.nub", "VOSCE04.nub", "VOSCE05.nub", "VOSCE06.nub", "VOSCE07.nub", "VOSCE08.nub", "VOSCE09.nub", "VOSCE15.nub", "VOSCE16.nub" }) { string subdir = "snd/strpck"; string subpath = subdir + "/" + name; Console.WriteLine(string.Format("injecting {0}", subpath)); var subfile = builder.Files.Where(x => x.Directory == subdir && x.Name == name).First(); ReplaceFile(subfile, voicecpk.GetChildByName(subpath).AsFile.DataStream.Duplicate().CopyToByteArrayStreamAndDispose()); } // skits: for all of these unpack them (FPS4 containers), copy over file with index 1, repack // some of them are mistimed now because of altered timing for english skits, this could be refined... for (long i = 0; i < datacpk.toc_entries; ++i) { var entry = datacpk.GetEntryByIndex(i); if (entry != null && entry.dir_name == "chat/chd" && entry.file_name.EndsWith(".chd") && entry.file_name != "debug_02.chd") { // for EU undub also exclude CHT_PR*.chd because those files are not on the EU disc (they look unused on US too...) if (!(undubVersion == UndubVersion.JpVoicesToEu && entry.file_name.StartsWith("CHT_PR"))) { string subpath = entry.dir_name + "/" + entry.file_name; Console.WriteLine(string.Format("injecting {0}", subpath)); var skitstreamen = datacpk.GetChildByIndex(i).AsFile.DataStream; var skitstreamjp = voicecpk.GetChildByName(subpath).AsFile.DataStream; var fps4en = new FPS4(skitstreamen); var fps4jp = new FPS4(skitstreamjp); List <PackFileInfo> packFileInfos = new List <PackFileInfo>(fps4en.Files.Count - 1); for (int j = 0; j < fps4en.Files.Count - 1; ++j) { var pf = new PackFileInfo(); pf.Name = fps4en.Files[j].FileName; if (j == 1) { pf.DataStream = fps4jp.GetChildByIndex(j).AsFile.DataStream.Duplicate(); } else { pf.DataStream = fps4en.GetChildByIndex(j).AsFile.DataStream.Duplicate(); } pf.Length = pf.DataStream.Length; packFileInfos.Add(pf); } packFileInfos = FPS4.DetectDuplicates(packFileInfos); MemoryStream newfps4stream = new MemoryStream(); FPS4.Pack(packFileInfos, newfps4stream, fps4en.ContentBitmask, EndianUtils.Endianness.BigEndian, fps4en.Unknown2, null, fps4en.ArchiveName, fps4en.FirstFileStart, 0x20); newfps4stream.Position = 0; var subfile = builder.Files.Where(x => x.Directory == entry.dir_name && x.Name == entry.file_name).First(); ReplaceFile(subfile, newfps4stream.CopyToByteArrayStreamAndDispose(), true); } } } // post-battle skits/quotes for (long i = 0; i < datacpk.toc_entries; ++i) { var entry = datacpk.GetEntryByIndex(i); if (entry != null && entry.dir_name == "btl/acf" && ( (entry.file_name.StartsWith("skt") && entry.file_name.EndsWith(".acf") && entry.file_name != "skt000.acf") || (entry.file_name.StartsWith("vav") && entry.file_name.EndsWith(".acf") && entry.file_name != "vav000.acf") )) { string subpath = entry.dir_name + "/" + entry.file_name; Console.WriteLine(string.Format("injecting {0}", subpath)); var subfile = builder.Files.Where(x => x.Directory == entry.dir_name && x.Name == entry.file_name).First(); ReplaceFile(subfile, voicecpk.GetChildByName(subpath).AsFile.DataStream.Duplicate().CopyToByteArrayStreamAndDispose()); } } CreateDirectory(outdir); WriteCpk(outfile, builder); }