private Task process(int mode, string regex, string path, ListViewItem[] items, Action <ListViewItem> startItem, Func <ListViewItem, bool> completedItem) { var guiSettings = new { Regex = txtSettingsRegex.Text, SystemOnly = chkSettingsSystemFiles.Checked }; return(Task.Run(() => { foreach (ListViewItem item in items) { ProcessFile pf = (ProcessFile)item.Tag; SourceFile src = pf.SourceFile; Converter nkitConvert = new Converter(src, false); startItem(item); try { nkitConvert.LogMessage += NkitConvert_LogMessage; int fileTotalLen = src.TotalFiles.ToString().Length; using (NDisc dx = new NDisc(nkitConvert, src.Name)) { if (dx != null) { try { switch (mode) { case 1: pf.Results = dx.ExtractRecoveryFiles(); break; case 2: Regex rx = new Regex(guiSettings.Regex, RegexOptions.Compiled | RegexOptions.IgnoreCase); pf.Results = dx.ExtractFiles( /*test*/ f => (guiSettings.SystemOnly && (f.Type == ExtractedFileType.System || f.Type == ExtractedFileType.WiiDiscItem)) || (!guiSettings.SystemOnly && rx.IsMatch(string.Format("{0}/{1}", f.Path, f.Name))), /*extract*/ (s, f) => saveFile(path, pf.SourceFile.Name, f, s)); break; case 3: pf.Results = dx.ExtractBasicInfo(); break; } } catch (Exception ex) { this.Invoke((MethodInvoker) delegate { addToLog(ex.Message); }); } finally { } } } } finally { nkitConvert.LogMessage -= NkitConvert_LogMessage; } if (!completedItem(item)) { break; } } })); }
private Task process(int convertMode, ListViewItem[] items, Action <ListViewItem> startItem, Func <ListViewItem, bool> completedItem) { //get the settings on the main thread to be used on another thread var guiSettings = new { SummaryLog = txtSettingsSummaryLog.Text, TempPath = txtSettingsTempPath.Text, CalculateHashes = chkSettingsCalculateHashes.Checked, DeleteSource = chkSettingsDeleteSource.Checked, EnableSummaryLog = chkSettingsSummaryLog.Checked, FullVerify = chkSettingsFullVerify.Checked, NkitReencode = chkSettingsReencodeNkit.Checked, NkitUpdatePartitionRemoval = chkSettingsRemoveUpdate.Checked, TestMode = chkSettingsTestMode.Checked, MaskRename = chkSettingsUseMasks.Checked, RecoveryMatchFailDelete = chkSettingsRecoveryMatchFailDelete.Checked, Masks = _masks }; return(Task.Run(() => { foreach (ListViewItem item in items) { bool exitLoop = false; Converter nkitConvert = null; ProcessFile pf = (ProcessFile)item.Tag; try { SourceFile src = pf.SourceFile; nkitConvert = new Converter(src, false); startItem(item); nkitConvert.Settings.SummaryLog = guiSettings.SummaryLog; nkitConvert.Settings.TempPath = guiSettings.TempPath; nkitConvert.Settings.CalculateHashes = guiSettings.CalculateHashes; nkitConvert.Settings.DeleteSource = guiSettings.DeleteSource; nkitConvert.Settings.EnableSummaryLog = guiSettings.EnableSummaryLog; nkitConvert.Settings.FullVerify = guiSettings.FullVerify; nkitConvert.Settings.NkitReencode = guiSettings.NkitReencode; nkitConvert.Settings.NkitUpdatePartitionRemoval = guiSettings.NkitUpdatePartitionRemoval; nkitConvert.Settings.TestMode = guiSettings.TestMode; nkitConvert.Settings.MaskRename = guiSettings.MaskRename; nkitConvert.Settings.RecoveryMatchFailDelete = guiSettings.RecoveryMatchFailDelete; if (nkitConvert.Settings.DiscType == DiscType.GameCube) { nkitConvert.Settings.RedumpMatchRenameToMask = guiSettings.Masks["GameCube:RedumpMatchRenameToMask"]; nkitConvert.Settings.CustomMatchRenameToMask = guiSettings.Masks["GameCube:CustomMatchRenameToMask"]; nkitConvert.Settings.MatchFailRenameToMask = guiSettings.Masks["GameCube:MatchFailRenameToMask"]; } else { nkitConvert.Settings.RedumpMatchRenameToMask = guiSettings.Masks["Wii:RedumpMatchRenameToMask"]; nkitConvert.Settings.CustomMatchRenameToMask = guiSettings.Masks["Wii:CustomMatchRenameToMask"]; nkitConvert.Settings.MatchFailRenameToMask = guiSettings.Masks["Wii:MatchFailRenameToMask"]; } nkitConvert.LogMessage += NkitConvert_LogMessage; nkitConvert.LogProgress += NkitConvert_LogProgress; pf.Log = ""; switch (convertMode) { case 1: //Recover to ISO pf.Results = nkitConvert.RecoverToIso(); break; case 2: //Recover to Nkit.iso nkitConvert.Settings.NkitFormat = NkitFormatType.Iso; pf.Results = nkitConvert.RecoverToNkit(); break; case 3: //Recover to Nkit.gcz nkitConvert.Settings.NkitFormat = NkitFormatType.Gcz; pf.Results = nkitConvert.RecoverToNkit(); break; case 4: //Convert to .iso pf.Results = nkitConvert.ConvertToIso(); break; case 5: //Convert to Nkit.iso nkitConvert.Settings.NkitFormat = NkitFormatType.Iso; pf.Results = nkitConvert.ConvertToNkit(); break; case 6: //Convert to Nkit.gcz nkitConvert.Settings.NkitFormat = NkitFormatType.Gcz; pf.Results = nkitConvert.ConvertToNkit(); break; } } catch (Exception ex) { try { HandledException hex = ex as HandledException; if (hex == null && ex is AggregateException) { hex = (HandledException)((AggregateException)ex).InnerExceptions.FirstOrDefault(a => a is HandledException); } pf.Log += string.Format("Failed{0}-------{0}{1}", Environment.NewLine, hex != null ? hex.FriendlyErrorMessage : ex.Message); } catch { } } finally { exitLoop = !completedItem(item); if (nkitConvert != null) { nkitConvert.LogMessage -= NkitConvert_LogMessage; nkitConvert.LogProgress -= NkitConvert_LogProgress; } } if (exitLoop) { break; } } })); }
private OutputResults process(string conversion, SourceFile sourceFile, bool renameWithMasks, bool toNkit, NkitFormatType nkitFormat, bool isRecovery, bool fullVerify, bool calcHashes, bool testMode, Func <NStream, IEnumerable <Processor> > passes) { OutputResults results = null; NStream nstream = _nstream; string lastTmp = null; string tmp = null; ConvertionName = conversion; try { SourceFile sf = null; long sourceSize = nstream.SourceSize; _context = new Context(); _context.Initialise(ConvertionName, sourceFile, _settings, true, isRecovery, nstream.IsGameCube, nstream.Id8, this); List <Processor> processors = passes(nstream).Where(a => a != null).ToList(); if (nkitFormat == NkitFormatType.Gcz) { processors.Add(new Processor(new IsoReader(), new GczWriter(), "To GCZ", this, false, true, ProcessorSizeMode.Stream)); } if (calcHashes) { processors.Add(new Processor(new IsoReader(), new HashWriter(), "Calc Hashes", this, false, true, ProcessorSizeMode.Stream)); } if (fullVerify) { if (!toNkit) { processors.Add(new Processor(new IsoReader(), new VerifyWriter(), "Full Verify", this, false, true, ProcessorSizeMode.Stream)); } else { processors.Add(new Processor(nstream.IsGameCube ? new NkitReaderGc() : (IReader) new NkitReaderWii(), new VerifyWriter(), "NKit Verify", this, true, true, ProcessorSizeMode.Image)); } processors.Last().Writer.RequireVerifyCrc = true; processors.Last().Writer.VerifyIsWrite = true; //read verify } _totalPasses = processors.Count(); if (processors.Count == 0) { return(null); } DateTime dt = DateTime.Now; _completedPasses = 0; Log("PROCESSING" + (testMode ? " [TEST MODE]" : ((_context.Settings.DeleteSource ? " [DELETE SOURCE]" : "")))); Log("-------------------------------------------------------------------------------"); if (_forcedWiiFullNkitRebuild) { LogBlank(); Log(string.Format("Nkit Reencode forced: NkitUpdatePartitionRemoval is {0} and source image has {1} Update Partition", _context.Settings.NkitUpdatePartitionRemoval.ToString(), nstream.IsNkitUpdateRemoved ? "no" : "an")); LogBlank(); } Log(string.Format("{0} [{1}] {2} [MiB:{3,2:#.0}]", friendly(nstream.Title), friendly(nstream.Id), nstream.IsGameCube ? "GameCube" : "Wii", (sourceSize / (double)(1024 * 1024)))); LogBlank(); string passesText = getPassesLine(nstream, processors); Log(passesText); int i = 1; foreach (Processor pro in processors.Where(pro => pro != null)) { LogDebug(string.Format("Pass {0}: {1}", (i++).ToString(), pro.ToString())); } LogBlank(); foreach (Processor pro in processors) { //sort out temp file and open input as nstream each time //raise progress and output messages from processors if (sf != null) { nstream = sf.OpenNStream(!(pro.Writer is HashWriter)); //if hashWriter then read as raw file sf = null; } tmp = null; FileStream tmpFs = null; try { if (pro.HasWriteStream) { tmp = Path.Combine(_context.Settings.TempPath, Path.GetFileName(Path.GetTempFileName())); if (!Directory.Exists(_context.Settings.TempPath)) { Directory.CreateDirectory(_context.Settings.TempPath); } tmpFs = File.Create(tmp, 0x400 * 0x400 * 4, FileOptions.SequentialScan); } _logCache = new List <Tuple <string, LogMessageType> >(); OutputResults nr = pro.Process(_context, nstream, tmpFs ?? Stream.Null); _logCache = null; if (results == null) { results = nr; results.DiscType = nstream.IsGameCube ? DiscType.GameCube : DiscType.Wii; results.InputFileName = sourceFile.AllFiles.Length != 0 ? sourceFile.AllFiles[0] : sourceFile.FilePath; results.InputDiscNo = nstream.DiscNo; results.InputDiscVersion = nstream.Version; results.InputTitle = nstream.Title; results.InputId8 = nstream.Id8; results.InputSize = sourceSize; results.FullSize = nstream.ImageSize; results.Passes = passesText; if (pro.IsVerify) { results.OutputSize = results.InputSize; } } else if (pro.Writer is HashWriter) //hash writer gives no meaningful info back other than md5 and sha1 (the crc is forced when nkit, so ignore) { results.OutputMd5 = nr.OutputMd5; results.OutputSha1 = nr.OutputSha1; } else { if (nr.AliasJunkId != null) { results.AliasJunkId = nr.AliasJunkId; } if (nr.OutputTitle != null) { results.OutputDiscNo = nr.OutputDiscNo; results.OutputDiscVersion = nr.OutputDiscVersion; results.OutputTitle = nr.OutputTitle; } results.OutputId8 = nr.OutputId8; results.OutputCrc = nr.OutputCrc; results.OutputPrePatchCrc = nr.OutputPrePatchCrc; results.FullSize = nstream.ImageSize; if (tmp != null) { results.OutputSize = nr.OutputSize; } if (nr.ValidationCrc != 0 && results.VerifyCrc != 0) { results.VerifyCrc = 0; //blank verify if a new ValidationCrc is set - verification happened when both != 0 } if (nr.VerifyCrc != 0) { results.VerifyCrc = nr.VerifyCrc; } if (nr.ValidationCrc != 0) { results.ValidationCrc = nr.ValidationCrc; } if (nr.ValidateReadResult != VerifyResult.Unverified) { results.ValidateReadResult = nr.ValidateReadResult; } if (nr.VerifyOutputResult != VerifyResult.Unverified) { if (results.ValidateReadResult == VerifyResult.Unverified && nstream.IsNkit) { results.ValidateReadResult = nr.VerifyOutputResult; } results.VerifyOutputResult = nr.VerifyOutputResult; } if (nr.IsRecoverable) { results.IsRecoverable = nr.IsRecoverable; } } } finally { if (tmpFs != null) { tmpFs.Dispose(); } nstream.Close(); } if (lastTmp != null && tmp != null) { File.Delete(lastTmp); } //handle failures well if (results.ValidateReadResult == VerifyResult.VerifyFailed || results.VerifyOutputResult == VerifyResult.VerifyFailed) { lastTmp = tmp; //keep post loop happy break; } if (_completedPasses != _totalPasses) //last item { sf = SourceFiles.OpenFile(tmp ?? lastTmp); } if (tmp != null) { lastTmp = tmp; } } TimeSpan ts = DateTime.Now - dt; results.ProcessingTime = ts; //FAIL if (results.ValidateReadResult == VerifyResult.VerifyFailed || results.VerifyOutputResult == VerifyResult.VerifyFailed) { LogBlank(); Log(string.Format("Verification Failed Crc:{0} - Failed Test Crc:{1}", results.OutputCrc.ToString("X8"), results.ValidationCrc.ToString("X8"))); if (lastTmp != null) //only null when verify only { Log("Deleting Output" + (Settings.OutputLevel != 3 ? "" : " (Skipped as OutputLevel is 3:Debug)")); results.OutputFileName = null; if (Settings.OutputLevel != 3) { File.Delete(lastTmp); } LogBlank(); } } else //SUCCESS { LogBlank(); Log(string.Format("Completed ~ {0}m {1}s [MiB:{2:#.0}]", ((int)ts.TotalMinutes).ToString(), ts.Seconds.ToString(), (results.OutputSize / (double)(1024 * 1024)))); LogBlank(); Log("RESULTS"); Log("-------------------------------------------------------------------------------"); uint finalCrc = results.ValidationCrc != 0 ? results.ValidationCrc : results.OutputCrc; string mask = _context.Settings.MatchFailRenameToMask; results.OutputFileExt = "." + SourceFiles.ExtensionString(false, false, toNkit, nkitFormat == NkitFormatType.Gcz).ToLower(); results.RedumpInfo = _context.Dats.GetRedumpEntry(_context.Settings, _context.Dats, finalCrc); if (results.RedumpInfo.MatchType == MatchType.Redump || results.RedumpInfo.MatchType == MatchType.Custom) { Log(string.Format("{0} [{1} Name]", results.RedumpInfo.MatchName, results.RedumpInfo.MatchType.ToString())); if (results.IsRecoverable) { Log(string.Format("Missing Recovery data is required to correctly restore this image!", results.RedumpInfo.MatchName, results.RedumpInfo.MatchType.ToString())); } mask = results.RedumpInfo.MatchType == MatchType.Custom ? _context.Settings.CustomMatchRenameToMask : _context.Settings.RedumpMatchRenameToMask; } else { Log(string.Format("CRC {0} not in Redump or Custom Dat", finalCrc.ToString("X8"))); } LogBlank(); outputResults(results); if (lastTmp != null) //only null when verify only { if (testMode) { Log("TestMode: Deleting Output"); results.OutputFileName = null; if (File.Exists(lastTmp)) { File.Delete(lastTmp); } } else if (isRecovery && _context.Settings.RecoveryMatchFailDelete && results.RedumpInfo.MatchType == MatchType.MatchFail) { Log("Failed to Recover to Dat Entry: Deleting Output"); results.OutputFileName = null; File.Delete(lastTmp); } else { if (renameWithMasks) { results.OutputFileName = _context.Dats.GetFilename(results, mask); Log("Renaming Output Using Masks"); } else { results.OutputFileName = SourceFiles.GetUniqueName(sourceFile.CreateOutputFilename(results.OutputFileExt)); Log("Renaming Output Based on Source File" + (sourceFile.AllFiles.Count() > 1 ? "s" : "")); } LogBlank(); string path = Path.GetDirectoryName(results.OutputFileName); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } File.Move(lastTmp, results.OutputFileName); Log(string.Format("Output: {0}", Path.GetDirectoryName(results.OutputFileName))); Log(string.Format(" {0}", Path.GetFileName(results.OutputFileName))); //double check test mode just to be sure if (_context.Settings.DeleteSource && !testMode && results.VerifyOutputResult == VerifyResult.VerifySuccess) { LogBlank(); Log("Deleting Source:"); foreach (string s in sourceFile.AllFiles.Length == 0 ? new string[] { sourceFile.FilePath } : sourceFile.AllFiles) { Log(string.Format(" {0}", s)); File.Delete(s); } } } LogBlank(); } } } catch (Exception ex) { try { if (lastTmp == null) { lastTmp = tmp; } if (lastTmp != null) { LogBlank(); Log("Deleting Output" + (Settings.OutputLevel != 3 ? "" : " (Skipped as OutputLevel is 3:Debug)")); if (results != null) { results.OutputFileName = null; } if (Settings.OutputLevel != 3) { File.Delete(lastTmp); } } } catch { } if (_context.Settings.EnableSummaryLog) { if (results == null) { results = new OutputResults { Conversion = ConvertionName, DiscType = (nstream?.IsGameCube ?? true) ? DiscType.GameCube : DiscType.Wii, InputFileName = (sourceFile?.AllFiles?.Length ?? 0) == 0 ? (sourceFile?.FilePath ?? "") : (sourceFile?.AllFiles.FirstOrDefault() ?? ""), InputDiscNo = nstream?.DiscNo ?? 0, InputDiscVersion = nstream?.Version ?? 0, InputTitle = nstream?.Title ?? "", InputId8 = nstream?.Id8 ?? "", InputSize = sourceFile?.Length ?? 0 }; } results.VerifyOutputResult = VerifyResult.Error; HandledException hex = ex as HandledException; if (hex == null) { hex = new HandledException(ex, "Unhandled Exception"); } results.ErrorMessage = hex.FriendlyErrorMessage; } throw; } finally { if (_context.Settings.EnableSummaryLog) { summaryLog(_context.Settings, results); Log("Summary Log Written" + (results.VerifyOutputResult != VerifyResult.Error ? "" : " as Errored!")); LogBlank(); } } return(results); }
private static IEnumerable <SourceFile> buildCollection(List <string> files) { List <SourceFile> srcFiles = new List <SourceFile>(); long length; List <string> firstParts = new List <string>(); firstParts = files.Where(a => Regex.IsMatch(a, @"\.(part0*1\.rar|z01|001|r00|wbf1)$")).ToList(); //get multi file sets foreach (string s in firstParts) { length = 0; try { Match m = Regex.Match(s.ToLower(), @"^(.*\.)(part0*1\.rar|z01|001|r00|wbf1)$"); if (m.Success) { string firstName = Regex.Replace(s, @".r00$", ".rar", RegexOptions.IgnoreCase); firstName = Regex.Replace(firstName, @".wbf1$", ".wbfs", RegexOptions.IgnoreCase); List <string> parts = files.Where(a => string.Compare(firstName, a, true) != 0 && a.Length == s.Length && a.ToLower().StartsWith(m.Groups[1].Value)).OrderBy(a => a).ToList(); if (parts.Count != 0) { parts.Insert(0, firstName); } SourceFile sf = new SourceFile() { Name = Path.GetFileName(firstName), Path = Path.GetDirectoryName(firstName), FilePath = firstName, AllFiles = parts.ToArray(), IsSplit = firstName.EndsWith(".001") || firstName.ToLower().EndsWith("wbfs") }; srcFiles.Add(sf); files.RemoveAll(a => sf.AllFiles.Contains(a)); //relies on ToLower used above foreach (FileInfo fi in sf.AllFiles.Select(a => new FileInfo(a))) { length += fi.Length; } sf.Length = length; } } catch (Exception ex) { throw new HandledException(ex, "SourceFiles.buildCollection failed on '{0}' getting multi file sets", s ?? ""); } } //get single file sets foreach (string fn in files.Where(a => Regex.IsMatch(Path.GetExtension(a), @"\.(gcz|gcm|iso|dec|wbfs|zip|rar|7z|gz|z)(:?_[0-9]*)?$", RegexOptions.IgnoreCase))) { try { SourceFile sf = new SourceFile() { Name = Path.GetFileName(fn), Path = Path.GetDirectoryName(fn), FilePath = fn, AllFiles = new string[0], IsSplit = false, Length = (new FileInfo(fn)).Length }; srcFiles.Add(sf); } catch (Exception ex) { throw new HandledException(ex, "SourceFiles.buildCollection failed on '{0}' getting single file info", fn ?? ""); } } //get files from archives for (int i = srcFiles.Count - 1; i >= 0; i--) { try { string[] arcs = GetArchiveFiles(srcFiles[i]); if (arcs == null) { continue; //not archive, ignore } else if (arcs.Length == 0) //archive with no valid files { srcFiles.RemoveAt(i); } else { for (int j = 0; j < arcs.Length; j++) { if (j == 0) { srcFiles[i].IsArchive = true; srcFiles[i].Name = Path.GetFileName(arcs[j]); srcFiles[i].Path = Path.GetDirectoryName(arcs[j]); } else { SourceFile sf = new SourceFile() { IsArchive = srcFiles[i].IsArchive, Name = Path.GetFileName(arcs[j]), Path = Path.GetDirectoryName(arcs[j]), FilePath = srcFiles[i].FilePath, AllFiles = srcFiles[i].AllFiles, IsSplit = srcFiles[i].IsSplit, Length = srcFiles[i].Length }; srcFiles.Add(sf); } } } } catch (Exception ex) { throw new HandledException(ex, "SourceFiles.buildCollection failed on '{0}' listing files from archive", (srcFiles[i]?.FilePath) ?? ""); } } int idx = 0; foreach (SourceFile f in srcFiles.OrderBy(a => a.Name)) { f.Index = idx++; f.TotalFiles = srcFiles.Count; yield return(f); } }