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; this.ConvertionName = conversion; try { SourceFile sf = null; long sourceSize = nstream.SourceSize; _context = new Context(); _context.Initialise(this.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(); results.Conversion = this.ConvertionName; results.DiscType = (nstream?.IsGameCube ?? true) ? DiscType.GameCube : DiscType.Wii; results.InputFileName = (sourceFile?.AllFiles?.Length ?? 0) == 0 ? (sourceFile?.FilePath ?? "") : (sourceFile?.AllFiles.FirstOrDefault() ?? ""); results.InputDiscNo = nstream?.DiscNo ?? 0; results.InputDiscVersion = nstream?.Version ?? 0; results.InputTitle = nstream?.Title ?? ""; results.InputId8 = nstream?.Id8 ?? ""; results.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); }
public string ExtensionString() { return(SourceFiles.ExtensionString(_isIsoDec, _isWbfs, _isNkit, _isGcz)); }