public void Execute() { while (file != null) { GameDataMBIN.Record record = null; var path = Utils.AbsoluteToRelativePath(RunSettings.GameDataDir, file); bool skip = path.StartsWith("LANGUAGE\\"); skip |= path.EndsWith(".MBIN.PC"); if (!skip) { long size = new FileInfo(file).Length; string hash = Utils.SHA1.GetHexString(file); using (var mbin = new MBINFile(file)) { mbin.Load(); record = new GameDataMBIN.Record(path, size, hash, mbin.Header); } } file = onFinished(record); Thread.Yield(); } }
public override int ExecuteCommand(CommandLineParser options) { var files = options.GetFileParams(); if (files.Count == 0) { return(CommandLine.ShowVersion(Quiet)); } if (files.Count > 1) { return(CommandLine.ShowInvalidCommandLineArg(files[1])); } var fIn = new FileStream(files[0], FileMode.Open, FileAccess.Read); var mbin = new MBINFile(fIn); if (!mbin.Load() || !mbin.Header.IsValid) { return(CommandLine.ShowCommandLineError("Invalid file type.\n" + "Only MBIN files can be versioned.\n" + $"\"{files[0]}\"")); } CommandLine.ShowVersion(mbin, Quiet); return((int)ErrorCode.Success); }
//This is the function called when we click the loadMBIN button. public void LoadMBIN() { System.Windows.Forms.OpenFileDialog openFileDialog = new System.Windows.Forms.OpenFileDialog(); openFileDialog.Filter = "MBIN Files | *.mbin; *.MBIN"; if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { _mbinPath = openFileDialog.FileName; Debug.WriteLine(_mbinPath.ToString()); NMSTemplate template = null; using (MBINFile mbin = new MBINFile(_mbinPath)) { mbin.Load(); template = mbin.GetData(); } if (template != null) { //We now handle the formatting in this custom control, which is loaded into the MainWindowView when done. MBinViewer = new MBinViewModel(template); } } else { Debug.WriteLine("No MBIN Selected"); } }
private static void WarnBroken(string msg, string filePath, MBINFile mbin, NMSTemplate data = null, ulong expectedGUID = 0L) { #if ERROR_ON_BROKEN if (mbin != null) { throw new MbinException(msg, filePath, mbin); } throw new ExmlException(msg, filePath, data); #endif Async.SynchronizeTask(errorLock, ref errorTask, () => { warnedFiles.Add(filePath); warnings.Add(msg); if (Logger.LogStream.BaseStream.Position != lastPosition) { msg = $"\n{msg}"; } Logger.LogWarning($"{msg}"); using (var indentInfo = new Logger.IndentScope()) { Logger.LogMessage(false, Console.Out, null, ""); // newline, console only Logger.LogMessage(Console.Out, $"[INFO]: {filePath}"); if (mbin != null) { Logger.LogMessage(false, Console.Out, null, ""); // newline, console only Logger.LogMessage(null, "INFO", $"{CommandLine.GetFileInfo( mbin )}"); if (expectedGUID != 0L) { Logger.LogMessage(null, "EXPECTED INFO", $"GUID: {expectedGUID:X}\n"); } } //Logger.LogMessage( true, Console.Out, null, "" ); // newline, console and log } lastPosition = Logger.LogStream.BaseStream.Position; }); }
static void ExtractMBinFile(FileInfo inputFile, string outputFileName) { using var mbinFile = new MBINFile(inputFile.FullName); using var outputFile = File.Create(outputFileName); using var sw = new StreamWriter(outputFile); if (!(mbinFile.Load() && mbinFile.Header.IsValid)) { throw new InvalidDataException("Invalid File"); } var type = NMSTemplate.GetTemplateType(mbinFile.Header.GetXMLTemplateName()); if (type == null) { throw new NullReferenceException(); } var nms = (NMSAttribute)(type.GetCustomAttributes(typeof(NMSAttribute), false)?[0] ?? null); var broken = nms.Broken; // GUID's for the old files ulong[] UnsupportedGUIDs = new ulong[] { }; var mismatch = (mbinFile.Header.TemplateGUID != nms.GUID); bool unsupported = (UnsupportedGUIDs.Contains(mbinFile.Header.TemplateGUID)); if (broken) { var previousColour = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("File is broken"); Console.ForegroundColor = previousColour; } else if (unsupported) { var previousColour = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.DarkRed; Console.WriteLine("File is Unsupported"); Console.ForegroundColor = previousColour; } else if (mismatch) { var previousColour = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("File is Mismatched"); Console.ForegroundColor = previousColour; } var data = mbinFile.GetData(); sw.Write(EXmlFile.WriteTemplate(data)); sw.Flush(); }
/// <summary> /// Construct a new parallel MBIN file. /// </summary> /// <param name="sourceFile">The vanilla version of this MBIN file.</param> /// <param name="filesToMerge">A list of modified MBIN files that should have their contents merged.</param> /// <param name="vanillaPath">The path to the vanilla MBIN file.</param> /// <param name="mergePaths">The paths to all of the files being merged.</param> public MultiMBINEnumerator(MBINFile sourceFile, IEnumerable <MBINFile> filesToMerge, string vanillaPath, IEnumerable <string> mergePaths) { VanillaEXML = sourceFile.GetData().SerializeEXml(false); VanillaEXMLParented = ParentedEXmlObject.TransformEntireElementTree(VanillaEXML); VanillaPath = vanillaPath; ModEXMLs = new List <EXmlBase>(filesToMerge.Count()); ModEXMLsParented = new List <ParentedEXmlObject>(filesToMerge.Count()); ModPaths = mergePaths.ToList(); foreach (MBINFile file in filesToMerge) { EXmlBase data = file.GetData().SerializeEXml(false); ModEXMLs.Add(data); ModEXMLsParented.Add(ParentedEXmlObject.TransformEntireElementTree(data)); } }
public void TestMBINCompilerTemplate() { const string path = "../../MBINCompilerTestTemplate.MBIN"; var file = new MBINFile(path); file.Load(); Assert.AreEqual("MBINCompilerTestTemplate", file.Header.GetXMLTemplateName(), $"{path} header not using TemplateType MBINCompilerTestTemplate!"); var data = file.GetData(); Assert.IsNotNull(data, $"{path} deserialized data was null"); Assert.IsNotNull(data.SerializeEXml(false), $"{path} xml serialization was null"); Assert.IsInstanceOfType(data, typeof(MBINCompilerTestTemplate), $"{path} template isn't of type MBINCompilerTestTemplate!"); MBINCompilerTestTemplate test = (MBINCompilerTestTemplate)data; Assert.AreEqual(true, test.TestBoolTrue); Assert.AreEqual(false, test.TestBoolFalse); Assert.AreEqual(true, test.TestBool3); Assert.AreEqual(1337, test.TestInt16); Assert.AreEqual(2448, test.TestInt32); Assert.AreEqual(3559, test.TestInt64); Assert.AreEqual(1337.0, test.TestFloat); Assert.AreEqual(1, test.TestEnumYes); Assert.AreEqual(0, test.TestEnumNo); var expectedString = "SixteenByteStrng"; Assert.AreEqual(expectedString, test.TestString); var expectedDynamicString = "NoWayToControlItIt'sTotallyDynamicWheneverYou'reAround"; Assert.AreEqual(expectedDynamicString, test.TestDynamicString.Value); string[] expectedStrings = new[] { "FirstEntry", "SecondEntry", "ThirdEntry" }; Assert.AreEqual(expectedStrings.Length, test.Test0x80ByteStringList.Count); for (int i = 0; i < expectedStrings.Length; i++) { Assert.AreEqual(expectedStrings[i], test.Test0x80ByteStringList[i].Value); } }
/// <summary>Convert EXML to MBIN</summary> /// <param name="fIn">Source file</param> /// <param name="msOut">Output stream</param> /// <param name="fileOut">Output file path. Passed through as the return value. For geometry files, ".PC" will be appended.</param> /// <returns>fileOut</returns> private static string ConvertEXML(string inputPath, FileStream fIn, MemoryStream msOut, string fileOut) { string templateName; NMSTemplate data = null; try { data = EXmlFile.ReadTemplateFromStream(fIn, out templateName); Type type = NMSTemplate.GetTemplateType(templateName); var nms = (NMSAttribute)(data.GetType().GetCustomAttributes(typeof(NMSAttribute), false)?[0] ?? null); if (nms.Broken) { FileIsBroken(inputPath, data); } if (data is null) { throw new InvalidDataException($"Failed to deserialize EXML."); } if (data is libMBIN.NMS.Toolkit.TkGeometryData | data is libMBIN.NMS.Toolkit.TkGeometryStreamData) { fileOut += ".PC"; } var mbin = new MBINFile(msOut) { Header = new MBINHeader() }; mbin.Header.SetDefaults(data.GetType(), FormatVersion); mbin.SetData(data); mbin.Save(); } catch (Exception e) { throw new ExmlException(e, fIn.Name, data); } return(fileOut); }
/// <summary>Convert MBIN to EXML</summary> /// <param name="fIn">Source file</param> /// <param name="msOut">Output stream</param> /// <param name="fileOut">Output file path. Passed through as the return value. Not actually used.</param> /// <returns>fileOut</returns> private static string ConvertMBIN(string inputPath, FileStream fIn, MemoryStream msOut, string fileOut) { var mbin = new MBINFile(fIn); if (!(mbin.Load() && mbin.Header.IsValid)) { throw new InvalidDataException("Not a valid MBIN file!"); } var type = NMSTemplate.GetTemplateType(mbin.Header.GetXMLTemplateName()); var nms = (NMSAttribute)(type.GetCustomAttributes(typeof(NMSAttribute), false)?[0] ?? null); var broken = nms.Broken; // GUID's for the old files ulong[] UnsupportedGUIDs = new ulong[] { }; var mismatch = (mbin.Header.TemplateGUID != nms.GUID); bool unsupported = (UnsupportedGUIDs.Contains(mbin.Header.TemplateGUID)); //if ( broken && mismatch ) { // FileIsUnsupported( fIn.Name, mbin ); //} else if (broken) { FileIsBroken(inputPath, mbin); } else if (unsupported) { FileIsUnused(inputPath, mbin); } else if (mismatch) { FileIsUnrecognized(inputPath, mbin, nms.GUID); } var sw = new StreamWriter(msOut); NMSTemplate data = null; string msg = ""; try { msg = $"Failed to read {mbin.Header.GetXMLTemplateName()} from MBIN."; data = mbin.GetData(); if (data is null) { throw new InvalidDataException("Invalid MBIN data."); } msg = $"Failed serializing {mbin.Header.GetXMLTemplateName()} to EXML."; string exml = EXmlFile.WriteTemplate(data, HideVersionInfo); if (StreamToConsole) { EmitInfo($""); EmitInfo($"[INPUT]: {inputPath}"); EmitInfo($"{exml}"); } else { sw.Write(exml); sw.Flush(); if (msOut.Length == 0) { throw new InvalidDataException("Invalid EXML data."); } } } catch (Exception e) { throw new MbinException(msg, e, fIn.Name, mbin); } return(fileOut); }
private static void FileIsUnsupported(string filePath, MBINFile mbin) { WarnBroken("File not supported." , filePath, mbin); }
private static void FileIsUnrecognized(string filePath, MBINFile mbin, ulong expectedGUID = 0L) { WarnBroken("File not recognized. You may need to use an older (or newer) version of MBINCompiler." , filePath, mbin, null, expectedGUID); }
private static void FileIsUnused(string filePath, MBINFile mbin) { WarnBroken("This file is not supported by MBINCompiler as it is no longer used by the game. Do not report issues decompiling this file anywhere as it is not expected to." , filePath, mbin); }
private static void FileIsBroken(string filePath, MBINFile mbin) => _FileIsBroken(filePath, mbin, null);
private static bool AutoDetectFormat(ref List <string> fileList) { // detect what types of file formats are found bool foundMBIN = false; bool foundEXML = false; foreach (var file in fileList) { DetectFormat(file, ref foundMBIN, ref foundEXML); } // TODO: this should be handled better if (!foundMBIN && !foundEXML) { if ((fileList.Count == 1) && File.Exists(fileList[0])) { using (var fIn = new FileStream(fileList[0], FileMode.Open)) { // possibly MBIN? check for a valid header using (var mbin = new MBINFile(fIn, true)) foundMBIN = (mbin.Load() && mbin.Header.IsValid); if (!foundMBIN) // possibly EXML? check for a valid xml tag { var xmlTag = "<?xml version=\"1.0\" encoding=\"utf-8\"?>".ToLower(); var bytes = new byte[xmlTag.Length]; // TODO: handle potential leading whitespace? if (fIn.Read(bytes, 0, xmlTag.Length) == xmlTag.Length) { var txt = System.Text.Encoding.ASCII.GetString(bytes).ToLower(); foundEXML = (txt == xmlTag); } } } } } if (foundMBIN && foundEXML) { const string msg = "Unable to automatically determine the --input-format type."; if (Quiet) { return(CommandLine.ShowError(msg) == (int)ErrorCode.Success); } CommandLine.ShowWarning(msg); Console.Out.WriteLine("Both MBIN and EXML file types were detected!\n"); InputFormat = Utils.PromptInputFormat(); Console.WriteLine(); } else if (foundMBIN) { if (!StreamToConsole) { Logger.LogInfo("Auto-Detected --input-format=MBIN"); } InputFormat = FormatType.MBIN; } else if (foundEXML) { if (!StreamToConsole) { Logger.LogInfo("Auto-Detected --input-format=EXML"); } InputFormat = FormatType.EXML; } else { CommandLine.ShowError("No valid files found!"); return(false); } OutputFormat = (InputFormat == FormatType.MBIN) ? FormatType.EXML : FormatType.MBIN; Logger.LogMessage("INFO", $"--input-format={InputFormat} --output-format={OutputFormat}"); // exclude any files that don't match InputFormat for (int i = fileList.Count - 1; i >= 0; i--) { var ext = Path.GetExtension(fileList[i]).ToUpper(); if (ext == ".PC") { ext = Path.GetExtension(Path.ChangeExtension(fileList[i], null)).ToUpper(); } if (ext.Substring(1) != InputFormat.ToString()) { fileList.RemoveAt(i); } } return(true); }
public static NMSTemplate LoadNMSTemplate(string filepath, ref ResourceManager resMgr) { int load_mode = 0; NMSTemplate template = null; filepath = filepath.Replace('\\', '/'); string effective_filepath = filepath; //Checks to prevent malformed paths from further processing if (filepath.Contains(' ')) { return(null); } string exmlpath = Path.ChangeExtension(filepath, "exml"); exmlpath = exmlpath.ToUpper(); //Make upper case if (File.Exists(Path.Combine(RenderState.settings.UnpackDir, exmlpath))) { load_mode = 0; //Load Exml } else if (File.Exists(Path.Combine(RenderState.settings.UnpackDir, filepath))) { load_mode = 1; //Load MBIN from file } else if (resMgr.NMSFileToArchiveMap.ContainsKey(filepath)) { load_mode = 2; //Extract file from archive } else if (resMgr.NMSFileToArchiveMap.ContainsKey("/" + filepath)) //AMUMSS BULLSHIT { effective_filepath = "/" + filepath; load_mode = 2; //Extract file from archive } else { CallBacks.Log("File: " + filepath + " Not found in PAKs or local folders. "); Util.showError("File: " + filepath + " Not found in PAKs or local folders. ", "Error"); return(null); } try { switch (load_mode) { case 0: //Load EXML { string xml = File.ReadAllText(Path.Combine(RenderState.settings.UnpackDir, exmlpath)); template = EXmlFile.ReadTemplateFromString(xml); break; } case 1: //Load MBIN { string eff_path = Path.Combine(RenderState.settings.UnpackDir, filepath); MBINFile mbinf = new MBINFile(eff_path); mbinf.Load(); template = mbinf.GetData(); mbinf.Dispose(); break; } case 2: //Load File from Archive { Stream file = resMgr.NMSFileToArchiveMap[effective_filepath].ExtractFile(effective_filepath); MBINFile mbinf = new MBINFile(file); mbinf.Load(); template = mbinf.GetData(); mbinf.Dispose(); break; } } } catch (Exception ex) { if (ex is System.IO.DirectoryNotFoundException || ex is System.IO.FileNotFoundException) { Util.showError("File " + effective_filepath + " Not Found...", "Error"); } else if (ex is System.IO.IOException) { Util.showError("File " + effective_filepath + " problem...", "Error"); } else if (ex is System.Reflection.TargetInvocationException) { Util.showError("libMBIN failed to decompile file. If this is a vanilla file, contact the MbinCompiler developer", "Error"); } else { Util.showError("Unhandled Exception " + ex.Message, "Error"); } return(null); } #if DEBUG //Save NMSTemplate to exml string data = EXmlFile.WriteTemplate(template); string path = Path.Combine("Temp", filepath + ".exml"); Directory.CreateDirectory(Path.GetDirectoryName(path)); File.WriteAllText(path, data); #endif return(template); }
static void Init(string[] args) { Console.ForegroundColor = ConsoleColor.Green; string vanillaMBINPath = null; List <string> patchFiles = new List <string>(); // [0] = vanilla file // [1] = custom file 1 // [2] = custom file 2 // [...] = ... if (args.Length < 3) { PopulateDirectoryInfo(out vanillaMBINPath, out patchFiles); } else { vanillaMBINPath = args[0]; if (!File.Exists(vanillaMBINPath)) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("ERROR: The file you input does not exist!"); Console.ForegroundColor = ConsoleColor.DarkRed; Console.WriteLine("Failed to find: " + vanillaMBINPath); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Press enter to quit..."); Console.ReadLine(); return; } foreach (string data in args.Skip(1)) { if (!File.Exists(data)) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("ERROR: The file you input does not exist!"); Console.ForegroundColor = ConsoleColor.DarkRed; Console.WriteLine("Failed to find: " + data); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Press enter to quit..."); Console.ReadLine(); return; } patchFiles.Add(data); } } Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Loading up all of the MBIN files..."); FileStream vanillaMBIN = File.OpenRead(vanillaMBINPath); FileStream[] otherMBINs = new FileStream[patchFiles.Count]; for (int idx = 0; idx < patchFiles.Count; idx++) { otherMBINs[idx] = File.OpenRead(patchFiles[idx]); } Console.ForegroundColor = ConsoleColor.DarkGreen; Console.WriteLine("Processing MBIN File: {0}", vanillaMBINPath); MBINFile[] otherBnkObjects = new MBINFile[otherMBINs.Length]; MBINFile vanillaFile = new MBINFile(vanillaMBIN); vanillaFile.Load(); for (int idx = 0; idx < otherBnkObjects.Length; idx++) { Console.ForegroundColor = ConsoleColor.DarkGreen; Console.WriteLine("Processing MBIN File: {0}", patchFiles[idx]); MBINFile newFile = new MBINFile(otherMBINs[idx]); newFile.Load(); otherBnkObjects[idx] = newFile; } Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Done processing MBIN files! Enumerating... Please be present so that you may resolve any file conflicts."); MultiMBINEnumerator iterator = new MultiMBINEnumerator(vanillaFile, otherBnkObjects, vanillaMBINPath, patchFiles); EXmlData newData = iterator.PatchEverything(); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Done enumerating BNK files! Saving in the same directory as the EXE..."); string name = "MergedMBIN-" + DateTime.Now.ToFileTimeUtc().ToString() + ".MBIN"; //FileStream save = File.OpenWrite(@".\" + name); // Since the MBINFile class refuses to populate the data properly (Am I just not getting how to use it? Ech.) // It kept throwing null pointer exceptions when I called SetData. wtf? // Edit: Turns out I have to specify the header myself. wat. // Monkey if you're reading this, I love you nohomo it's just this is written really awkwardly and I'm not used to it. using (MBINFile outFile = new MBINFile(@".\" + name)) { NMSTemplate template = NMSTemplate.DeserializeEXml(newData); MBINHeader header = new MBINHeader(); header.SetDefaults(); outFile.Header = header; outFile.SetData(template); outFile.Save(); } vanillaMBIN.Dispose(); foreach (FileStream str in otherMBINs) { str.Dispose(); } Console.Write("Saved as "); Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine(name); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Press enter to quit."); Console.ReadLine(); }
private static void _FileIsBroken(string filePath, MBINFile mbin, NMSTemplate data) { WarnBroken("There are known issues with this file in the current version of MBINCompiler." , filePath, mbin, data); }