public static void Open(String inputPath, out LocalsFile lf, out List<CineFile> cfl, out String bigPath, out String patchPath) { lf = null; cfl = new List<CineFile>(); bool isBigEndian; var doc = new XPathDocument(inputPath, XmlSpace.Preserve); var nav = doc.CreateNavigator(); var root = nav.SelectSingleNode("/root"); bigPath = root.GetAttribute("bigpath", ""); patchPath = root.GetAttribute("patchpath", ""); var be = root.GetAttribute("bigendian", ""); if (be == string.Empty) isBigEndian = false; else isBigEndian = bool.Parse(be); var fileNodes = root.Select("file"); while (fileNodes.MoveNext() == true) { addCineFileNode(fileNodes.Current, cfl, isBigEndian); } var localsNode = root.Select("locals"); localsNode.MoveNext(); addLocalsFileNode(localsNode.Current, out lf, isBigEndian); }
public void AddLocalsFile(LocalsFile lf, String basepath, String filename) { if (isFileEntryOpen) { isFileEntryOpen = false; xml.WriteEndElement(); } xml.WriteStartElement("locals"); xml.WriteAttributeString("id", lf.id.ToString()); xml.WriteAttributeString("base", basepath); xml.WriteAttributeString("name", filename); foreach (LocalsEntry e in lf.entries) { if (e.text != string.Empty) { var lines = e.text.Split("\n".ToCharArray()); foreach (string line in lines) { xml.WriteComment(line); xml.WriteStartElement("entry"); xml.WriteAttributeString("index", e.index.ToString()); xml.WriteAttributeString("offset", e.offset.ToString()); xml.WriteValue(line); xml.WriteEndElement(); } } } xml.WriteEndElement(); }
public static void Open(String inputPath, out LocalsFile lf, out List <CineFile> cfl, out String bigPath, out String patchPath) { lf = null; cfl = new List <CineFile>(); bool isBigEndian; var doc = new XPathDocument(inputPath, XmlSpace.Preserve); var nav = doc.CreateNavigator(); var root = nav.SelectSingleNode("/root"); bigPath = root.GetAttribute("bigpath", ""); patchPath = root.GetAttribute("patchpath", ""); var be = root.GetAttribute("bigendian", ""); if (be == string.Empty) { isBigEndian = false; } else { isBigEndian = bool.Parse(be); } var fileNodes = root.Select("file"); while (fileNodes.MoveNext() == true) { addCineFileNode(fileNodes.Current, cfl, isBigEndian); } var localsNode = root.Select("locals"); localsNode.MoveNext(); addLocalsFileNode(localsNode.Current, out lf, isBigEndian); }
public static void doExtract(string[] args) { bool isBigEndian = false; LocaleID lang = LocaleID.Default; String bigfilePath = String.Empty; String patchPath = String.Empty; if (args.Length < 2) { Console.WriteLine("Error! Not enough arguments passed to program."); Console.WriteLine(""); showHelpAndQuit(); } else { if (args[1] == "help") { showHelpAndQuit(); } else if (args.Length < 3) { Console.WriteLine("Error! Not enough arguments passed to program."); Console.WriteLine(""); showHelpAndQuit(); } else if (args.Length > 5) { Console.WriteLine("Error! Too many arguments passed to program."); Console.WriteLine(""); showHelpAndQuit(); } else { lang = Locale.getFromString(args[1]); if (lang == LocaleID.Default) { Console.WriteLine("Error! Unknown language {0}", args[1]); Console.WriteLine(""); showHelpAndQuit(); } bigfilePath = args[2]; if (args.Length > 3) { if (args[3] == "be") { isBigEndian = true; if (args.Length > 4) { patchPath = args[4]; } } else { patchPath = args[3]; } } } } // Remove trailing backslash on paths if (bigfilePath.EndsWith("\\")) { bigfilePath = bigfilePath.Remove(bigfilePath.Length - 1); } if (patchPath.EndsWith("\\")) { patchPath = patchPath.Remove(patchPath.Length - 1); } // Get locale mask uint mask; if (patchPath != "") { uint mask2 = Locale.getLocaleMask(bigfilePath); mask = Locale.getLocaleMask(patchPath); if (mask2 != mask) { throw new Exception("Patch and bigfile locale mask different"); } } else { mask = Locale.getLocaleMask(bigfilePath); } if (mask == uint.MaxValue) { throw new Exception("Error finding localisation database (\"locals.bin\"). Make sure the game files are properly unpacked."); } else if (mask == (uint.MaxValue - 1)) { Console.WriteLine(""); Console.WriteLine("Unable to determine language of game files."); Console.WriteLine("Please confirm that the language {0} is supported by your game.", Locale.toString(lang)); Console.WriteLine("NOTE: If the language is not supported by the game, you won't see any changes!"); Console.Write("Confirm? (y/n)"); var yes = new ConsoleKeyInfo('y', ConsoleKey.Y, false, false, false); var no = new ConsoleKeyInfo('n', ConsoleKey.N, false, false, false); while (true) { var key = Console.ReadKey(true); if (key == no) { System.Environment.Exit(0); } else if (key == yes) { break; } } Console.WriteLine(""); } //Check if lang is present in files else if ((mask & (1 << (int)lang)) == 0) { Console.WriteLine(""); Console.WriteLine("Error! Language {0} not found in game files.", Locale.toString(lang)); Console.WriteLine(""); Console.WriteLine("Detected languages:"); for (int i = 0; i < 16; i++) { if ((mask & (1 << i)) != 0) { Console.WriteLine(Locale.toString((LocaleID)i)); } } System.Environment.Exit(0); } TransFile tf = new TransFile(bigfilePath, patchPath, isBigEndian); var files = getFilelist(bigfilePath, patchPath, (int)lang, mask); System.Console.WriteLine("Searching following files for translatable text:"); int f = 0; foreach (string file in files) { System.Console.WriteLine("{0} of {1} - {2}", ++f, files.Count, Path.GetFileName(file)); if (file.EndsWith("locals.bin")) { LocalsFile lf = new LocalsFile(isBigEndian); lf.parse(file); string basep; string name; if (file.StartsWith(bigfilePath)) { basep = bigfilePath; name = file.Substring(bigfilePath.Length); } else { basep = patchPath; name = file.Substring(patchPath.Length); } tf.AddLocalsFile(lf, basep, name); } else { CineFile cf = new CineFile(isBigEndian); cf.parse(file); if (cf.isSubs()) { string basep; string name; if (file.StartsWith(bigfilePath)) { basep = bigfilePath; name = file.Substring(bigfilePath.Length); } else { basep = patchPath; name = file.Substring(patchPath.Length); } tf.AddFile(basep, name); List <SubtitleEntry> entries = cf.getSubtitles(); foreach (SubtitleEntry e in entries) { if (e.lang == lang) { tf.AddEntry(e.text, e.lang.ToString(), e.blockNumber.ToString()); } } } } } tf.Close(); System.Console.WriteLine("Translatable text saved to file \"translations.xml\""); }
public static void doApply(string[] args) { String transFilePath = String.Empty; String ovrFileBasePath = String.Empty; String ovrFilePatchPath = String.Empty; if (args.Length < 2) { Console.WriteLine("Error! Not enough arguments passed to program."); Console.WriteLine(""); showHelpAndQuit(); } else { if (args[1] == "help") { showHelpAndQuit(); } else if (args.Length > 4) { Console.WriteLine("Error! Too many arguments passed to program."); Console.WriteLine(""); showHelpAndQuit(); } transFilePath = args[1]; if (args.Length > 2) { ovrFileBasePath = args[2]; } if (args.Length > 3) { ovrFilePatchPath = args[3]; } } LocalsFile localsFile = null; List <CineFile> cineFileList = null; String patchPathBase, origPatchPathBase; String bigPathBase, origBigPathBase; String outPath = "newpatch"; String dest; Directory.CreateDirectory(outPath); origBigPathBase = String.Empty; origPatchPathBase = String.Empty; // Get info from translations.xml file System.Console.Write("Loading translation data..."); TransFile.Open(transFilePath, out localsFile, out cineFileList, out bigPathBase, out patchPathBase); System.Console.WriteLine("done!"); if (ovrFileBasePath != String.Empty) { origBigPathBase = bigPathBase; bigPathBase = ovrFileBasePath; if (patchPathBase != String.Empty) { if (ovrFilePatchPath == String.Empty) { System.Console.WriteLine("Error: A patch was specified in the translation file\nPatch override path must be provided!"); System.Environment.Exit(-1); } else { origPatchPathBase = patchPathBase; patchPathBase = ovrFilePatchPath; } } System.Console.WriteLine("Using different source paths"); System.Console.WriteLine("Base: {0}", bigPathBase); if (patchPathBase != String.Empty) { System.Console.WriteLine("Patch: {0}", patchPathBase); } else { System.Console.WriteLine(""); } } // Copy existing patch into output dir System.Console.Write("Copying existing patch data..."); if (patchPathBase != "") { foreach (string filename in Directory.GetFiles(patchPathBase, "*.*", SearchOption.AllDirectories)) { dest = outPath + filename.Substring(patchPathBase.Length); Directory.CreateDirectory(Path.GetDirectoryName(dest)); File.Copy(filename, dest, true); } System.Console.WriteLine("done!"); } else { System.Console.WriteLine("No patch specified, skipping!"); //Creating empty bigfile.xml var xmlsettings = new XmlWriterSettings(); xmlsettings.Indent = true; XmlWriter xml = XmlWriter.Create(outPath + "\\bigfile.xml", xmlsettings); // Open main files bigfile.xml to get values var doc = new XPathDocument(bigPathBase + "\\bigfile.xml"); var nav = doc.CreateNavigator(); var root = nav.SelectSingleNode("/files"); xml.WriteStartDocument(); xml.WriteStartElement("files"); xml.WriteAttributeString("alignment", root.GetAttribute("alignment", "")); xml.WriteAttributeString("endian", root.GetAttribute("endian", "")); xml.WriteEndElement(); xml.WriteEndDocument(); xml.Flush(); xml.Close(); } XmlDocument xdoc = new XmlDocument(); xdoc.Load(outPath + "\\bigfile.xml"); // Create new files in out dir System.Console.WriteLine("Creating translated files..."); // locals.bin if (localsFile != null) { dest = outPath + localsFile.name; Directory.CreateDirectory(Path.GetDirectoryName(dest)); if (localsFile.sourcePath == origBigPathBase) { localsFile.sourcePath = bigPathBase; } else if (localsFile.sourcePath == origPatchPathBase) { localsFile.sourcePath = patchPathBase; } localsFile.rebuildAndSave(dest); System.Console.WriteLine(dest); if (localsFile.sourcePath.StartsWith(bigPathBase)) { // Add node in file xdoc.DocumentElement.AppendChild(createNode(xdoc, localsFile.name)); } } // mul files if (cineFileList.Count > 0) { foreach (CineFile cinefile in cineFileList) { dest = outPath + cinefile.name; Directory.CreateDirectory(Path.GetDirectoryName(dest)); // Replace the source path for the override one // If no override, orig*PathBase will be empty if (cinefile.sourcePath == origBigPathBase) { cinefile.sourcePath = bigPathBase; } else if (cinefile.sourcePath == origPatchPathBase) { cinefile.sourcePath = patchPathBase; } cinefile.rebuild(dest); System.Console.WriteLine(dest); if (cinefile.sourcePath.StartsWith(bigPathBase)) { // Add node in file xdoc.DocumentElement.AppendChild(createNode(xdoc, cinefile.name)); } } } System.Console.WriteLine("done!"); // Add new files in patch dir to bigfile.xml System.Console.Write("Adding new files to \"bigfile.xml\"..."); xdoc.Save(outPath + "\\bigfile.xml"); System.Console.WriteLine("done!"); }
public static void doExtract(string[] args) { bool isBigEndian = false; LocaleID lang = LocaleID.Default; String bigfilePath = String.Empty; String patchPath = String.Empty; if (args.Length < 2) { Console.WriteLine("Error! Not enough arguments passed to program."); Console.WriteLine(""); showHelpAndQuit(); } else { if (args[1] == "help") { showHelpAndQuit(); } else if (args.Length < 3) { Console.WriteLine("Error! Not enough arguments passed to program."); Console.WriteLine(""); showHelpAndQuit(); } else if (args.Length > 5) { Console.WriteLine("Error! Too many arguments passed to program."); Console.WriteLine(""); showHelpAndQuit(); } else { lang = Locale.getFromString(args[1]); if (lang == LocaleID.Default) { Console.WriteLine("Error! Unknown language {0}", args[1]); Console.WriteLine(""); showHelpAndQuit(); } bigfilePath = args[2]; if (args.Length > 3) if (args[3] == "be") { isBigEndian = true; if (args.Length > 4) patchPath = args[4]; } else patchPath = args[3]; } } // Remove trailing backslash on paths if (bigfilePath.EndsWith("\\")) bigfilePath = bigfilePath.Remove(bigfilePath.Length - 1); if (patchPath.EndsWith("\\")) patchPath = patchPath.Remove(patchPath.Length - 1); // Get locale mask uint mask; if (patchPath != "") { uint mask2 = Locale.getLocaleMask(bigfilePath); mask = Locale.getLocaleMask(patchPath); if (mask2 != mask) throw new Exception("Patch and bigfile locale mask different"); } else mask = Locale.getLocaleMask(bigfilePath); if (mask == uint.MaxValue) { throw new Exception("Error finding localisation database (\"locals.bin\"). Make sure the game files are properly unpacked."); } else if (mask == (uint.MaxValue - 1)) { Console.WriteLine(""); Console.WriteLine("Unable to determine language of game files."); Console.WriteLine("Please confirm that the language {0} is supported by your game.", Locale.toString(lang)); Console.WriteLine("NOTE: If the language is not supported by the game, you won't see any changes!"); Console.Write("Confirm? (y/n)"); var yes = new ConsoleKeyInfo('y', ConsoleKey.Y, false, false, false); var no = new ConsoleKeyInfo('n', ConsoleKey.N, false, false, false); while (true) { var key = Console.ReadKey(true); if (key == no) System.Environment.Exit(0); else if (key == yes) break; } Console.WriteLine(""); } //Check if lang is present in files else if ((mask & (1 << (int)lang)) == 0) { Console.WriteLine(""); Console.WriteLine("Error! Language {0} not found in game files.", Locale.toString(lang)); Console.WriteLine(""); Console.WriteLine("Detected languages:"); for (int i = 0; i < 16; i++) { if((mask & (1 << i)) != 0) Console.WriteLine(Locale.toString((LocaleID)i)); } System.Environment.Exit(0); } TransFile tf = new TransFile(bigfilePath, patchPath, isBigEndian); var files = getFilelist(bigfilePath, patchPath, (int)lang, mask); System.Console.WriteLine("Searching following files for translatable text:"); int f = 0; foreach (string file in files) { System.Console.WriteLine("{0} of {1} - {2}", ++f, files.Count, Path.GetFileName(file)); if (file.EndsWith("locals.bin")) { LocalsFile lf = new LocalsFile(isBigEndian); lf.parse(file); string basep; string name; if (file.StartsWith(bigfilePath)) { basep = bigfilePath; name = file.Substring(bigfilePath.Length); } else { basep = patchPath; name = file.Substring(patchPath.Length); } tf.AddLocalsFile(lf, basep, name); } else { CineFile cf = new CineFile(isBigEndian); cf.parse(file); if (cf.isSubs()) { string basep; string name; if (file.StartsWith(bigfilePath)) { basep = bigfilePath; name = file.Substring(bigfilePath.Length); } else { basep = patchPath; name = file.Substring(patchPath.Length); } tf.AddFile(basep, name); List<SubtitleEntry> entries = cf.getSubtitles(); foreach (SubtitleEntry e in entries) { if (e.lang == lang) { tf.AddEntry(e.text, e.lang.ToString(), e.blockNumber.ToString()); } } } } } tf.Close(); System.Console.WriteLine("Translatable text saved to file \"translations.xml\""); }
private static void addLocalsFileNode(XPathNavigator current, out LocalsFile lf, bool isBigEndian) { string basepath = current.GetAttribute("base", ""); string name = current.GetAttribute("name", ""); lf = new LocalsFile(basepath, name, isBigEndian); lf.id = uint.Parse(current.GetAttribute("id", "")); uint index, offset; String entryText = ""; uint prevIndex = 0; uint lastOffset = 0; var entryNodes = current.Select("entry"); entryNodes.MoveNext(); prevIndex = uint.Parse(entryNodes.Current.GetAttribute("index", "")); lastOffset = uint.Parse(entryNodes.Current.GetAttribute("offset", "")); entryText = entryText + entryNodes.Current.Value; while (entryNodes.MoveNext() == true) { // Get index of entry index = uint.Parse(entryNodes.Current.GetAttribute("index", "")); offset = uint.Parse(entryNodes.Current.GetAttribute("offset", "")); if (prevIndex == index) { // this entry is the same as the last one, save the text with LF entryText = entryText + "\n" + entryNodes.Current.Value; continue; } // This entry is a new one, save last entry LocalsEntry e = new LocalsEntry(); e.index = prevIndex; e.offset = lastOffset; lastOffset += (uint)Encoding.UTF8.GetByteCount(entryText) + 1; /*if (lastOffset != offset) throw new Exception("Error loading locals.bin");*/ e.text = entryText; lf.entries.Add(e); // Save text of current entry entryText = entryNodes.Current.Value; prevIndex++; // If next entry is not sequential, we need to add empty entries while (index > prevIndex) { LocalsEntry fake = new LocalsEntry(); fake.index = prevIndex; fake.offset = 0; fake.text = ""; lf.entries.Add(fake); prevIndex++; } } // Write last entry LocalsEntry last = new LocalsEntry(); last.index = prevIndex; last.offset = lastOffset; last.text = entryText; lf.entries.Add(last); }
private static void addLocalsFileNode(XPathNavigator current, out LocalsFile lf, bool isBigEndian) { string basepath = current.GetAttribute("base", ""); string name = current.GetAttribute("name", ""); lf = new LocalsFile(basepath, name, isBigEndian); lf.id = uint.Parse(current.GetAttribute("id", "")); uint index, offset; String entryText = ""; uint prevIndex = 0; uint lastOffset = 0; var entryNodes = current.Select("entry"); entryNodes.MoveNext(); prevIndex = uint.Parse(entryNodes.Current.GetAttribute("index", "")); lastOffset = uint.Parse(entryNodes.Current.GetAttribute("offset", "")); entryText = entryText + entryNodes.Current.Value; while (entryNodes.MoveNext() == true) { // Get index of entry index = uint.Parse(entryNodes.Current.GetAttribute("index", "")); offset = uint.Parse(entryNodes.Current.GetAttribute("offset", "")); if (prevIndex == index) { // this entry is the same as the last one, save the text with LF entryText = entryText + "\n" + entryNodes.Current.Value; continue; } // This entry is a new one, save last entry LocalsEntry e = new LocalsEntry(); e.index = prevIndex; e.offset = lastOffset; lastOffset += (uint)Encoding.UTF8.GetByteCount(entryText) + 1; /*if (lastOffset != offset) * throw new Exception("Error loading locals.bin");*/ e.text = entryText; lf.entries.Add(e); // Save text of current entry entryText = entryNodes.Current.Value; prevIndex++; // If next entry is not sequential, we need to add empty entries while (index > prevIndex) { LocalsEntry fake = new LocalsEntry(); fake.index = prevIndex; fake.offset = 0; fake.text = ""; lf.entries.Add(fake); prevIndex++; } } // Write last entry LocalsEntry last = new LocalsEntry(); last.index = prevIndex; last.offset = lastOffset; last.text = entryText; lf.entries.Add(last); }