コード例 #1
0
ファイル: Reanimator.cs プロジェクト: dragnilar/reanimator
        private void _OpenXmlFile(String filePath)
        {
            byte[] xmlCookedBytes;
            try
            {
                xmlCookedBytes = File.ReadAllBytes(filePath);
            }
            catch (Exception e)
            {
                MessageBox.Show("Failed to read in file!\n\n" + e, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            XmlCookedFile xmlCookedFile = new XmlCookedFile(_fileManager);

            try
            {
                xmlCookedFile.ParseFileBytes(xmlCookedBytes, true);
            }
            catch (Exception e)
            {
                MessageBox.Show("Failed to uncook xml file!\n" + e, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            String xmlPath = filePath.Replace(".cooked", "");

            try
            {
                xmlCookedFile.SaveXmlDocument(xmlPath);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Failed to save uncooked xml file!\n\n" + ex, "Error", MessageBoxButtons.OK,
                                MessageBoxIcon.Error);
                return;
            }

            try
            {
                Process process = new Process {
                    StartInfo = { FileName = Config.XmlEditor, Arguments = xmlPath }
                };
                process.Start();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Failed to start default XML Editor.\n" + ex, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
コード例 #2
0
ファイル: Program.cs プロジェクト: dragnilar/reanimator
        public static void CookXmlFile(String xmlPath, FileManager fileManager)
        {
            try
            {
                Console.WriteLine(String.Format("Cooking {0}", Path.GetFileNameWithoutExtension(xmlPath)));

                XmlDocument xmlDocument = new XmlDocument();
                xmlDocument.Load(xmlPath);

                XmlCookedFile cookedXmlFile = new XmlCookedFile(fileManager, xmlPath);
                byte[]        xmlCookedData = cookedXmlFile.CookXmlDocument(xmlDocument);
                File.WriteAllBytes(xmlPath + ".cooked", xmlCookedData);
            }
            catch (Exception ex)
            {
                String error = "Error: Failed to cook XML file: " + ex.Message;
                ExceptionLogger.LogException(ex, error);
                Console.WriteLine(error);
            }
        }
コード例 #3
0
ファイル: TestScripts.cs プロジェクト: khadoran/reanimator
        public static void TestAllXml(bool doTCv4 = false)
        {
            //System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
            //const String root = @"D:\Games\Hellgate\Data\";
            //const String root = @"D:\Games\Hellgate London\data\mp_hellgate_1.10.180.3416_1.0.86.4580\";
            //const String root = @"D:\Games\Hellgate London\data\mp_hellgate_1.10.180.3416_1.0.86.4580\data\background\";
            //List<String> xmlFiles = new List<String>(Directory.GetFiles(root, "*.xml.cooked", SearchOption.AllDirectories));

            String debugPath = @"C:\xml_debug\";
            FileManager.ClientVersions clientVersion = FileManager.ClientVersions.SinglePlayer;
            if (doTCv4)
            {
                debugPath = Path.Combine(debugPath, "tcv4");
                clientVersion = FileManager.ClientVersions.TestCenter;
            }
            debugPath += @"\"; // lazy
            Directory.CreateDirectory(debugPath);

            FileManager fileManager = new FileManager(Config.HglDir, clientVersion);
            fileManager.BeginAllDatReadAccess();
            fileManager.LoadTableFiles();

            int count = 0;
            List<XmlCookedFile> excelStringWarnings = new List<XmlCookedFile>();
            List<String> testCentreWarnings = new List<String>();
            List<String> resurrectionWarnings = new List<String>();
            int i = 0;
            foreach (PackFileEntry fileEntry in fileManager.FileEntries.Values)
            {
                if (!fileEntry.Path.EndsWith(XmlCookedFile.Extension)) continue;

                String xmlFilePath = fileEntry.Path;

                //const String debugStr = "buildintx_inside_env";
                //if (!xmlFilePath.Contains(debugStr)) continue;
                //if (xmlFilePath.Contains(debugStr))
                //{
                //    int bp = 0;
                //}

                //foreach (String xmlFilePath in xmlFiles)
                //{
                //bool skip = ((i++ % 23) > 0);
                //if (skip)
                //{
                //    if (xmlFilePath.Contains("\\Data\\colorsets.xml")) continue;
                //    if (xmlFilePath.Contains("\\Data\\ai\\")) continue;
                //    if (xmlFilePath.Contains("\\Data\\background\\")) continue;
                //    if (xmlFilePath.Contains("\\Data\\demolevel\\")) continue;
                //    if (xmlFilePath.Contains("\\Data\\lights\\")) continue;
                //    if (xmlFilePath.Contains("\\Data\\materials\\")) continue;
                //    if (xmlFilePath.Contains("\\Data\\particles\\")) continue;
                //    if (xmlFilePath.Contains("\\Data\\screenfx\\")) continue;
                //    if (xmlFilePath.Contains("\\Data\\skills\\")) continue;
                //    if (xmlFilePath.Contains("\\Data\\sounds\\")) continue;
                //    if (xmlFilePath.Contains("\\Data\\states\\")) continue;
                //    if (xmlFilePath.Contains("\\Data\\units\\items\\")) continue;
                //    if (xmlFilePath.Contains("\\Data\\units\\missiles\\")) continue;
                //    if (xmlFilePath.Contains("\\Data\\units\\monsters\\")) continue;
                //    if (xmlFilePath.Contains("\\Data\\units\\npc\\")) continue;
                //    if (xmlFilePath.Contains("\\Data\\units\\objects\\")) continue;
                //}

                String path = xmlFilePath;
                String fileName = Path.GetFileName(path);
                Debug.Assert(!String.IsNullOrEmpty(fileName));
                //path = @"D:\Games\Hellgate London\data\mp_hellgate_1.10.180.3416_1.0.86.4580\data\background\city\treasury\cap_path.xml.cooked";
                //path = "D:\\Games\\Hellgate\\Data\\background\\_environments\\outdoor_redhellcow_env.xml.cooked";
                //path = "D:\\Games\\Hellgate\\Data\\particles\\background\\t_background\\tokyo_dark_smoke_c_large_01.xml.cooked";
                //if (path == @"D:\Games\Hellgate\Data\background\cans and boxes.xml.cooked")
                //{
                //    int bp = 0;
                //}

                XmlCookedFile xmlCookedFile = new XmlCookedFile(fileManager, fileName) { CookExcludeTestCentre = !doTCv4 };
                byte[] data = fileManager.GetFileBytes(fileEntry);
                Debug.Assert(data != null && data.Length > 0);

                Console.Write("Uncooking " + fileName + "... ");

                try
                {
                    xmlCookedFile.ParseFileBytes(data, true);
                }
                catch (Exception e)
                {
                    File.WriteAllBytes(debugPath + fileName, data);
                    Console.WriteLine("Failed to uncooked file \"" + path + "\"\n" + e + "\n");
                    continue;
                }

                byte[] newXmlBytes = xmlCookedFile.ExportAsDocument();
                count++;

                if (xmlCookedFile.HasExcelStringsMissing) excelStringWarnings.Add(xmlCookedFile);
                if (xmlCookedFile.HasTestCentreElements) testCentreWarnings.Add(Path.GetFileName(fileName));
                if (xmlCookedFile.HasResurrectionElements) resurrectionWarnings.Add(Path.GetFileName(fileName));
                //if (xmlCookedFile.HasExcelStringsMissing || xmlCookedFile.HasTestCentreElements || xmlCookedFile.HasResurrectionElements) continue;

                XmlCookedFile recookedXmlFile = new XmlCookedFile(fileManager, fileName) { CookExcludeTestCentre = !doTCv4 };
                byte[] newXmlCookedBytes = recookedXmlFile.ParseFileBytes(newXmlBytes);

                // check if *cooking method* is working. i.e. is the cook from the *new* XML format == the original cooked
                bool identicalNew = data.SequenceEqual(newXmlCookedBytes);

                // if file passes byte-byte test, then continue
                if (identicalNew)
                {
                    Console.WriteLine("OK!");
                    continue;
                }

                if (
                path.Contains("female_3p_appearance.xml") ||            // this file has some weird bytes in a string element
                path.Contains("focus_item12_mesh_appearance.xml") ||    // this file has non-zeroed flag base masks (all differing)
                path.Contains("focus_item10_mesh_appearance.xml") ||    // as above     // (all 3 probably from not zeroing a ptr at original cooking)
                path.Contains("dof_test.xml") ||                        // as above
                path.Contains("motionblur.xml") ||                      // as above
                    path.Contains("player dead.xml")
                 )
                {
                    Console.WriteLine("OK!");
                    continue;
                }

                File.WriteAllBytes(debugPath + fileName, data);
                File.WriteAllBytes(debugPath + fileName + "recooked", newXmlCookedBytes);
                File.WriteAllBytes(debugPath + fileName.Replace(".cooked", ""), newXmlBytes);

                Console.WriteLine("FAILED!");
            }

            TextWriter consoleOut = Console.Out;
            TextWriter textWriter = new StreamWriter("uncook_results.txt");
            Console.SetOut(textWriter);
            Console.WriteLine("XML Files Uncooked: " + count);
            if (excelStringWarnings.Count > 0)
            {
                Console.WriteLine("Warning: " + excelStringWarnings.Count + " files had excel strings missing:");
                foreach (XmlCookedFile xmlCookedFile in excelStringWarnings)
                {
                    Console.WriteLine("\t" + xmlCookedFile.FileName);
                    foreach (String str in xmlCookedFile.ExcelStringsMissing) Console.WriteLine("\t\t- \"" + str + "\"");
                }
            }
            if (testCentreWarnings.Count > 0)
            {
                Console.WriteLine("Warning: " + testCentreWarnings.Count + " files had TestCentre-specific elements:");
                foreach (String str in testCentreWarnings) Console.WriteLine("\t" + str);
            }
            if (resurrectionWarnings.Count > 0)
            {
                Console.WriteLine("Warning: " + resurrectionWarnings.Count + " files had Resurrection-specific elements:");
                foreach (String str in resurrectionWarnings) Console.WriteLine("\t" + str);
            }
            textWriter.Close();
            Console.SetOut(consoleOut);
        }
コード例 #4
0
        /// <summary>
        /// User-friendly uncooking of Tree Node list.
        /// </summary>
        /// <param name="progressForm">A progress form to update.</param>
        /// <param name="param">The Tree Node List.</param>
        private void _DoUnooking(ProgressForm progressForm, Object param)
        {
            List<TreeNode> uncookingNodes = (List<TreeNode>)param;
            const int progressUpdateFreq = 20;
            if (progressForm != null)
            {
                progressForm.ConfigBar(1, uncookingNodes.Count, progressUpdateFreq);
            }

            int i = 0;
            foreach (TreeNode treeNode in uncookingNodes)
            {
                NodeObject nodeObject = (NodeObject)treeNode.Tag;
                PackFileEntry fileEntry = nodeObject.FileEntry;

                // update progress if applicable
                if (i % progressUpdateFreq == 0 && progressForm != null)
                {
                    progressForm.SetCurrentItemText(fileEntry.Path);
                }
                i++;

                // get the file bytes
                String relativePath = fileEntry.Path;
                byte[] fileBytes;
                try
                {
                    fileBytes = _fileManager.GetFileBytes(fileEntry, true);
                    if (fileBytes == null) continue;
                }
                catch (Exception e)
                {
                    ExceptionLogger.LogException(e);
                    continue;
                }

                // determine file type
                HellgateFile hellgateFile;
                if (relativePath.EndsWith(XmlCookedFile.Extension))
                {
                    hellgateFile = new XmlCookedFile(_fileManager);
                }
                else if (relativePath.EndsWith(RoomDefinitionFile.Extension))
                {
                    hellgateFile = new RoomDefinitionFile(relativePath);
                }
                else if (relativePath.EndsWith(MLIFile.Extension))
                {
                    hellgateFile = new MLIFile();
                }
                else
                {
                    Debug.Assert(false, "wtf");
                    continue;
                }

                // deserialise file
                DialogResult dr = DialogResult.Retry;
                bool uncooked = false;
                while (dr == DialogResult.Retry && !uncooked)
                {
                    try
                    {
                        hellgateFile.ParseFileBytes(fileBytes);
                        uncooked = true;
                    }
                    catch (Exception e)
                    {
                        ExceptionLogger.LogException(e, true);

                        String errorMsg = String.Format("Failed to uncooked file!\n{0}\n\n{1}", relativePath, e);
                        dr = MessageBox.Show(errorMsg, "Error", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Exclamation);
                        if (dr == DialogResult.Abort) return;
                        if (dr == DialogResult.Ignore) break;
                    }
                }
                if (!uncooked) continue;

                // save file
                String relativeSavePath = relativePath.Replace(HellgateFile.Extension, HellgateFile.ExtensionDeserialised);
                String savePath = Path.Combine(Config.HglDir, relativeSavePath);

                dr = DialogResult.Retry;
                bool saved = false;
                byte[] documentBytes = null;
                while (dr == DialogResult.Retry && !saved)
                {
                    try
                    {
                        if (documentBytes == null) documentBytes = hellgateFile.ExportAsDocument();
                        File.WriteAllBytes(savePath, documentBytes);
                        saved = true;
                    }
                    catch (Exception e)
                    {
                        ExceptionLogger.LogException(e, true);

                        String errorMsg = String.Format("Failed to save file!\n{0}\n\n{1}", relativePath, e);
                        dr = MessageBox.Show(errorMsg, "Error", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Exclamation);
                        if (dr == DialogResult.Abort) return;
                        if (dr == DialogResult.Ignore) break;
                    }
                }

                // update tree view
                TreeNode newTreeNode = new TreeNode();
                NodeObject newNodeObject = new NodeObject
                {
                    CanEdit = true,
                    IsUncookedVersion = true
                };
                newTreeNode.Tag = newNodeObject;
                treeNode.Nodes.Add(newTreeNode);
            }
        }
コード例 #5
0
ファイル: Reanimator.cs プロジェクト: khadoran/reanimator
        private void _OpenXmlFile(String filePath)
        {
            byte[] xmlCookedBytes;
            try
            {
                xmlCookedBytes = File.ReadAllBytes(filePath);
            }
            catch (Exception e)
            {
                MessageBox.Show("Failed to read in file!\n\n" + e, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            XmlCookedFile xmlCookedFile = new XmlCookedFile(_fileManager);
            try
            {
                xmlCookedFile.ParseFileBytes(xmlCookedBytes, true);
            }
            catch (Exception e)
            {
                MessageBox.Show("Failed to uncook xml file!\n" + e, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            String xmlPath = filePath.Replace(".cooked", "");
            try
            {
                xmlCookedFile.SaveXmlDocument(xmlPath);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Failed to save uncooked xml file!\n\n" + ex, "Error", MessageBoxButtons.OK,
                                MessageBoxIcon.Error);
                return;
            }

            try
            {
                Process process = new Process { StartInfo = { FileName = Config.XmlEditor, Arguments = xmlPath } };
                process.Start();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Failed to start default XML Editor.\n" + ex, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
コード例 #6
0
ファイル: FileExplorer.cs プロジェクト: khadoran/reanimator
        private void _DoCooking(ProgressForm progressForm, Object param)
        {
            List<TreeNode> cookNodes = (List<TreeNode>)param;
            const int progressUpdateFreq = 20;
            if (progressForm != null)
            {
                progressForm.ConfigBar(1, cookNodes.Count, progressUpdateFreq);
            }

            int i = 0;
            //foreach (String nodeFullPath in cookNodes.Select(treeNode => treeNode.FullPath))
            foreach (TreeNode treeNode in cookNodes)
            {
                TreeNode cookedNode = treeNode.Parent;
                String nodeFullPath = cookedNode.FullPath.Replace(".cooked", "");
                String filePath = Path.Combine(Config.HglDir, nodeFullPath);
                Debug.Assert(filePath.EndsWith(".xml"));

                if (i % progressUpdateFreq == 0 && progressForm != null)
                {
                    progressForm.SetCurrentItemText(filePath);
                }
                i++;

                //if (nodeFullPath.Contains("actor_ghost.xml"))
                //{
                //    int bp = 0;
                //}

                if (!File.Exists(filePath)) continue;
                XmlDocument xmlDocument = new XmlDocument();
                XmlCookedFile cookedXmlFile = new XmlCookedFile(_fileManager);

                DialogResult dr = DialogResult.Retry;
                byte[] cookedBytes = null;
                while (dr == DialogResult.Retry && cookedBytes == null)
                {
                    try
                    {
                        xmlDocument.Load(filePath);
                        cookedBytes =  cookedXmlFile.CookXmlDocument(xmlDocument);
                    }
                    catch (Exception e)
                    {
                        ExceptionLogger.LogException(e, true);

                        String errorMsg = String.Format("Failed to cook file!\n{0}\n\n{1}", nodeFullPath, e);
                        dr = MessageBox.Show(errorMsg, "Error",
                                             MessageBoxButtons.AbortRetryIgnore,
                                             MessageBoxIcon.Exclamation);
                        if (dr == DialogResult.Abort) return;
                        if (dr == DialogResult.Ignore) break;
                    }
                }

                if (cookedBytes == null) continue;

                // todo: update newly cooked file to file tree
                String savePath = Path.Combine(Config.HglDir, filePath + ".cooked");
                File.WriteAllBytes(savePath, cookedBytes);

                // debug section
                //String savePath2 = Path.Combine(Config.HglDir, filePath + ".cooked2");
                //File.WriteAllBytes(savePath2, cookedBytes);
                //byte[] origBytes = File.ReadAllBytes(savePath);

                //if (cookedBytes.Length != origBytes.Length)
                //{
                //    int bp = 0;
                //}

                //if (!origBytes.SequenceEqual(cookedBytes))
                //{
                //    int bp = 0;
                //}
            }
        }
コード例 #7
0
ファイル: FileExplorer.cs プロジェクト: khadoran/reanimator
        private void _QuickXmlWorker(ProgressForm progressForm, Object param)
        {
            const int progressStepRate = 50;
            const String outputResultsName = "uncook_results.txt";
            ExtractPackPatchArgs extractPatchArgs = (ExtractPackPatchArgs)param;

            TextWriter consoleOut = Console.Out;
            TextWriter textWriter = new StreamWriter(outputResultsName);
            Console.SetOut(textWriter);
            Console.WriteLine("Results of most recent uncooking of .xml.cooked files. Please scroll to end for tallied results.");

            // get all .xml.cooked
            List<PackFileEntry> xmlCookedFiles = _fileManager.FileEntries.Values.Where(fileEntry => fileEntry.Name.EndsWith(XmlCookedFile.Extension)).ToList();
            _fileManager.BeginAllDatReadAccess();

            // loop through file entries
            int count = xmlCookedFiles.Count();
            progressForm.ConfigBar(1, count, progressStepRate);
            progressForm.SetLoadingText("Extracting and uncooking .xml.cooked files... (" + count + ")");
            int i = 0;
            int uncooked = 0;
            int readFailed = 0;
            int uncookFailed = 0;
            int testCentreWarnings = 0;
            int resurrectionWarnings = 0;
            int excelWarnings = 0;
            foreach (PackFileEntry fileEntry in xmlCookedFiles)
            {
                // update progress
                if (i % progressStepRate == 0)
                {
                    progressForm.SetCurrentItemText(fileEntry.Path);
                }
                i++;

                // get file and uncook
                Console.WriteLine(fileEntry.Path);
                byte[] fileBytes;
                XmlCookedFile xmlCookedFile = new XmlCookedFile(_fileManager);

                try
                {
                    fileBytes = _fileManager.GetFileBytes(fileEntry);
                }
                catch (Exception)
                {
                    Console.WriteLine("Error: FileManager failed to read file!\n");
                    readFailed++;
                    continue;
                }

                try
                {
                    xmlCookedFile.ParseFileBytes(fileBytes, true);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.ToString());
                    Console.WriteLine("Warning: Failed to uncook file: " + fileEntry.Name + "\n");
                    uncookFailed++;
                    continue;
                }

                // did we have any uncooking issues?
                bool hadWarning = false;
                if (xmlCookedFile.HasTestCentreElements)
                {
                    Console.WriteLine("Warning: File has TestCentre-specific elements.");
                    hadWarning = true;
                    testCentreWarnings++;
                }
                if (xmlCookedFile.HasResurrectionElements)
                {
                    Console.WriteLine("Warning: File has Resurrection-specific elements.");
                    hadWarning = true;
                    resurrectionWarnings++;
                }
                if (xmlCookedFile.HasExcelStringsMissing)
                {
                    Console.WriteLine("Warning: File has " + xmlCookedFile.ExcelStringsMissing.Count + " unknown excel strings: ");
                    foreach (String str in xmlCookedFile.ExcelStringsMissing) Console.WriteLine("\t- \"" + str + "\"");
                    hadWarning = true;
                    excelWarnings++;
                }

                // save file
                String savePath = Path.Combine(extractPatchArgs.RootDir, fileEntry.Path);
                Directory.CreateDirectory(Path.GetDirectoryName(savePath));

                try
                {
                    xmlCookedFile.SaveXmlDocument(savePath.Replace(".cooked", ""));
                }
                catch (Exception)
                {
                    Console.WriteLine("Warning: Failed to save XML file: " + savePath + "\n");
                    continue;
                }

                if (hadWarning) Console.WriteLine();
                uncooked++;
            }

            _fileManager.EndAllDatAccess();

            // output final results
            Console.WriteLine("\nXML Files Uncooked: " + uncooked);
            if (readFailed > 0) Console.WriteLine(readFailed + " file(s) could not be read from the data files.");
            if (uncookFailed > 0) Console.WriteLine(uncookFailed + " file(s) failed to uncook at all.");
            if (testCentreWarnings > 0) Console.WriteLine(testCentreWarnings + " file(s) had TestCentre-specific XML elements which wont be included when recooked.");
            if (resurrectionWarnings > 0) Console.WriteLine(resurrectionWarnings + " file(s) had Resurrection-specific XML elements which wont be included when recooked.");
            if (excelWarnings > 0) Console.WriteLine(excelWarnings + " file(s) had excel warnings and cannot be safely recooked.");
            textWriter.Close();
            Console.SetOut(consoleOut);

            try
            {
                Process process = new Process { StartInfo = { FileName = Config.TxtEditor, Arguments = outputResultsName } };
                process.Start();
            }
            catch (Exception e)
            {
                MessageBox.Show(
                    "Failed to open results!\nThe " + outputResultsName + " can be found in your Reanimator folder.\n" +
                    e, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
コード例 #8
0
ファイル: Program.cs プロジェクト: khadoran/reanimator
        public static void CookXmlFile(String xmlPath, FileManager fileManager)
        {
            try
            {
                Console.WriteLine(String.Format("Cooking {0}", Path.GetFileNameWithoutExtension(xmlPath)));

                XmlDocument xmlDocument = new XmlDocument();
                xmlDocument.Load(xmlPath);

                XmlCookedFile cookedXmlFile = new XmlCookedFile(fileManager, xmlPath);
                byte[] xmlCookedData = cookedXmlFile.CookXmlDocument(xmlDocument);
                File.WriteAllBytes(xmlPath + ".cooked", xmlCookedData);
            }
            catch (Exception ex)
            {
                String error = "Error: Failed to cook XML file: " + ex.Message;
                ExceptionLogger.LogException(ex, error);
                Console.WriteLine(error);
            }
        }
コード例 #9
0
        /// <summary>
        /// User-friendly uncooking of Tree Node list.
        /// </summary>
        /// <param name="progressForm">A progress form to update.</param>
        /// <param name="param">The Tree Node List.</param>
        private void _DoUnooking(ProgressForm progressForm, Object param)
        {
            List <TreeNode> uncookingNodes     = (List <TreeNode>)param;
            const int       progressUpdateFreq = 20;

            if (progressForm != null)
            {
                progressForm.ConfigBar(1, uncookingNodes.Count, progressUpdateFreq);
            }

            int i = 0;

            foreach (TreeNode treeNode in uncookingNodes)
            {
                NodeObject    nodeObject = (NodeObject)treeNode.Tag;
                PackFileEntry fileEntry  = nodeObject.FileEntry;


                // update progress if applicable
                if (i % progressUpdateFreq == 0 && progressForm != null)
                {
                    progressForm.SetCurrentItemText(fileEntry.Path);
                }
                i++;


                // get the file bytes
                String relativePath = fileEntry.Path;
                byte[] fileBytes;
                try
                {
                    fileBytes = _fileManager.GetFileBytes(fileEntry, true);
                    if (fileBytes == null)
                    {
                        continue;
                    }
                }
                catch (Exception e)
                {
                    ExceptionLogger.LogException(e);
                    continue;
                }


                // determine file type
                HellgateFile hellgateFile;
                if (relativePath.EndsWith(XmlCookedFile.Extension))
                {
                    hellgateFile = new XmlCookedFile(_fileManager);
                }
                else if (relativePath.EndsWith(RoomDefinitionFile.Extension))
                {
                    hellgateFile = new RoomDefinitionFile(relativePath);
                }
                else if (relativePath.EndsWith(MLIFile.Extension))
                {
                    hellgateFile = new MLIFile();
                }
                else
                {
                    Debug.Assert(false, "wtf");
                    continue;
                }


                // deserialise file
                DialogResult dr       = DialogResult.Retry;
                bool         uncooked = false;
                while (dr == DialogResult.Retry && !uncooked)
                {
                    try
                    {
                        hellgateFile.ParseFileBytes(fileBytes);
                        uncooked = true;
                    }
                    catch (Exception e)
                    {
                        ExceptionLogger.LogException(e, true);

                        String errorMsg = String.Format("Failed to uncooked file!\n{0}\n\n{1}", relativePath, e);
                        dr = MessageBox.Show(errorMsg, "Error", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Exclamation);
                        if (dr == DialogResult.Abort)
                        {
                            return;
                        }
                        if (dr == DialogResult.Ignore)
                        {
                            break;
                        }
                    }
                }
                if (!uncooked)
                {
                    continue;
                }


                // save file
                String relativeSavePath = relativePath.Replace(HellgateFile.Extension, HellgateFile.ExtensionDeserialised);
                String savePath         = Path.Combine(Config.HglDir, relativeSavePath);

                dr = DialogResult.Retry;
                bool   saved         = false;
                byte[] documentBytes = null;
                while (dr == DialogResult.Retry && !saved)
                {
                    try
                    {
                        if (documentBytes == null)
                        {
                            documentBytes = hellgateFile.ExportAsDocument();
                        }
                        File.WriteAllBytes(savePath, documentBytes);
                        saved = true;
                    }
                    catch (Exception e)
                    {
                        ExceptionLogger.LogException(e, true);

                        String errorMsg = String.Format("Failed to save file!\n{0}\n\n{1}", relativePath, e);
                        dr = MessageBox.Show(errorMsg, "Error", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Exclamation);
                        if (dr == DialogResult.Abort)
                        {
                            return;
                        }
                        if (dr == DialogResult.Ignore)
                        {
                            break;
                        }
                    }
                }


                // update tree view
                TreeNode   newTreeNode   = new TreeNode();
                NodeObject newNodeObject = new NodeObject
                {
                    CanEdit           = true,
                    IsUncookedVersion = true
                };
                newTreeNode.Tag = newNodeObject;
                treeNode.Nodes.Add(newTreeNode);
            }
        }