private void LoadFile(string fileName) { string lowerFilename = Path.GetExtension(fileName).ToLower(); if (lowerFilename.EndsWith(".pcc") || lowerFilename.EndsWith(".u") || lowerFilename.EndsWith(".sfm") || lowerFilename.EndsWith(".upk")) { pcc = MEPackageHandler.OpenMEPackage(fileName); } else if (lowerFilename.EndsWith(".sfar")) { dlcPackage = new DLCPackage(fileName); } bytes = File.ReadAllBytes(fileName); Interpreter_Hexbox.ByteProvider = new DynamicByteProvider(bytes); Title = "FileHexViewerWPF - " + fileName; AddRecent(fileName, false); SaveRecentList(); RefreshRecent(); MemoryStream inStream = new MemoryStream(bytes); UnusedSpaceList.ClearEx(); if (pcc != null) { parsePackage(inStream); } else if (dlcPackage != null) { parseDLC(inStream); } }
private void addFileToolStripMenuItem_Click(object sender, EventArgs e) { if (DLC == null) { return; } OpenFileDialog d = new OpenFileDialog(); d.Filter = "*.*|*.*"; string p = Path.GetDirectoryName(DLC.Files[0].FileName) + "\\"; if (d.ShowDialog() == DialogResult.OK) { string path = p + Path.GetFileName(d.FileName); path = path.Replace('\\', '/'); string result = Microsoft.VisualBasic.Interaction.InputBox("Please enter the path with name that the file will have inside the DLC", "ME3 Explorer", path, 0, 0); if (result == "") { return; } path = result; System.Diagnostics.Debug.WriteLine("Adding file quick: " + d.FileName + " " + path); DLC.AddFileQuick(d.FileName, path); DLC = new DLCPackage(DLC.FileName); treeView1.Nodes.Clear(); treeView1.Nodes.Add(DLC.ToTree()); SearchNode(result, treeView1.Nodes[0]); MessageBox.Show("File added."); } }
public bool ExtractAllDLC() { bool retval = true; string DLCBasePath = ME3Directory.DLCPath; DebugOutput.PrintLn("DLC Path: " + DLCBasePath); List <string> files = new List <string>(Directory.EnumerateFiles(DLCBasePath, "Default.sfar", SearchOption.AllDirectories)); foreach (string file in files) { string[] parts = file.Split('\\'); if (parts[parts.Length - 2].ToLower() != "cookedpcconsole") { DebugOutput.PrintLn(file + " doesn't look correct. SFAR in the wrong place?"); retval = false; continue; } if (file != "") { DLCPackage DLC = openSFAR2(file); unpackSFAR(DLC); } } DebugOutput.PrintLn("All DLCs Done."); return(retval); }
private void replaceFile(string filename, int n) { DLC.ReplaceEntry(filename, n); DLC = new DLCPackage(DLC.FileName); treeView1.Nodes.Clear(); treeView1.Nodes.Add(DLC.ToTree()); SearchNode(filename, treeView1.Nodes[0]); }
private void replaceFile(string filename, int n) { DLC.ReplaceEntry(filename, n); DLC = new DLCPackage(DLC.FileName); treeView1.Nodes.Clear(); // Todo: Add extension for toTree() // SFAR Editor 2 is useful for looking at non-PC SFARs //treeView1.Nodes.Add(DLC.ToTree()); SearchNode(filename, treeView1.Nodes[0]); }
private void LoadME3FilesList() { var me3files = new List <BackupFile>(); var bup = BackupService.GetGameBackupPath(Mod.MEGame.ME3); if (bup != null) { var target = new GameTarget(Mod.MEGame.ME3, bup, false); var cookedPath = MEDirectories.CookedPath(target); foreach (var f in Extensions.GetFiles(cookedPath, @"\.pcc|\.tfc|\.afc|\.bin|\.tlk", SearchOption.AllDirectories)) { me3files.Add(new BackupFile(@"BASEGAME", Path.GetFileName(f))); } me3files.Sort(); //sort basegame var dlcDir = MEDirectories.DLCPath(target); var officialDLC = VanillaDatabaseService.GetInstalledOfficialDLC(target); foreach (var v in officialDLC) { var sfarPath = Path.Combine(dlcDir, v, @"CookedPCConsole", @"Default.sfar"); if (File.Exists(sfarPath)) { var filesToAdd = new List <BackupFile>(); DLCPackage dlc = new DLCPackage(sfarPath); foreach (var f in dlc.Files) { filesToAdd.Add(new BackupFile(v, Path.GetFileName(f.FileName))); } filesToAdd.Sort(); me3files.AddRange(filesToAdd); } } //TESTPATCH var tpPath = ME3Directory.GetTestPatchPath(target); if (File.Exists(tpPath)) { var filesToAdd = new List <BackupFile>(); DLCPackage dlc = new DLCPackage(tpPath); foreach (var f in dlc.Files) { filesToAdd.Add(new BackupFile(@"TESTPATCH", Path.GetFileName(f.FileName))); } filesToAdd.Sort(); me3files.AddRange(filesToAdd); } } Application.Current.Dispatcher.Invoke(delegate { ME3Files.ReplaceAll(me3files); }); Debug.WriteLine(@"Num ME3 files: " + ME3Files.Count); }
public static void unpackSFAR(DLCPackage dlc) { if (dlc == null || dlc.Files == null) { return; } string[] patt = { "pcc", "bik", "tfc", "afc", "cnd", "tlk", "bin", "dlc" }; string file = dlc.FileName; //full path string t1 = Path.GetDirectoryName(file); //cooked string t2 = Path.GetDirectoryName(t1); //DLC_Name string t3 = Path.GetDirectoryName(t2); //DLC string t4 = Path.GetDirectoryName(t3); //BioGame string gamebase = Path.GetDirectoryName(t4); //Mass Effect3 DebugOutput.PrintLn("Extracting DLC with gamebase : " + gamebase); DebugOutput.PrintLn("DLC name : " + t2); if (dlc.Files.Length > 1) { List <int> Indexes = new List <int>(); for (int i = 0; i < dlc.Files.Length; i++) { string DLCpath = dlc.Files[i].FileName; for (int j = 0; j < patt.Length; j++) { if (DLCpath.ToLower().EndsWith(patt[j].Trim().ToLower()) && patt[j].Trim().ToLower() != "") { string relPath = GetRelativePath(DLCpath); string outpath = gamebase + relPath; DebugOutput.PrintLn("Extracting file #" + i.ToString("d4") + ": " + outpath); if (!Directory.Exists(Path.GetDirectoryName(outpath))) { Directory.CreateDirectory(Path.GetDirectoryName(outpath)); } if (!File.Exists(outpath)) { using (FileStream fs = new FileStream(outpath, FileMode.Create)) dlc.DecompressEntryAsync(i, fs).Wait(); } Indexes.Add(i); Application.DoEvents(); break; } } } dlc.DeleteEntries(Indexes); } // AutoTOC AutoTOC.prepareToCreateTOC(t2 + "\\PCConsoleTOC.bin"); DebugOutput.PrintLn("DLC Done."); }
internal static HeroLevel[] Parse(DLCPackage.Manifest.PhraseIteration phraseIteration) { var heroLevels = new HeroLevel[3]; for (var i = 0; i < heroLevels.Length; i++) { heroLevels[i] = new HeroLevel { Hero = i + 1, Difficulty = (byte) phraseIteration.MaxScorePerDifficulty[i] }; } return heroLevels; }
private void openSFAR(string filename) { try { DLC = new DLCPackage(filename); treeView1.Nodes.Clear(); treeView1.Nodes.Add(DLC.ToTree()); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } }
private void rebuildSFARToolStripMenuItem_Click(object sender, EventArgs e) { if (DLC == null) { return; } DebugOutput.StartDebugger("DLCEditor2"); DLC.ReBuild(); DLC = new DLCPackage(DLC.FileName); treeView1.Nodes.Clear(); treeView1.Nodes.Add(DLC.ToTree()); MessageBox.Show("SFAR Rebuilt."); }
private void openSFAR(String filename) { try { BitConverter.IsLittleEndian = true; DLC = new DLCPackage(filename); treeView1.Nodes.Clear(); treeView1.Nodes.Add(DLC.ToTree()); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } }
private void checkAndRebuildSFARToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog d = new OpenFileDialog(); d.Filter = "*.sfar|*.sfar"; if (d.ShowDialog() == System.Windows.Forms.DialogResult.OK) { BitConverter.IsLittleEndian = true; DebugOutput.Clear(); DLC = new DLCPackage(d.FileName); DLC.UpdateTOCbin(true); DebugOutput.PrintLn("Done."); MessageBox.Show("Done."); } }
public void ExtractAllDLC() { string DLCBasePath = ME3Directory.DLCPath; DebugOutput.PrintLn("DLC Path: " + DLCBasePath); List <string> files = new List <string>(Directory.EnumerateFiles(DLCBasePath, "Default.sfar", SearchOption.AllDirectories)); foreach (string file in files) { if (file != "") { DLCPackage DLC = openSFAR2(file); unpackSFAR(DLC); } } DebugOutput.PrintLn("All DLCs Done."); }
private void replaceFile(String filename, int n) { DLC.ReplaceEntry(filename, n); DLC = new DLCPackage(DLC.MyFileName); treeView1.Nodes.Clear(); treeView1.Nodes.Add(DLC.ToTree()); SearchNode(filename, treeView1.Nodes[0]); if (!automated) { MessageBox.Show("File Replaced."); } else { System.Diagnostics.Debug.WriteLine("Injection complete."); } }
public static List <string> DLCExtractHelper(string file) { // KFreon: Ditching this stuff for Fobs ExtractAllDLC function in Texplorer2.cs // NOTE that the files are normally collected here, now done in Texplorer2.cs return(new List <string>()); List <string> ExtractedFiles = new List <string>(); string[] dlcname = file.Split('\\'); DebugOutput.PrintLn("Temp extracting DLC: " + dlcname[dlcname.Length - 3]); DLCPackage dlc = new DLCPackage(file); List <string> dlcpath = new List <string>(dlc.MyFileName.Split('\\')); dlcpath.RemoveRange(dlcpath.Count - 5, 5); string dlcExtractionPath = String.Join("\\", dlcpath.ToArray()); List <int> Indicies = new List <int>(); for (int i = 0; i < dlc.Files.Count(); i++) { DLCPackage.FileEntryStruct entry = dlc.Files[i]; if (Path.GetExtension(entry.FileName).ToLower() == ".pcc" || Path.GetExtension(entry.FileName).ToLower() == ".tfc") { DebugOutput.PrintLn("Extracting: " + dlc.Files[i].FileName); try { Directory.CreateDirectory(Path.GetDirectoryName(dlcExtractionPath + dlc.Files[i].FileName)); using (FileStream fs = new FileStream(dlcExtractionPath + dlc.Files[i].FileName, FileMode.CreateNew)) dlc.DecompressEntry(i).WriteTo(fs); Indicies.Add(i); } catch (Exception e) { DebugOutput.PrintLn("File " + dlcExtractionPath + entry.FileName + " already exists. Extra: " + e.Message); Console.WriteLine(e.Message); } ExtractedFiles.Add(dlcExtractionPath + entry.FileName); } } dlc.DeleteEntry(Indicies); return(ExtractedFiles); }
private void deleteSelectedToolStripMenuItem_Click(object sender, EventArgs e) { TreeNode t = treeView1.SelectedNode; if (DLC == null || t == null || t.Parent == null || t.Parent.Text != "FileEntries") { return; } if (MessageBox.Show("Are you sure to delete this File?", "DLCEditor2", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { int n = t.Index; DLC.DeleteEntry(n); DLC = new DLCPackage(DLC.FileName); treeView1.Nodes.Clear(); treeView1.Nodes.Add(DLC.ToTree()); MessageBox.Show("File Deleted."); } }
public static AFCInventory GetInventory(string inputPath, MEGame game, Action <string> currentScanningFileCallback = null, Action <string> debugOut = null) { AFCInventory inventory = new AFCInventory(); inventory.LocalFolderAFCFiles.ReplaceAll(Directory.GetFiles(inputPath, "*.afc", SearchOption.AllDirectories)); debugOut?.Invoke($"Beginning AFC references scan. Input path: {inputPath}, game {game}"); inventory.BasegameAFCFiles.ReplaceAll(MELoadedFiles.GetCookedFiles(game, GameFilesystem.MEDirectories.GetBioGamePath(game), includeAFCs: true).Where(x => Path.GetExtension(x) == ".afc")); foreach (var oafc in inventory.BasegameAFCFiles) { debugOut?.Invoke($@" >> Found Basegame AFC {oafc}"); } inventory.OfficialDLCAFCFiles = MELoadedFiles.GetOfficialDLCFolders(game).SelectMany(x => Directory.GetFiles(x, "*.afc", SearchOption.AllDirectories)).ToList(); foreach (var oafc in inventory.OfficialDLCAFCFiles) { debugOut?.Invoke($@" >> Found AFC in DLC directory {oafc}"); } // ME3: Inspect SFARs for AFCs if (game == MEGame.ME3 && Directory.Exists(ME3Directory.DLCPath)) { debugOut?.Invoke($@"DLC directory: {ME3Directory.DLCPath}"); foreach (var officialDLC in ME3Directory.OfficialDLC) { var sfarPath = Path.Combine(ME3Directory.DLCPath, officialDLC, "CookedPCConsole", "Default.sfar"); if (File.Exists(sfarPath)) { currentScanningFileCallback?.Invoke(ME3Directory.OfficialDLCNames[officialDLC]); debugOut?.Invoke($@"{ME3Directory.OfficialDLCNames[officialDLC]} is installed ({officialDLC})"); DLCPackage dlc = new DLCPackage(sfarPath); inventory.SFARAFCsMap[officialDLC] = dlc.Files.Where(x => x.FileName.EndsWith(".afc")).Select(x => x.FileName).ToList(); foreach (var oafc in inventory.SFARAFCsMap[officialDLC]) { debugOut?.Invoke($@" >> Found SFAR AFC {oafc}"); } inventory.OfficialDLCAFCFiles.AddRange(inventory.SFARAFCsMap[officialDLC]); } } } return(inventory); }
private double GetRequiredSize() { var folders = Directory.EnumerateDirectories(ME3Directory.DLCPath); var extracted = folders.Where(folder => Directory.EnumerateFiles(folder, "*", SearchOption.AllDirectories).Any(file => file.EndsWith("pcconsoletoc.bin", StringComparison.OrdinalIgnoreCase))); var unextracted = folders.Except(extracted); double compressedSize = 0; double uncompressedSize = 0; double largestUncompressedSize = 0; double temp; foreach (var folder in unextracted) { if (folder.Contains("__metadata")) { continue; } try { FileInfo info = new FileInfo(Directory.EnumerateFiles(folder, "*", SearchOption.AllDirectories).Where(file => file.EndsWith(".sfar", StringComparison.OrdinalIgnoreCase)).First()); compressedSize += info.Length; DLCPackage sfar = new DLCPackage(info.FullName); sfarsToUnpack.Add(sfar); temp = sfar.UncompressedSize; uncompressedSize += temp; if (temp > largestUncompressedSize) { largestUncompressedSize = temp; } } catch (Exception) { return(-1); } } totalUncompressedSize = uncompressedSize; //each SFAR is stripped of all its files after unpacking, so the maximum space needed on the drive is //the difference between the uncompressed size and compressed size of all SFARS, plus the compressed size //of the largest SFAR. I'm using the uncompressed size instead as a fudge factor. return((uncompressedSize - compressedSize) + largestUncompressedSize); }
private void openSFAR(string filename) { try { DLC = new DLCPackage(filename); treeView1.Nodes.Clear(); //todo //treeView1.Nodes.Add(DLC.ToTree()); //var outf = @"X:\quickbms"; //foreach (var f in DLC.Files.Where(x => x.isActualFile)) //{ // var outpath = Path.Combine(outf, f.FileName.Replace("/", "\\").TrimStart('\\')); // Directory.CreateDirectory(Path.GetDirectoryName(outpath)); // var decomp = DLC.DecompressEntry(f); // decomp.WriteToFile(outpath); //} } catch (Exception ex) { MessageBox.Show(ex.ToString()); } }
public void Init(string DLCpath) { MyPath = DLCpath; dlc = new DLCPackage(DLCpath); int count = 0; Objects = new List <int>(); listBox1.Items.Clear(); foreach (DLCPackage.FileEntryStruct f in dlc.Files) { if (f.FileName.Trim().ToLower().EndsWith(".pcc")) { listBox1.Items.Add(f.FileName); Objects.Add(count); } count++; } bool run = true; while (run) { run = false; for (int i = 0; i < Objects.Count - 1; i++) { if (listBox1.Items[i].ToString().CompareTo(listBox1.Items[i + 1]) > 0) { string s = listBox1.Items[i].ToString(); listBox1.Items[i] = listBox1.Items[i + 1].ToString(); listBox1.Items[i + 1] = s; int x = Objects[i]; Objects[i] = Objects[i + 1]; Objects[i + 1] = x; run = true; } } } }
public void TestSFARParsing() { GlobalTest.Init(); // Loads compressed packages and attempts to enumerate every object's properties. var sfarsPath = GlobalTest.GetTestSFARsDirectory(); var sfars = Directory.GetFiles(sfarsPath, "*.sfar", SearchOption.AllDirectories); foreach (var s in sfars) { var expectedCompressionType = Path.GetFileNameWithoutExtension(s); Console.WriteLine($"Opening SFAR {s}"); DLCPackage dlc = new DLCPackage(s); Assert.AreEqual(expectedCompressionType, dlc.Header.CompressionScheme); // Enumerate files foreach (var f in dlc.Files) { var lookup = dlc.FindFileEntry(Path.GetFileName(f.FileName)); Assert.AreEqual(dlc.Files[lookup], f); var de = dlc.DecompressEntry(lookup); Assert.AreEqual(f.RealUncompressedSize, de.Length); } } }
public DLCEditor2() { InitializeComponent(); //FemShep's Mod Manager 3 automator for DLCEditor2. string[] arguments = Environment.GetCommandLineArgs(); if (arguments.Length > 2) { try { string cmdCommand = arguments[1]; if (cmdCommand.Equals("-dlcinject", StringComparison.Ordinal)) { if (arguments.Length % 2 != 1 || arguments.Length < 5) { MessageBox.Show("Wrong number of arguments for the -dlcinject switch.:\nSyntax is: <exe> -dlcinject SFARPATH SEARCHTERM NEWFILEPATH [SEARCHTERM2 NEWFILEPATH2]...", "ME3 DLCEditor2 Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } string dlcFileName = arguments[2]; int numfiles = (arguments.Length - 3) / 2; string[] filesToReplace = new String[numfiles]; string[] newFiles = new String[numfiles]; int argnum = 3; //starts at 3 for (int i = 0; i < filesToReplace.Length; i++) { filesToReplace[i] = arguments[argnum]; argnum++; newFiles[i] = arguments[argnum]; argnum++; } automated = true; if (File.Exists(dlcFileName)) { openSFAR(dlcFileName); } else { System.Diagnostics.Debug.WriteLine("dlcFilename does not exist: " + dlcFileName); MessageBox.Show("Failed to autoinject: DLC file does not exist: " + dlcFileName, "ME3Explorer DLCEditor2 Error", MessageBoxButtons.OK, MessageBoxIcon.Error); Application.Exit(); return; } //SFAR was opened. //Now we search for the element to replace so it is selected... for (int i = 0; i < numfiles; i++) { selectSearchedElement(filesToReplace[i]); //the element is now selected, hopefully. TreeNode t = treeView1.SelectedNode; if (DLC == null || t == null || t.Parent == null || t.Parent.Text != "FileEntries") { MessageBox.Show("DLCEditor2 automator encountered an error: the file to replace does not exist or the tree has not been initialized.", "ME3 DLCEditor2 Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } replaceFile(newFiles[i], t.Index); } } else if (cmdCommand.Equals("-dlcextract", StringComparison.Ordinal)) { if (arguments.Length != 5) { //-2 for me3explorer & -dlcextract MessageBox.Show("Wrong number of arguments for the -dlcinject switch.:\nSyntax is: <exe> -dlcextract SFARPATH SEARCHTERM EXTRACTIONPATH", "ME3 DLCEditor2 Error", MessageBoxButtons.OK, MessageBoxIcon.Error); Application.Exit(); return; } automated = true; string dlcFileName = arguments[2]; string searchTerm = arguments[3]; string extractionPath = arguments[4]; if (File.Exists(dlcFileName)) { openSFAR(dlcFileName); } else { System.Diagnostics.Debug.WriteLine("dlcFilename does not exist: " + dlcFileName); MessageBox.Show("Failed to autoextract: DLC file does not exist: " + dlcFileName, "ME3Explorer DLCEditor2 Error", MessageBoxButtons.OK, MessageBoxIcon.Error); Application.Exit(); return; } //SFAR was opened. //Now we search for the element to extract so it is selected... selectSearchedElement(searchTerm); //the element is now selected, hopefully. TreeNode t = treeView1.SelectedNode; if (DLC == null || t == null || t.Parent == null || t.Parent.Text != "FileEntries") { MessageBox.Show("DLCEditor2 extraction automator encountered an error:\nThe file to replace does not exist or the tree has not been initialized.", "DLCEditor2 Error", MessageBoxButtons.OK, MessageBoxIcon.Error); Application.Exit(); return; } extractFile(t.Index, extractionPath); } else if (cmdCommand.Equals("-dlcaddfiles", StringComparison.Ordinal)) { if (arguments.Length % 2 != 1 || arguments.Length < 5) { MessageBox.Show("Wrong number of arguments for the -dlcaddfiles switch.:\nSyntax is: <exe> -dlcinject SFARPATH INTERNALPATH NEWFILEPATH [INTERNALPATH2 NEWFILEPATH2]...", "ME3 DLCEditor2 Error", MessageBoxButtons.OK, MessageBoxIcon.Error); Application.Exit(); return; } automated = true; string dlcFileName = arguments[2]; int numfiles = (arguments.Length - 3) / 2; string[] internalPaths = new String[numfiles]; string[] sourcePaths = new String[numfiles]; int argnum = 3; //starts at 3 for (int i = 0; i < internalPaths.Length; i++) { internalPaths[i] = arguments[argnum]; argnum++; sourcePaths[i] = arguments[argnum]; argnum++; } if (File.Exists(dlcFileName)) { openSFAR(dlcFileName); } else { System.Diagnostics.Debug.WriteLine("DLC does not exist: " + dlcFileName); MessageBox.Show("Failed to autoadd: DLC file does not exist: " + dlcFileName, "ME3Explorer DLCEditor2 Error", MessageBoxButtons.OK, MessageBoxIcon.Error); Application.Exit(); return; } //SFAR was opened. for (int i = 0; i < internalPaths.Length; i++) { System.Diagnostics.Debug.WriteLine("Adding file quick: " + sourcePaths[i] + " " + internalPaths[i]); DLC.AddFileQuick(sourcePaths[i], internalPaths[i]); DLC = new DLCPackage(DLC.MyFileName); treeView1.Nodes.Clear(); treeView1.Nodes.Add(DLC.ToTree()); } } else if (cmdCommand.Equals("-dlcremovefiles", StringComparison.Ordinal)) { if (arguments.Length < 4) { //-2 for me3explorer & -dlcextract MessageBox.Show("Wrong number of arguments for the -dlcremovefiles switch.:\nSyntax is: <exe> -dlcinject SFARPATH INTERNALPATH [INTERNALPATH2]...", "ME3 DLCEditor2 Error", MessageBoxButtons.OK, MessageBoxIcon.Error); Application.Exit(); return; } automated = true; string dlcFileName = arguments[2]; int numfiles = (arguments.Length - 3); string[] filesToRemove = new String[numfiles]; int argnum = 3; //starts at 3 for (int i = 0; i < filesToRemove.Length; i++) { filesToRemove[i] = arguments[argnum]; argnum++; } if (File.Exists(dlcFileName)) { openSFAR(dlcFileName); } else { System.Diagnostics.Debug.WriteLine("DLC does not exist: " + dlcFileName); MessageBox.Show("Failed to autoremove: DLC file does not exist: " + dlcFileName, "ME3Explorer DLCEditor2 Error", MessageBoxButtons.OK, MessageBoxIcon.Error); Application.Exit(); return; } //SFAR was opened. for (int i = 0; i < filesToRemove.Length; i++) { selectSearchedElement(filesToRemove[i]); //the element is now selected, hopefully. TreeNode t = treeView1.SelectedNode; if (DLC == null || t == null || t.Parent == null || t.Parent.Text != "FileEntries") { MessageBox.Show("DLCEditor2 file removal automator encountered an error:\nThe file to remove does not exist or the tree has not been initialized.", "DLCEditor2 Error", MessageBoxButtons.OK, MessageBoxIcon.Error); Application.Exit(); return; } DLC.DeleteEntry(t.Index); DLC = new DLCPackage(DLC.MyFileName); treeView1.Nodes.Clear(); treeView1.Nodes.Add(DLC.ToTree()); } } else if (cmdCommand.Equals("-dlcunpack", StringComparison.Ordinal) || cmdCommand.Equals("-dlcunpack-nodebug", StringComparison.Ordinal)) { if (arguments.Length != 4) { MessageBox.Show("Wrong number of arguments for automated DLC unpacking:\nSyntax is: <exe> -dlcinject SFARPATH EXTRACTIONPATH", "ME3 DLCEditor2 Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } string sfarPath = arguments[2]; autoUnpackFolder = arguments[3]; automated = true; if (File.Exists(sfarPath)) { openSFAR(sfarPath); } else { System.Diagnostics.Debug.WriteLine("DLC does not exist: " + sfarPath); MessageBox.Show("Failed to autounpack: DLC file does not exist: " + sfarPath, "ME3Explorer DLCEditor2 Error", MessageBoxButtons.OK, MessageBoxIcon.Error); Application.Exit(); return; } //SFAR was opened. if (cmdCommand.Equals("-dlcunpack")) { DebugOutput.StartDebugger("DLC Editor 2"); //open debugging window since this operation takes a long time. The main debugger won't start as this will exit before that code can be reached } //Simulate Unpack operation click. unpackSFARToolStripMenuItem.PerformClick(); } } catch (FileNotFoundException exc) { MessageBox.Show("Failed to run DLCEditor2 Automator with the specified parameters.\n\nA file not found error occured while trying to automate a task.\n" + exc.Message, "DLC Editor2 Error", MessageBoxButtons.OK, MessageBoxIcon.Error); Environment.Exit(1); Application.Exit(); } Environment.Exit(0); Application.Exit(); } DebugOutput.StartDebugger("DLC Editor 2"); //open debugging window AFTER automation. Otherwise it pops up all weirdlike. }
private void unpackSFAR(DLCPackage DLC) { AutoTOC.AutoTOC toc = new AutoTOC.AutoTOC(); if (DLC == null || DLC.Files == null) { return; } string result = "pcc; tfc; afc; cnd; tlk; bin; bik; dlc"; if (result == "") { return; } result = result.Trim(); if (result.EndsWith(";")) { result = result.Substring(0, result.Length - 1); } string[] patt = result.Split(';'); string file = DLC.MyFileName; //full path string t1 = Path.GetDirectoryName(file); //cooked string t2 = Path.GetDirectoryName(t1); //DLC_Name string t3 = Path.GetDirectoryName(t2); //DLC string t4 = Path.GetDirectoryName(t3); //BioGame string gamebase = Path.GetDirectoryName(t4); //Mass Effect3 DebugOutput.PrintLn("Extracting DLC with gamebase : " + gamebase); DebugOutput.PrintLn("DLC name : " + t2); if (DLC.Files.Length > 1) { List <int> Indexes = new List <int>(); for (int i = 0; i < DLC.Files.Length; i++) { string DLCpath = DLC.Files[i].FileName; for (int j = 0; j < patt.Length; j++) { if (DLCpath.ToLower().EndsWith(patt[j].Trim().ToLower()) && patt[j].Trim().ToLower() != "") { string relPath = GetRelativePath(DLCpath); string outpath = gamebase + relPath; DebugOutput.PrintLn("Extracting file #" + i.ToString("d4") + ": " + outpath); if (!Directory.Exists(Path.GetDirectoryName(outpath))) { Directory.CreateDirectory(Path.GetDirectoryName(outpath)); } if (!File.Exists(outpath)) { using (FileStream fs = new FileStream(outpath, FileMode.Create)) DLC.DecompressEntry(i).WriteTo(fs); } Indexes.Add(i); Application.DoEvents(); break; } } } DLC.DeleteEntry(Indexes); } // AutoTOC DebugOutput.PrintLn("Updating DLC's PCConsoleTOC.bin"); List <string> FileNames = toc.GetFiles(t2 + "\\"); List <string> tet = new List <string>(t2.Split('\\')); string remov = String.Join("\\", tet.ToArray()); for (int i = 0; i < FileNames.Count; i++) { FileNames[i] = FileNames[i].Substring(remov.Length + 1); } string[] ts = t2.Split('\\'); tet.Clear(); tet.AddRange(ts); string basepath = String.Join("\\", tet.ToArray()) + '\\'; string tocfile = t2 + "\\PCConsoleTOC.bin"; toc.CreateTOC(basepath, tocfile, FileNames.ToArray()); DebugOutput.PrintLn("DLC Done."); }
public void ScanDLCfolder2() { DebugOutput.PrintLn("\n\nDLC Scan for packed files...\n", true); string dir = ME3Directory.DLCPath; string[] files = Directory.GetFiles(dir, "*.sfar", SearchOption.AllDirectories); if (files.Length == 0) { return; } pbar1.Maximum = files.Length - 1; int count = 0; foreach (string file in files) { if (!file.ToLower().Contains("patch")) { DebugOutput.PrintLn("Scan file #" + count + " : " + file, count % 10 == 0); try { DLCPackage dlc = new DLCPackage(file); DebugOutput.PrintLn("found " + dlc.Files.Length + " files : " + file); for (int j = 0; j < dlc.Files.Length; j++) { if (dlc.Files[j].FileName.ToLower().EndsWith(".pcc")) { string filename = dlc.Files[j].FileName; DebugOutput.PrintLn(" " + j.ToString("d4") + " / " + dlc.Files.Length.ToString("d4") + " : opening " + Path.GetFileName(filename), true); MemoryStream mem = dlc.DecompressEntry(j); File.WriteAllBytes("temp.pcc", mem.ToArray()); using (ME3Package pcc = MEPackageHandler.OpenME3Package("temp.pcc")) { IReadOnlyList <IExportEntry> Exports = pcc.Exports; for (int i = 0; i < Exports.Count; i++) { if (Exports[i].ClassName == "BioConversation") { DebugOutput.PrintLn("Found dialog \"" + Exports[i].ObjectName + "\"", false); ME3BioConversation Dialog = new ME3BioConversation(Exports[i] as ME3ExportEntry); foreach (ME3BioConversation.EntryListStuct e in Dialog.EntryList) { string text = ME3TalkFiles.findDataById(e.refText); if (text.Length != 7 && text != "No Data") { EntryStruct t = new EntryStruct(); t.inDLC = true; t.text = text; t.ID = e.refText; t.indexpcc = i; t.pathafc = "";//Todo t.pathdlc = file; t.pathpcc = filename; t.convname = Exports[i].ObjectName; if (e.SpeakerIndex >= 0 && e.SpeakerIndex < Dialog.SpeakerList.Count) { t.speaker = Dialog.SpeakerList[e.SpeakerIndex].InstancedString; } else { t.speaker = "unknown"; } if (t.speaker == null || t.speaker == "") { t.speaker = "unknown"; } Entries.Add(t); DebugOutput.PrintLn("Requ.: (" + t.speaker + ") " + t.text, false); } } foreach (ME3BioConversation.ReplyListStruct e in Dialog.ReplyList) { string text = ME3TalkFiles.findDataById(e.refText); if (text.Length != 7 && text != "No Data") { EntryStruct t = new EntryStruct(); t.inDLC = true; t.text = text; t.ID = e.refText; t.indexpcc = i; t.pathafc = "";//Todo t.pathdlc = file; t.pathpcc = filename; t.convname = Exports[i].ObjectName; Entries.Add(t); DebugOutput.PrintLn("Reply: " + t.text, false); } } } } } } } if (count % 10 == 0) { Application.DoEvents(); pbar1.Value = count; } count++; } catch (Exception ex) { DebugOutput.PrintLn("=====ERROR=====\n" + ex.ToString() + "\n=====ERROR====="); } } } if (File.Exists("temp.pcc")) { File.Delete("temp.pcc"); } }
private bool HandleCommandLineArgs(string[] args, out int exitCode) { if (args.Length < 2) { exitCode = 0; return(false); } //automation try { if (args[1].Equals("-dlcinject")) { if (args.Length % 2 != 1 || args.Length < 5) { MessageBox.Show("Wrong number of arguments for the -dlcinject switch.:\nSyntax is: <exe> -dlcinject SFARPATH SEARCHTERM NEWFILEPATH [SEARCHTERM2 NEWFILEPATH2]...", "ME3 DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error); exitCode = 1; return(true); } string dlcFileName = args[2]; int numfiles = (args.Length - 3) / 2; string[] filesToReplace = new string[numfiles]; string[] newFiles = new string[numfiles]; int argnum = 3; //starts at 3 for (int i = 0; i < filesToReplace.Length; i++) { filesToReplace[i] = args[argnum]; argnum++; newFiles[i] = args[argnum]; argnum++; } if (File.Exists(dlcFileName)) { DLCPackage dlc = new DLCPackage(dlcFileName); for (int i = 0; i < numfiles; i++) { int idx = dlc.FindFileEntry(filesToReplace[i]); if (idx == -1) { MessageBox.Show("DLCEditor2 automator encountered an error: the file to replace does not exist.", "ME3 DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error); exitCode = 1; return(true); } dlc.ReplaceEntry(newFiles[i], idx); } exitCode = 0; return(true); } MessageBox.Show("Failed to autoinject: DLC file does not exist: " + dlcFileName, "ME3Explorer DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error); exitCode = 1; return(true); } else if (args[1].Equals("-dlcextract")) { if (args.Length != 5) { //-2 for me3explorer & -dlcextract MessageBox.Show("Wrong number of arguments for the -dlcextract switch.:\nSyntax is: <exe> -dlcextract SFARPATH SEARCHTERM EXTRACTIONPATH", "ME3 DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error); exitCode = 1; return(true); } string dlcFileName = args[2]; string searchTerm = args[3]; string extractionPath = args[4]; if (File.Exists(dlcFileName)) { DLCPackage dlc = new DLCPackage(dlcFileName); int idx = dlc.FindFileEntry(searchTerm); if (idx == -1) { MessageBox.Show("DLCEditor2 extraction automator encountered an error:\nThe file to replace does not exist or the tree has not been initialized.", "DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error); exitCode = 1; return(true); } using (FileStream fs = new FileStream(extractionPath, FileMode.Create, FileAccess.Write, FileShare.None, 4096, useAsync: true)) { dlc.DecompressEntryAsync(idx, fs).Wait(); } exitCode = 0; return(true); } MessageBox.Show("Failed to autoextract: DLC file does not exist: " + dlcFileName, "ME3Explorer DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error); exitCode = 1; return(true); } else if (args[1].Equals("-dlcaddfiles")) { if (args.Length % 2 != 1 || args.Length < 5) { MessageBox.Show("Wrong number of arguments for the -dlcaddfiles switch.:\nSyntax is: <exe> -dlcinject SFARPATH INTERNALPATH NEWFILEPATH [INTERNALPATH2 NEWFILEPATH2]...", "ME3 DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error); exitCode = 1; return(true); } string dlcFileName = args[2]; int numfiles = (args.Length - 3) / 2; string[] internalPaths = new string[numfiles]; string[] sourcePaths = new string[numfiles]; int argnum = 3; //starts at 3 for (int i = 0; i < internalPaths.Length; i++) { internalPaths[i] = args[argnum]; argnum++; sourcePaths[i] = args[argnum]; argnum++; } if (File.Exists(dlcFileName)) { DLCPackage dlc = new DLCPackage(dlcFileName); for (int i = 0; i < internalPaths.Length; i++) { dlc.AddFileQuick(sourcePaths[i], internalPaths[i]); } exitCode = 0; return(true); } MessageBox.Show("Failed to autoadd: DLC file does not exist: " + dlcFileName, "ME3Explorer DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error); exitCode = 1; return(true); } else if (args[1].Equals("-dlcremovefiles")) { if (args.Length < 4) { //-2 for me3explorer & -dlcextract MessageBox.Show("Wrong number of arguments for the -dlcremovefiles switch.:\nSyntax is: <exe> -dlcinject SFARPATH INTERNALPATH [INTERNALPATH2]...", "ME3 DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error); exitCode = 1; return(true); } string dlcFileName = args[2]; int numfiles = (args.Length - 3); string[] filesToRemove = new string[numfiles]; int argnum = 3; //starts at 3 for (int i = 0; i < filesToRemove.Length; i++) { filesToRemove[i] = args[argnum]; argnum++; } if (File.Exists(dlcFileName)) { DLCPackage dlc = new DLCPackage(dlcFileName); for (int i = 0; i < filesToRemove.Length; i++) { int idx = dlc.FindFileEntry(filesToRemove[i]); if (idx == -1) { MessageBox.Show("DLCEditor2 file removal automator encountered an error:\nThe file to remove does not exist or the tree has not been initialized.", "DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error); exitCode = 1; return(true); } dlc.DeleteEntry(idx); } exitCode = 0; return(true); } MessageBox.Show("Failed to autoremove: DLC file does not exist: " + dlcFileName, "ME3Explorer DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error); exitCode = 1; return(true); } else if (args[1].Equals("-dlcunpack") || args[1].Equals("-dlcunpack-nodebug")) { if (args.Length != 4) { MessageBox.Show("Wrong number of arguments for automated DLC unpacking:\nSyntax is: <exe> -dlcunpack SFARPATH EXTRACTIONPATH", "ME3 DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error); exitCode = 1; return(true); } string sfarPath = args[2]; string autoUnpackFolder = args[3]; if (File.Exists(sfarPath)) { DLCPackage dlc = new DLCPackage(sfarPath); if (args[1].Equals("-dlcunpack")) { //open debugging window since this operation takes a long time. KFreonLib.Debugging.DebugOutput.StartDebugger("DLC Editor 2"); } //Simulate Unpack operation click. SFAREditor2.unpackSFAR(dlc); exitCode = 0; return(true); } else { MessageBox.Show("Failed to autounpack: DLC file does not exist: " + sfarPath, "ME3Explorer DLCEditor2 Error", MessageBoxButton.OK, MessageBoxImage.Error); exitCode = 1; return(true); } } else if (args[1].Equals("-toceditorupdate")) { //Legacy command requested by FemShep TOCeditor toc = new TOCeditor(); exitCode = toc.updateTOCFromCommandLine(args.Skip(2).ToList()); return(true); } else if (args[1].Equals("-autotoc")) { if (args.Length == 2) { AutoTOC.GenerateAllTOCs(); } else { AutoTOC.prepareToCreateTOC(args[2]); } exitCode = 0; return(true); } else if (args[1].Equals("-sfarautotoc")) { if (args.Length != 3) { MessageBox.Show("-sfarautotoc command line argument requires at least 1 parameter:\nSFARFILE.sfar", "Automated SFAR TOC Update Fail", MessageBoxButton.OK, MessageBoxImage.Error); exitCode = 1; return(true); } var result = Parallel.For(2, args.Length, i => { if (args[i].EndsWith(".sfar") && File.Exists(args[i])) { DLCPackage DLC = new DLCPackage(args[2]); DLC.UpdateTOCbin(true); } }); exitCode = result.IsCompleted ? 0 : 1; return(true); } else if (args[1].Equals("-decompresspcc")) { if (args.Length != 4) { MessageBox.Show("-decompresspcc command line argument requires 2 parameters:\ninputfile.pcc outputfile.pcc\nBoth arguments can be the same.", "Auto Decompression Error", MessageBoxButton.OK, MessageBoxImage.Error); exitCode = 1; return(true); } exitCode = PCCRepack.autoDecompressPcc(args[2], args[3]); return(true); } else if (args[1].Equals("-compresspcc")) { if (args.Length != 4) { MessageBox.Show("-compresspcc command line argument requires 2 parameters:\ninputfile.pcc outputfile.pcc\nBoth arguments can be the same.", "Auto Compression Error", MessageBoxButton.OK, MessageBoxImage.Error); exitCode = 1; return(true); } exitCode = PCCRepack.autoCompressPcc(args[2], args[3]); return(true); } } catch { exitCode = 1; return(true); } string ending = Path.GetExtension(args[1]).ToLower(); switch (ending) { case ".pcc": PackageEditor editor = new PackageEditor(); editor.Show(); editor.LoadFile(args[1]); break; } exitCode = 0; return(false); }
public static bool RunTOCOnGameTarget(GameTarget target, Action <int> percentDoneCallback = null) { Log.Information(@"Autotocing game: " + target.TargetPath); //get toc target folders, ensuring we clean up the inputs a bit. string baseDir = Path.GetFullPath(Path.Combine(target.TargetPath, @"BIOGame")); string dlcDirRoot = MEDirectories.DLCPath(target); if (!Directory.Exists(dlcDirRoot)) { Log.Error(@"Specified game directory does not appear to be a Mass Effect 3 root game directory (DLC folder missing)."); return(false); } var tocTargets = (new DirectoryInfo(dlcDirRoot)).GetDirectories().Select(x => x.FullName).Where(x => Path.GetFileName(x).StartsWith(@"DLC_", StringComparison.OrdinalIgnoreCase)).ToList(); tocTargets.Add(baseDir); tocTargets.Add(Path.Combine(target.TargetPath, @"BIOGame\Patches\PCConsole\Patch_001.sfar")); //Debug.WriteLine("Found TOC Targets:"); tocTargets.ForEach(x => Debug.WriteLine(x)); //Debug.WriteLine("=====Generating TOC Files====="); int done = 0; foreach (var tocTarget in tocTargets) { string sfar = Path.Combine(tocTarget, SFAR_SUBPATH); if (tocTarget.EndsWith(@".sfar")) { //TestPatch var watch = Stopwatch.StartNew(); DLCPackage dlc = new DLCPackage(tocTarget); var tocResult = dlc.UpdateTOCbin(); watch.Stop(); if (tocResult == DLCPackage.DLCTOCUpdateResult.RESULT_UPDATE_NOT_NECESSARY) { Log.Information($@"TOC is already up to date in {tocTarget}"); } else if (tocResult == DLCPackage.DLCTOCUpdateResult.RESULT_UPDATED) { var elapsedMs = watch.ElapsedMilliseconds; Log.Information($@"{tocTarget} - Ran SFAR TOC, took {elapsedMs}ms"); } } else if (ME3Directory.OfficialDLCNames.ContainsKey(Path.GetFileName(tocTarget))) { //Official DLC if (File.Exists(sfar)) { if (new FileInfo(sfar).Length == 32) //DLC is unpacked for sure { CreateUnpackedTOC(tocTarget); } else { //AutoTOC it - SFAR is not unpacked var watch = System.Diagnostics.Stopwatch.StartNew(); DLCPackage dlc = new DLCPackage(sfar); var tocResult = dlc.UpdateTOCbin(); watch.Stop(); if (tocResult == DLCPackage.DLCTOCUpdateResult.RESULT_ERROR_NO_ENTRIES) { Log.Information($@"No DLC entries in SFAR... Suspicious. Creating empty TOC for {tocTarget}"); CreateUnpackedTOC(tocTarget); } else if (tocResult == DLCPackage.DLCTOCUpdateResult.RESULT_UPDATE_NOT_NECESSARY) { Log.Information($@"TOC is already up to date in {tocTarget}"); } else if (tocResult == DLCPackage.DLCTOCUpdateResult.RESULT_UPDATED) { var elapsedMs = watch.ElapsedMilliseconds; Log.Information($@"{Path.GetFileName(tocTarget)} - Ran SFAR TOC, took {elapsedMs}ms"); } } } } else { //TOC it unpacked style // Console.WriteLine(foldername + ", - UNPACKED TOC"); CreateUnpackedTOC(tocTarget); } done++; percentDoneCallback?.Invoke((int)Math.Floor(done * 100.0 / tocTargets.Count)); } return(true); }
private bool RunGameWideAutoTOC() { Debug.WriteLine("FULL AUTOTOC MODE - Updating Unpacked and SFAR TOCs"); //get toc target folders, ensuring we clean up the inputs a bit. string baseDir = Path.GetFullPath(Path.Combine(gameWideModeTarget.TargetPath, "BIOGame")); string dlcDirRoot = Path.GetFullPath(Path.Combine(baseDir, "DLC")); if (!Directory.Exists(dlcDirRoot)) { Log.Error("Specified game directory does not appear to be a Mass Effect 3 root game directory (DLC folder missing)."); return(false); } var tocTargets = (new DirectoryInfo(dlcDirRoot)).GetDirectories().Select(x => x.FullName).Where(x => Path.GetFileName(x).StartsWith("DLC_", StringComparison.OrdinalIgnoreCase)).ToList(); tocTargets.Add(baseDir); tocTargets.Add(Path.Combine(gameWideModeTarget.TargetPath, @"BIOGame\Patches\PCConsole\Patch_001.sfar")); //.Select(d => d.FullName + "\\").Where(x => x.StartsWith(dlcDir + "DLC_", StringComparison.OrdinalIgnoreCase)).ToList(); Debug.WriteLine("Found TOC Targets:"); tocTargets.ForEach(x => Debug.WriteLine(x)); Debug.WriteLine("=====Generating TOC Files====="); //Parallel.ForEach(tocTargets, (currentfolder) => //{ int done = 0; foreach (var tocTarget in tocTargets) { string sfar = Path.Combine(tocTarget, SFAR_SUBPATH); if (tocTarget.EndsWith(".sfar")) { //TestPatch var watch = System.Diagnostics.Stopwatch.StartNew(); DLCPackage dlc = new DLCPackage(tocTarget); var tocResult = dlc.UpdateTOCbin(); watch.Stop(); if (tocResult == DLCPackage.DLCTOCUpdateResult.RESULT_UPDATE_NOT_NECESSARY) { Log.Information("TOC is already up to date in " + tocTarget); } else if (tocResult == DLCPackage.DLCTOCUpdateResult.RESULT_UPDATED) { var elapsedMs = watch.ElapsedMilliseconds; Log.Information($"{tocTarget} - Ran SFAR TOC, took {elapsedMs}ms"); } } else if (ME3Directory.OfficialDLCNames.ContainsKey(Path.GetFileName(tocTarget))) { //Official DLC if (File.Exists(sfar)) { if (new FileInfo(sfar).Length == 32) //DLC is unpacked for sure { CreateUnpackedTOC(tocTarget); } else { //AutoTOC it - SFAR is not unpacked var watch = System.Diagnostics.Stopwatch.StartNew(); DLCPackage dlc = new DLCPackage(sfar); var tocResult = dlc.UpdateTOCbin(); watch.Stop(); if (tocResult == DLCPackage.DLCTOCUpdateResult.RESULT_ERROR_NO_ENTRIES) { CreateUnpackedTOC(tocTarget); } else if (tocResult == DLCPackage.DLCTOCUpdateResult.RESULT_UPDATE_NOT_NECESSARY) { Log.Information("TOC is already up to date in " + tocTarget); } else if (tocResult == DLCPackage.DLCTOCUpdateResult.RESULT_UPDATED) { var elapsedMs = watch.ElapsedMilliseconds; Log.Information($"{Path.GetFileName(tocTarget)} - Ran SFAR TOC, took {elapsedMs}ms"); } } } } else { //TOC it unpacked style // Console.WriteLine(foldername + ", - UNPACKED TOC"); CreateUnpackedTOC(tocTarget); } done++; Percent = (int)Math.Floor(done * 100.0 / tocTargets.Count); } return(true); }
private void CompileIntoGame() { NamedBackgroundWorker nbw = new NamedBackgroundWorker(@"MixinManager CompileIntoGameThread"); List <string> failedApplications = new List <string>(); nbw.DoWork += (a, b) => { BottomLeftMessage = M3L.GetString(M3L.string_compilingMixins); OperationInProgress = true; //DEBUG STUFF #if DEBUG int numCoresToApplyWith = 1; #else var numCoresToApplyWith = Environment.ProcessorCount; if (numCoresToApplyWith > 4) { numCoresToApplyWith = 4; //no more than 4 as this uses a lot of memory } #endif var mixins = AvailableOfficialMixins.Where(x => x.UISelectedForUse).ToList(); MixinHandler.LoadPatchDataForMixins(mixins); //before dynamic void failedApplicationCallback(string str) { failedApplications.Add(str); } var compilingListsPerModule = MixinHandler.GetMixinApplicationList(mixins, failedApplicationCallback); if (failedApplications.Any()) { //Error building list Log.Information(@"Aborting mixin install due to incompatible selection of mixins"); return; } ProgressBarMax = mixins.Count(); ProgressBarValue = 0; int numdone = 0; void completedSingleApplicationCallback() { var val = Interlocked.Increment(ref numdone); ProgressBarValue = val; } //Mixins are ready to be applied Parallel.ForEach(compilingListsPerModule, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount > numCoresToApplyWith ? numCoresToApplyWith : Environment.ProcessorCount }, mapping => { var dlcFolderName = ModMakerCompiler.ModmakerChunkNameToDLCFoldername(mapping.Key.ToString()); //var outdir = Path.Combine(modpath, ModMakerCompiler.HeaderToDefaultFoldername(mapping.Key), @"CookedPCConsole"); //Directory.CreateDirectory(outdir); if (mapping.Key == ModJob.JobHeader.BASEGAME) { //basegame foreach (var file in mapping.Value) { try { using var vanillaPackageAsStream = VanillaDatabaseService.FetchBasegameFile(Mod.MEGame.ME3, Path.GetFileName(file.Key)); //packageAsStream.WriteToFile(@"C:\users\dev\desktop\compressed.pcc"); using var decompressedStream = MEPackage.GetDecompressedPackageStream(vanillaPackageAsStream, true); decompressedStream.Position = 0; var vanillaPackage = MEPackageHandler.OpenMEPackage(decompressedStream, $@"Vanilla - {Path.GetFileName(file.Key)}"); //decompressedStream.WriteToFile(@"C:\users\dev\desktop\decompressed.pcc"); using var mixinModifiedStream = MixinHandler.ApplyMixins(decompressedStream, file.Value, completedSingleApplicationCallback, failedApplicationCallback); mixinModifiedStream.Position = 0; var modifiedPackage = MEPackageHandler.OpenMEPackage(mixinModifiedStream, $@"Mixin Modified - {Path.GetFileName(file.Key)}"); // three way merge: get target stream var targetFile = Path.Combine(MEDirectories.CookedPath(SelectedInstallTarget), Path.GetFileName(file.Key)); var targetPackage = MEPackageHandler.OpenMEPackage(targetFile); var merged = ThreeWayPackageMerge.AttemptMerge(vanillaPackage, modifiedPackage, targetPackage); if (merged) { targetPackage.save(); Log.Information("Three way merge succeeded for " + targetFile); } else { Log.Error("Could not merge three way merge into " + targetFile); } //var outfile = Path.Combine(outdir, Path.GetFileName(file.Key)); //package.save(outfile, false); // don't compress //finalStream.WriteToFile(outfile); //File.WriteAllBytes(outfile, finalStream.ToArray()); } catch (Exception e) { var mixinsStr = string.Join(@", ", file.Value.Select(x => x.PatchName)); Log.Error($@"Error in mixin application for file {file.Key}: {e.Message}"); failedApplicationCallback(M3L.GetString(M3L.string_interp_errorApplyingMixinsForFile, mixinsStr, file.Key, e.Message)); } } } else { //dlc var dlcPackage = VanillaDatabaseService.FetchVanillaSFAR(dlcFolderName); //do not have to open file multiple times. var targetCookedPCDir = Path.Combine(MEDirectories.DLCPath(SelectedInstallTarget), dlcFolderName, @"CookedPCConsole"); var sfar = mapping.Key == ModJob.JobHeader.TESTPATCH ? Utilities.GetTestPatchPath(SelectedInstallTarget) : Path.Combine(targetCookedPCDir, @"Default.sfar"); bool unpacked = new FileInfo(sfar).Length == 32; DLCPackage targetDLCPackage = unpacked ? null : new DLCPackage(sfar); //cache SFAR target foreach (var file in mapping.Value) { try { using var vanillaPackageAsStream = VanillaDatabaseService.FetchFileFromVanillaSFAR(dlcFolderName, file.Key, forcedDLC: dlcPackage); using var decompressedStream = MEPackage.GetDecompressedPackageStream(vanillaPackageAsStream); decompressedStream.Position = 0; var vanillaPackage = MEPackageHandler.OpenMEPackage(decompressedStream, $@"VanillaDLC - {Path.GetFileName(file.Key)}"); using var mixinModifiedStream = MixinHandler.ApplyMixins(decompressedStream, file.Value, completedSingleApplicationCallback, failedApplicationCallback); mixinModifiedStream.Position = 0; var modifiedPackage = MEPackageHandler.OpenMEPackage(mixinModifiedStream, $@"Mixin Modified - {Path.GetFileName(file.Key)}"); // three way merge: get target stream // must see if DLC is unpacked first MemoryStream targetFileStream = null; //Packed if (unpacked) { targetFileStream = new MemoryStream(File.ReadAllBytes(Path.Combine(targetCookedPCDir, file.Key))); } else { targetFileStream = VanillaDatabaseService.FetchFileFromVanillaSFAR(dlcFolderName, Path.GetFileName(file.Key), forcedDLC: targetDLCPackage); } var targetPackage = MEPackageHandler.OpenMEPackage(targetFileStream, $@"Target package {dlcFolderName} - {file.Key}, from SFAR: {unpacked}"); var merged = ThreeWayPackageMerge.AttemptMerge(vanillaPackage, modifiedPackage, targetPackage); if (merged) { if (unpacked) { targetPackage.save(); Log.Information("Three way merge succeeded for " + targetPackage.FilePath); } else { var finalSTream = targetPackage.saveToStream(); targetDLCPackage.ReplaceEntry(finalSTream.ToArray(), targetDLCPackage.FindFileEntry(Path.GetFileName(file.Key))); Log.Information("Three way merge succeeded for " + targetPackage.FileSourceForDebugging); } } else { Log.Error("Could not merge three way merge into " + targetFileStream); } } catch (Exception e) { var mixinsStr = string.Join(@", ", file.Value.Select(x => x.PatchName)); Log.Error($@"Error in mixin application for file {file.Key}: {e.Message}"); failedApplicationCallback(M3L.GetString(M3L.string_interp_errorApplyingMixinsForFile, mixinsStr, file.Key, e.Message)); } //finalStream.WriteToFile(outfile); } } }); MixinHandler.FreeME3TweaksPatchData(); var percent = 0; //this is used to save a localization BottomLeftMessage = $"Running AutoTOC on game {percent}%"; //Run autotoc void tocingUpdate(int percent) { BottomLeftMessage = $"Running AutoTOC on game {percent}%"; } AutoTOC.RunTOCOnGameTarget(SelectedInstallTarget, tocingUpdate); //Generate moddesc //IniData ini = new IniData(); //ini[@"ModManager"][@"cmmver"] = App.HighestSupportedModDesc.ToString(CultureInfo.InvariantCulture); //prevent commas //ini[@"ModInfo"][@"game"] = @"ME3"; //ini[@"ModInfo"][@"modname"] = modname; //ini[@"ModInfo"][@"moddev"] = App.AppVersionHR; //ini[@"ModInfo"][@"moddesc"] = M3L.GetString(M3L.string_compiledFromTheFollowingMixins); //ini[@"ModInfo"][@"modver"] = @"1.0"; //generateRepaceFilesMapping(ini, modpath); //File.WriteAllText(Path.Combine(modpath, @"moddesc.ini"), ini.ToString()); }; nbw.RunWorkerCompleted += (a, b) => { OperationInProgress = false; ClearMixinHandler(); if (failedApplications.Count > 0) { var ld = new ListDialog(failedApplications, M3L.GetString(M3L.string_failedToApplyAllMixins), M3L.GetString(M3L.string_theFollowingMixinsFailedToApply), mainwindow); ld.ShowDialog(); } /*if (modpath != null) * { * OnClosing(new DataEventArgs(modpath)); * } * else * {*/ BottomLeftMessage = "Mixins installed, maybe. Check logs"; //} }; CompilePanelButton.IsOpen = false; nbw.RunWorkerAsync(); }