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();
                }
            }
Пример #2
0
        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);
        }
Пример #3
0
        //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");
            }
        }
Пример #4
0
        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;
            });
        }
Пример #5
0
        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);
            }
        }
Пример #8
0
        /// <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);
        }
Пример #9
0
        /// <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);
        }
Пример #10
0
 private static void FileIsUnsupported(string filePath, MBINFile mbin)
 {
     WarnBroken("File not supported."
                , filePath, mbin);
 }
Пример #11
0
 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);
 }
Пример #12
0
 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);
 }
Пример #13
0
 private static void  FileIsBroken(string filePath, MBINFile mbin) => _FileIsBroken(filePath, mbin, null);
Пример #14
0
        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);
        }
Пример #15
0
        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);
        }
Пример #16
0
        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();
        }
Пример #17
0
 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);
 }