diff --git a/CHANGELIST.md b/CHANGELIST.md index f27171e2..955b3cd0 100644 --- a/CHANGELIST.md +++ b/CHANGELIST.md @@ -15,6 +15,7 @@ - Fix reversed ringcode test - Add C#12 syntax to tests - Trim PS3 serial and add unrelated notes +- Update RedumpLib and use moved methods ### 3.0.0 (2023-11-14) diff --git a/MPF.Check/MPF.Check.csproj b/MPF.Check/MPF.Check.csproj index df6cfa0d..fae5d17d 100644 --- a/MPF.Check/MPF.Check.csproj +++ b/MPF.Check/MPF.Check.csproj @@ -34,7 +34,7 @@ runtime; compile; build; native; analyzers; buildtransitive - + diff --git a/MPF.Core/Data/Constants.cs b/MPF.Core/Data/Constants.cs index 2700e9bd..973a695f 100644 --- a/MPF.Core/Data/Constants.cs +++ b/MPF.Core/Data/Constants.cs @@ -56,71 +56,11 @@ namespace MPF.Core.Data } } - // Moved to RedumpLib /// /// Template field values for submission info /// public static class Template { - // Manual information - - public const string TitleField = "Title"; - public const string ForeignTitleField = "Foreign Title (Non-latin)"; - public const string DiscNumberField = "Disc Number / Letter"; - public const string DiscTitleField = "Disc Title"; - public const string SystemField = "System"; - public const string MediaTypeField = "Media Type"; - public const string CategoryField = "Category"; - public const string RegionField = "Region"; - public const string LanguagesField = "Languages"; - public const string PlaystationLanguageSelectionViaField = "Language Selection Via"; - public const string DiscSerialField = "Disc Serial"; - public const string BarcodeField = "Barcode"; - public const string CommentsField = "Comments"; - public const string ContentsField = "Contents"; - public const string VersionField = "Version"; - public const string EditionField = "Edition/Release"; - public const string PlayStation3WiiDiscKeyField = "Disc Key"; - public const string PlayStation3DiscIDField = "Disc ID"; - public const string GameCubeWiiBCAField = "BCA"; - public const string CopyProtectionField = "Copy Protection"; - public const string MasteringRingField = "Mastering Code (laser branded/etched)"; - public const string MasteringSIDField = "Mastering SID Code"; - public const string MouldSIDField = "Mould SID Code"; - public const string AdditionalMouldField = "Additional Mould"; - public const string ToolstampField = "Toolstamp or Mastering Code (engraved/stamped)"; - - // Automatic Information - - public const string DumpingProgramField = "Dumping Program"; - public const string DumpingDateField = "Date"; - public const string DumpingDriveManufacturer = "Manufacturer"; - public const string DumpingDriveModel = "Model"; - public const string DumpingDriveFirmware = "Firmware"; - public const string ReportedDiscType = "Reported Disc Type"; - public const string PVDField = "Primary Volume Descriptor (PVD)"; - public const string DATField = "DAT"; - public const string SizeField = "Size"; - public const string CRC32Field = "CRC32"; - public const string MD5Field = "MD5"; - public const string SHA1Field = "SHA1"; - public const string FullyMatchingIDField = "Fully Matching ID"; - public const string PartiallyMatchingIDsField = "Partially Matching IDs"; - public const string ErrorCountField = "Error Count"; - public const string CuesheetField = "Cuesheet"; - public const string SubIntentionField = "SubIntention Data (SecuROM/LibCrypt)"; - public const string WriteOffsetField = "Write Offset"; - public const string LayerbreakField = "Layerbreak"; - public const string EXEDateBuildDate = "EXE/Build Date"; - public const string HeaderField = "Header"; - public const string PICField = "Permanent Information & Control (PIC)"; - public const string PlayStationEDCField = "EDC"; - public const string PlayStationAntiModchipField = "Anti-modchip"; - public const string PlayStationLibCryptField = "LibCrypt"; - public const string XBOXSSRanges = "Security Sector Ranges"; - - // Default values - public const string RequiredValue = "(REQUIRED)"; public const string RequiredIfExistsValue = "(REQUIRED, IF EXISTS)"; public const string OptionalValue = "(OPTIONAL)"; diff --git a/MPF.Core/DumpEnvironment.cs b/MPF.Core/DumpEnvironment.cs index 8f229c45..ec377934 100644 --- a/MPF.Core/DumpEnvironment.cs +++ b/MPF.Core/DumpEnvironment.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using MPF.Core.Data; using MPF.Core.Modules; using MPF.Core.Utilities; +using SabreTools.RedumpLib; using SabreTools.RedumpLib.Data; namespace MPF.Core @@ -328,7 +329,7 @@ namespace MPF.Core if (seedInfo != null) { resultProgress?.Report(Result.Success("Injecting user-supplied information...")); - SubmissionInfoTool.InjectSubmissionInformation(submissionInfo, seedInfo); + Builder.InjectSubmissionInformation(submissionInfo, seedInfo); resultProgress?.Report(Result.Success("Information injection complete!")); } @@ -370,12 +371,12 @@ namespace MPF.Core // Process special fields for site codes resultProgress?.Report(Result.Success("Processing site codes...")); - InfoTool.ProcessSpecialFields(submissionInfo); + Formatter.ProcessSpecialFields(submissionInfo); resultProgress?.Report(Result.Success("Processing complete!")); // Format the information for the text output resultProgress?.Report(Result.Success("Formatting information...")); - (var formattedValues, var formatResult) = InfoTool.FormatOutputData(submissionInfo, Options); + (var formattedValues, var formatResult) = Formatter.FormatOutputData(submissionInfo, Options.EnableRedumpCompatibility); if (formattedValues == null) resultProgress?.Report(Result.Success(formatResult)); else diff --git a/MPF.Core/InfoTool.cs b/MPF.Core/InfoTool.cs index 878f6fb2..a0222f24 100644 --- a/MPF.Core/InfoTool.cs +++ b/MPF.Core/InfoTool.cs @@ -1241,371 +1241,6 @@ namespace MPF.Core } } - // Moved to RedumpLib - /// - /// Format the output data in a human readable way, separating each printed line into a new item in the list - /// - /// Information object that should contain normalized values - /// Options object representing user-defined options - /// List of strings representing each line of an output file, null on error - public static (List?, string?) FormatOutputData(SubmissionInfo? info, Data.Options options) - { - // Check to see if the inputs are valid - if (info == null) - return (null, "Submission information was missing"); - - try - { - // Sony-printed discs have layers in the opposite order - var system = info.CommonDiscInfo?.System; - bool reverseOrder = system.HasReversedRingcodes(); - - // Preamble for submission -#pragma warning disable IDE0028 - var output = new List - { - "Users who wish to submit this information to Redump must ensure that all of the fields below are accurate for the exact media they have.", - "Please double-check to ensure that there are no fields that need verification, such as the version or copy protection.", - "If there are no fields in need of verification or all fields are accurate, this preamble can be removed before submission.", - "", - }; - - // Common Disc Info section - output.Add("Common Disc Info:"); - AddIfExists(output, Template.TitleField, info.CommonDiscInfo?.Title, 1); - AddIfExists(output, Template.ForeignTitleField, info.CommonDiscInfo?.ForeignTitleNonLatin, 1); - AddIfExists(output, Template.DiscNumberField, info.CommonDiscInfo?.DiscNumberLetter, 1); - AddIfExists(output, Template.DiscTitleField, info.CommonDiscInfo?.DiscTitle, 1); - AddIfExists(output, Template.SystemField, info.CommonDiscInfo?.System.LongName(), 1); - AddIfExists(output, Template.MediaTypeField, GetFixedMediaType( - info.CommonDiscInfo?.Media.ToMediaType(), - info.SizeAndChecksums?.PICIdentifier, - info.SizeAndChecksums?.Size, - info.SizeAndChecksums?.Layerbreak, - info.SizeAndChecksums?.Layerbreak2, - info.SizeAndChecksums?.Layerbreak3), - 1); - AddIfExists(output, Template.CategoryField, info.CommonDiscInfo?.Category.LongName(), 1); - AddIfExists(output, Template.FullyMatchingIDField, info.FullyMatchedID?.ToString(), 1); - AddIfExists(output, Template.PartiallyMatchingIDsField, info.PartiallyMatchedIDs, 1); - AddIfExists(output, Template.RegionField, info.CommonDiscInfo?.Region.LongName() ?? "SPACE! (CHANGE THIS)", 1); - AddIfExists(output, Template.LanguagesField, (info.CommonDiscInfo?.Languages ?? [null]).Select(l => l.LongName() ?? "SILENCE! (CHANGE THIS)").ToArray(), 1); - AddIfExists(output, Template.PlaystationLanguageSelectionViaField, (info.CommonDiscInfo?.LanguageSelection ?? []).Select(l => l.LongName()).ToArray(), 1); - AddIfExists(output, Template.DiscSerialField, info.CommonDiscInfo?.Serial, 1); - - // All ringcode information goes in an indented area - output.Add(""); output.Add("\tRingcode Information:"); output.Add(""); - - // If we have a triple-layer disc - if (info.SizeAndChecksums?.Layerbreak3 != default && info.SizeAndChecksums?.Layerbreak3 != default(long)) - { - AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.MasteringRingField, info.CommonDiscInfo?.Layer0MasteringRing, 0); - AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.MasteringSIDField, info.CommonDiscInfo?.Layer0MasteringSID, 0); - AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.ToolstampField, info.CommonDiscInfo?.Layer0ToolstampMasteringCode, 0); - AddIfExists(output, "Data Side " + Template.MouldSIDField, info.CommonDiscInfo?.Layer0MouldSID, 0); - AddIfExists(output, "Data Side " + Template.AdditionalMouldField, info.CommonDiscInfo?.Layer0AdditionalMould, 0); - - AddIfExists(output, "Layer 1 " + Template.MasteringRingField, info.CommonDiscInfo?.Layer1MasteringRing, 0); - AddIfExists(output, "Layer 1 " + Template.MasteringSIDField, info.CommonDiscInfo?.Layer1MasteringSID, 0); - AddIfExists(output, "Layer 1 " + Template.ToolstampField, info.CommonDiscInfo?.Layer1ToolstampMasteringCode, 0); - AddIfExists(output, "Label Side " + Template.MouldSIDField, info.CommonDiscInfo?.Layer1MouldSID, 0); - AddIfExists(output, "Label Side " + Template.AdditionalMouldField, info.CommonDiscInfo?.Layer1AdditionalMould, 0); - - AddIfExists(output, "Layer 2 " + Template.MasteringRingField, info.CommonDiscInfo?.Layer2MasteringRing, 0); - AddIfExists(output, "Layer 2 " + Template.MasteringSIDField, info.CommonDiscInfo?.Layer2MasteringSID, 0); - AddIfExists(output, "Layer 2 " + Template.ToolstampField, info.CommonDiscInfo?.Layer2ToolstampMasteringCode, 0); - - AddIfExists(output, (reverseOrder ? "Layer 3 (Inner) " : "Layer 3 (Outer) ") + Template.MasteringRingField, info.CommonDiscInfo?.Layer3MasteringRing, 0); - AddIfExists(output, (reverseOrder ? "Layer 3 (Inner) " : "Layer 3 (Outer) ") + Template.MasteringSIDField, info.CommonDiscInfo?.Layer3MasteringSID, 0); - AddIfExists(output, (reverseOrder ? "Layer 3 (Inner) " : "Layer 3 (Outer) ") + Template.ToolstampField, info.CommonDiscInfo?.Layer3ToolstampMasteringCode, 0); - } - // If we have a triple-layer disc - else if (info.SizeAndChecksums?.Layerbreak2 != default && info.SizeAndChecksums?.Layerbreak2 != default(long)) - { - AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.MasteringRingField, info.CommonDiscInfo?.Layer0MasteringRing, 0); - AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.MasteringSIDField, info.CommonDiscInfo?.Layer0MasteringSID, 0); - AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.ToolstampField, info.CommonDiscInfo?.Layer0ToolstampMasteringCode, 0); - AddIfExists(output, "Data Side " + Template.MouldSIDField, info.CommonDiscInfo?.Layer0MouldSID, 0); - AddIfExists(output, "Data Side " + Template.AdditionalMouldField, info.CommonDiscInfo?.Layer0AdditionalMould, 0); - - AddIfExists(output, "Layer 1 " + Template.MasteringRingField, info.CommonDiscInfo?.Layer1MasteringRing, 0); - AddIfExists(output, "Layer 1 " + Template.MasteringSIDField, info.CommonDiscInfo?.Layer1MasteringSID, 0); - AddIfExists(output, "Layer 1 " + Template.ToolstampField, info.CommonDiscInfo?.Layer1ToolstampMasteringCode, 0); - AddIfExists(output, "Label Side " + Template.MouldSIDField, info.CommonDiscInfo?.Layer1MouldSID, 0); - AddIfExists(output, "Label Side " + Template.AdditionalMouldField, info.CommonDiscInfo?.Layer1AdditionalMould, 0); - - AddIfExists(output, (reverseOrder ? "Layer 2 (Inner) " : "Layer 2 (Outer) ") + Template.MasteringRingField, info.CommonDiscInfo?.Layer2MasteringRing, 0); - AddIfExists(output, (reverseOrder ? "Layer 2 (Inner) " : "Layer 2 (Outer) ") + Template.MasteringSIDField, info.CommonDiscInfo?.Layer2MasteringSID, 0); - AddIfExists(output, (reverseOrder ? "Layer 2 (Inner) " : "Layer 2 (Outer) ") + Template.ToolstampField, info.CommonDiscInfo?.Layer2ToolstampMasteringCode, 0); - } - // If we have a dual-layer disc - else if (info.SizeAndChecksums?.Layerbreak != default && info.SizeAndChecksums?.Layerbreak != default(long)) - { - AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.MasteringRingField, info.CommonDiscInfo?.Layer0MasteringRing, 0); - AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.MasteringSIDField, info.CommonDiscInfo?.Layer0MasteringSID, 0); - AddIfExists(output, (reverseOrder ? "Layer 0 (Outer) " : "Layer 0 (Inner) ") + Template.ToolstampField, info.CommonDiscInfo?.Layer0ToolstampMasteringCode, 0); - AddIfExists(output, "Data Side " + Template.MouldSIDField, info.CommonDiscInfo?.Layer0MouldSID, 0); - AddIfExists(output, "Data Side " + Template.AdditionalMouldField, info.CommonDiscInfo?.Layer0AdditionalMould, 0); - - AddIfExists(output, (reverseOrder ? "Layer 1 (Inner) " : "Layer 1 (Outer) ") + Template.MasteringRingField, info.CommonDiscInfo?.Layer1MasteringRing, 0); - AddIfExists(output, (reverseOrder ? "Layer 1 (Inner) " : "Layer 1 (Outer) ") + Template.MasteringSIDField, info.CommonDiscInfo?.Layer1MasteringSID, 0); - AddIfExists(output, (reverseOrder ? "Layer 1 (Inner) " : "Layer 1 (Outer) ") + Template.ToolstampField, info.CommonDiscInfo?.Layer1ToolstampMasteringCode, 0); - AddIfExists(output, "Label Side " + Template.MouldSIDField, info.CommonDiscInfo?.Layer1MouldSID, 0); - AddIfExists(output, "Label Side " + Template.AdditionalMouldField, info.CommonDiscInfo?.Layer1AdditionalMould, 0); - } - // If we have a single-layer disc - else - { - AddIfExists(output, "Data Side " + Template.MasteringRingField, info.CommonDiscInfo?.Layer0MasteringRing, 0); - AddIfExists(output, "Data Side " + Template.MasteringSIDField, info.CommonDiscInfo?.Layer0MasteringSID, 0); - AddIfExists(output, "Data Side " + Template.ToolstampField, info.CommonDiscInfo?.Layer0ToolstampMasteringCode, 0); - AddIfExists(output, "Data Side " + Template.MouldSIDField, info.CommonDiscInfo?.Layer0MouldSID, 0); - AddIfExists(output, "Data Side " + Template.AdditionalMouldField, info.CommonDiscInfo?.Layer0AdditionalMould, 0); - - AddIfExists(output, "Label Side " + Template.MasteringRingField, info.CommonDiscInfo?.Layer1MasteringRing, 0); - AddIfExists(output, "Label Side " + Template.MasteringSIDField, info.CommonDiscInfo?.Layer1MasteringSID, 0); - AddIfExists(output, "Label Side " + Template.ToolstampField, info.CommonDiscInfo?.Layer1ToolstampMasteringCode, 0); - AddIfExists(output, "Label Side " + Template.MouldSIDField, info.CommonDiscInfo?.Layer1MouldSID, 0); - AddIfExists(output, "Label Side " + Template.AdditionalMouldField, info.CommonDiscInfo?.Layer1AdditionalMould, 0); - } - - output.Add(""); - AddIfExists(output, Template.BarcodeField, info.CommonDiscInfo?.Barcode, 1); - AddIfExists(output, Template.EXEDateBuildDate, info.CommonDiscInfo?.EXEDateBuildDate, 1); - AddIfExists(output, Template.ErrorCountField, info.CommonDiscInfo?.ErrorsCount, 1); - AddIfExists(output, Template.CommentsField, info.CommonDiscInfo?.Comments?.Trim(), 1); - AddIfExists(output, Template.ContentsField, info.CommonDiscInfo?.Contents?.Trim(), 1); - - // Version and Editions section - output.Add(""); output.Add("Version and Editions:"); - AddIfExists(output, Template.VersionField, info.VersionAndEditions?.Version, 1); - AddIfExists(output, Template.EditionField, info.VersionAndEditions?.OtherEditions, 1); - - // EDC section - if (info.CommonDiscInfo?.System == RedumpSystem.SonyPlayStation) - { - output.Add(""); output.Add("EDC:"); - AddIfExists(output, Template.PlayStationEDCField, info.EDC?.EDC.LongName(), 1); - } - - // Parent/Clone Relationship section - // output.Add(""); output.Add("Parent/Clone Relationship:"); - // AddIfExists(output, Template.ParentIDField, info.ParentID); - // AddIfExists(output, Template.RegionalParentField, info.RegionalParent.ToString()); - - // Extras section - if (info.Extras?.PVD != null || info.Extras?.PIC != null || info.Extras?.BCA != null || info.Extras?.SecuritySectorRanges != null) - { - output.Add(""); output.Add("Extras:"); - AddIfExists(output, Template.PVDField, info.Extras.PVD?.Trim(), 1); - AddIfExists(output, Template.PlayStation3WiiDiscKeyField, info.Extras.DiscKey, 1); - AddIfExists(output, Template.PlayStation3DiscIDField, info.Extras.DiscID, 1); - AddIfExists(output, Template.PICField, info.Extras.PIC, 1); - AddIfExists(output, Template.HeaderField, info.Extras.Header, 1); - AddIfExists(output, Template.GameCubeWiiBCAField, info.Extras.BCA, 1); - AddIfExists(output, Template.XBOXSSRanges, info.Extras.SecuritySectorRanges, 1); - } - - // Copy Protection section - if (!string.IsNullOrWhiteSpace(info.CopyProtection?.Protection) - || (info.CopyProtection?.AntiModchip != null && info.CopyProtection.AntiModchip != YesNo.NULL) - || (info.CopyProtection?.LibCrypt != null && info.CopyProtection.LibCrypt != YesNo.NULL) - || !string.IsNullOrWhiteSpace(info.CopyProtection?.LibCryptData) - || !string.IsNullOrWhiteSpace(info.CopyProtection?.SecuROMData)) - { - output.Add(""); output.Add("Copy Protection:"); - if (info.CommonDiscInfo?.System == RedumpSystem.SonyPlayStation) - { - AddIfExists(output, Template.PlayStationAntiModchipField, info.CopyProtection!.AntiModchip.LongName(), 1); - AddIfExists(output, Template.PlayStationLibCryptField, info.CopyProtection.LibCrypt.LongName(), 1); - AddIfExists(output, Template.SubIntentionField, info.CopyProtection.LibCryptData, 1); - } - - AddIfExists(output, Template.CopyProtectionField, info.CopyProtection!.Protection, 1); - AddIfExists(output, Template.SubIntentionField, info.CopyProtection.SecuROMData, 1); - } - - // Dumpers and Status section - // output.Add(""); output.Add("Dumpers and Status"); - // AddIfExists(output, Template.StatusField, info.Status.Name()); - // AddIfExists(output, Template.OtherDumpersField, info.OtherDumpers); - - // Tracks and Write Offsets section - if (!string.IsNullOrWhiteSpace(info.TracksAndWriteOffsets?.ClrMameProData)) - { - output.Add(""); output.Add("Tracks and Write Offsets:"); - AddIfExists(output, Template.DATField, info.TracksAndWriteOffsets!.ClrMameProData + "\n", 1); - AddIfExists(output, Template.CuesheetField, info.TracksAndWriteOffsets.Cuesheet, 1); - var offset = info.TracksAndWriteOffsets.OtherWriteOffsets; - if (Int32.TryParse(offset, out int i)) - offset = i.ToString("+#;-#;0"); - - AddIfExists(output, Template.WriteOffsetField, offset, 1); - } - // Size & Checksum section - else - { - output.Add(""); output.Add("Size & Checksum:"); - - // Gross hack because of automatic layerbreaks in Redump - if (!options.EnableRedumpCompatibility - || (info.CommonDiscInfo?.Media.ToMediaType() != MediaType.BluRay - && info.CommonDiscInfo?.System.IsXGD() == false)) - { - AddIfExists(output, Template.LayerbreakField, info.SizeAndChecksums?.Layerbreak, 1); - } - - AddIfExists(output, Template.SizeField, info.SizeAndChecksums?.Size.ToString(), 1); - AddIfExists(output, Template.CRC32Field, info.SizeAndChecksums?.CRC32, 1); - AddIfExists(output, Template.MD5Field, info.SizeAndChecksums?.MD5, 1); - AddIfExists(output, Template.SHA1Field, info.SizeAndChecksums?.SHA1, 1); - } - - // Dumping Info section - output.Add(""); output.Add("Dumping Info:"); - AddIfExists(output, Template.DumpingProgramField, info.DumpingInfo?.DumpingProgram, 1); - AddIfExists(output, Template.DumpingDateField, info.DumpingInfo?.DumpingDate, 1); - AddIfExists(output, Template.DumpingDriveManufacturer, info.DumpingInfo?.Manufacturer, 1); - AddIfExists(output, Template.DumpingDriveModel, info.DumpingInfo?.Model, 1); - AddIfExists(output, Template.DumpingDriveFirmware, info.DumpingInfo?.Firmware, 1); - AddIfExists(output, Template.ReportedDiscType, info.DumpingInfo?.ReportedDiscType, 1); - - // Make sure there aren't any instances of two blank lines in a row - string? last = null; - for (int i = 0; i < output.Count;) - { - if (output[i] == last && string.IsNullOrWhiteSpace(last)) - { - output.RemoveAt(i); - } - else - { - last = output[i]; - i++; - } - } - - return (output, "Formatting complete!"); - } - catch (Exception ex) - { - return (null, $"Error formatting submission info: {ex}"); - } - } - - // Moved to RedumpLib - /// - /// Get the adjusted name of the media based on layers, if applicable - /// - /// MediaType to get the proper name for - /// PIC identifier string (BD only) - /// Size of the current media - /// First layerbreak value, as applicable - /// Second layerbreak value, as applicable - /// Third layerbreak value, as applicable - /// String representation of the media, including layer specification - /// TODO: Figure out why we have this and NormalizeDiscType as well - public static string? GetFixedMediaType(MediaType? mediaType, string? picIdentifier, long? size, long? layerbreak, long? layerbreak2, long? layerbreak3) - { - switch (mediaType) - { - case MediaType.DVD: - if (layerbreak != default && layerbreak != default(long)) - return $"{mediaType.LongName()}-9"; - else - return $"{mediaType.LongName()}-5"; - - case MediaType.BluRay: - if (layerbreak3 != default && layerbreak3 != default(long)) - return $"{mediaType.LongName()}-128"; - else if (layerbreak2 != default && layerbreak2 != default(long)) - return $"{mediaType.LongName()}-100"; - else if (layerbreak != default && layerbreak != default(long) && picIdentifier == SabreTools.Models.PIC.Constants.DiscTypeIdentifierROMUltra) - return $"{mediaType.LongName()}-66"; - else if (layerbreak != default && layerbreak != default(long) && size > 53_687_063_712) - return $"{mediaType.LongName()}-66"; - else if (layerbreak != default && layerbreak != default(long)) - return $"{mediaType.LongName()}-50"; - else if (picIdentifier == SabreTools.Models.PIC.Constants.DiscTypeIdentifierROMUltra) - return $"{mediaType.LongName()}-33"; - else if (size > 26_843_531_856) - return $"{mediaType.LongName()}-33"; - else - return $"{mediaType.LongName()}-25"; - - case MediaType.UMD: - if (layerbreak != default && layerbreak != default(long)) - return $"{mediaType.LongName()}-DL"; - else - return $"{mediaType.LongName()}-SL"; - - default: - return mediaType.LongName(); - } - } - - // Moved to RedumpLib - /// - /// Process any fields that have to be combined - /// - /// Information object to normalize - public static void ProcessSpecialFields(SubmissionInfo? info) - { - // If there is no submission info - if (info == null) - return; - - // Process the comments field - if (info.CommonDiscInfo?.CommentsSpecialFields != null && info.CommonDiscInfo.CommentsSpecialFields?.Any() == true) - { - // If the field is missing, add an empty one to fill in - if (info.CommonDiscInfo.Comments == null) - info.CommonDiscInfo.Comments = string.Empty; - - // Add all special fields before any comments - info.CommonDiscInfo.Comments = string.Join( - "\n", OrderCommentTags(info.CommonDiscInfo.CommentsSpecialFields) - .Where(kvp => !string.IsNullOrWhiteSpace(kvp.Value)) - .Select(FormatSiteTag) - .Where(s => !string.IsNullOrEmpty(s)) - ) + "\n" + info.CommonDiscInfo.Comments; - - // Normalize newlines - info.CommonDiscInfo.Comments = info.CommonDiscInfo.Comments.Replace("\r\n", "\n"); - - // Trim the comments field - info.CommonDiscInfo.Comments = info.CommonDiscInfo.Comments.Trim(); - - // Wipe out the special fields dictionary - info.CommonDiscInfo.CommentsSpecialFields = null; - } - - // Process the contents field - if (info.CommonDiscInfo?.ContentsSpecialFields != null && info.CommonDiscInfo.ContentsSpecialFields?.Any() == true) - { - // If the field is missing, add an empty one to fill in - if (info.CommonDiscInfo.Contents == null) - info.CommonDiscInfo.Contents = string.Empty; - - // Add all special fields before any contents - info.CommonDiscInfo.Contents = string.Join( - "\n", OrderContentTags(info.CommonDiscInfo.ContentsSpecialFields) - .Where(kvp => !string.IsNullOrWhiteSpace(kvp.Value)) - .Select(FormatSiteTag) - .Where(s => !string.IsNullOrEmpty(s)) - ) + "\n" + info.CommonDiscInfo.Contents; - - // Normalize newlines - info.CommonDiscInfo.Contents = info.CommonDiscInfo.Contents.Replace("\r\n", "\n"); - - // Trim the contents field - info.CommonDiscInfo.Contents = info.CommonDiscInfo.Contents.Trim(); - - // Wipe out the special fields dictionary - info.CommonDiscInfo.ContentsSpecialFields = null; - } - } - /// /// Write the data to the output folder /// @@ -1755,112 +1390,6 @@ namespace MPF.Core return true; } - // Moved to RedumpLib - /// - /// Add the properly formatted key and value, if possible - /// - /// Output list - /// Name of the output key to write - /// Name of the output value to write - /// Number of tabs to indent the line - private static void AddIfExists(List output, string key, string? value, int indent) - { - // If there's no valid value to write - if (value == null) - return; - - string prefix = string.Empty; - for (int i = 0; i < indent; i++) - prefix += "\t"; - - // Skip fields that need to keep internal whitespace intact - if (key != "Primary Volume Descriptor (PVD)" - && key != "Header" - && key != "Cuesheet") - { - // Convert to tabs - value = value.Replace("", "\t"); - value = value.Replace("", "\t"); - value = value.Replace(" ", "\t"); - - // Sanitize whitespace around tabs - value = Regex.Replace(value, @"\s*\t\s*", "\t", RegexOptions.Compiled); - } - - // If the value contains a newline - value = value.Replace("\r\n", "\n"); - if (value.Contains('\n')) - { - output.Add(prefix + key + ":"); output.Add(""); - string[] values = value.Split('\n'); - foreach (string val in values) - output.Add(val); - - output.Add(""); - } - - // For all regular values - else - { - output.Add(prefix + key + ": " + value); - } - } - - // Moved to RedumpLib - /// - /// Add the properly formatted key and value, if possible - /// - /// Output list - /// Name of the output key to write - /// Name of the output value to write - /// Number of tabs to indent the line - private static void AddIfExists(List output, string key, string?[]? value, int indent) - { - // If there's no valid value to write - if (value == null || value.Length == 0) - return; - - AddIfExists(output, key, string.Join(", ", value), indent); - } - - // Moved to RedumpLib - /// - /// Add the properly formatted key and value, if possible - /// - /// Output list - /// Name of the output key to write - /// Name of the output value to write - /// Number of tabs to indent the line - private static void AddIfExists(List output, string key, long? value, int indent) - { - // If there's no valid value to write - if (value == null || value == default(long)) - return; - - string prefix = string.Empty; - for (int i = 0; i < indent; i++) - prefix += "\t"; - - output.Add(prefix + key + ": " + value); - } - - // Moved to RedumpLib - /// - /// Add the properly formatted key and value, if possible - /// - /// Output list - /// Name of the output key to write - /// Name of the output value to write - /// Number of tabs to indent the line - private static void AddIfExists(List output, string key, List? value, int indent) - { - // If there's no valid value to write - if (value == null || value.Count == 0) - return; - - AddIfExists(output, key, string.Join(", ", value.Select(o => o.ToString())), indent); - } - /// /// Generate a list of all MPF-specific log files generated /// @@ -2316,74 +1845,6 @@ namespace MPF.Core return newTitle; } - // Moved to RedumpLib - /// - /// Adjust the disc type based on size and layerbreak information - /// - /// Existing SubmissionInfo object to fill - /// Corrected disc type, if possible - public static void NormalizeDiscType(SubmissionInfo info) - { - // If we have nothing valid, do nothing - if (info?.CommonDiscInfo?.Media == null || info?.SizeAndChecksums == null) - return; - - switch (info.CommonDiscInfo.Media) - { - case DiscType.BD25: - case DiscType.BD33: - case DiscType.BD50: - case DiscType.BD66: - case DiscType.BD100: - case DiscType.BD128: - if (info.SizeAndChecksums.Layerbreak3 != default) - info.CommonDiscInfo.Media = DiscType.BD128; - else if (info.SizeAndChecksums.Layerbreak2 != default) - info.CommonDiscInfo.Media = DiscType.BD100; - else if (info.SizeAndChecksums.Layerbreak != default && info.SizeAndChecksums.PICIdentifier == SabreTools.Models.PIC.Constants.DiscTypeIdentifierROMUltra) - info.CommonDiscInfo.Media = DiscType.BD66; - else if (info.SizeAndChecksums.Layerbreak != default && info.SizeAndChecksums.Size > 50_050_629_632) - info.CommonDiscInfo.Media = DiscType.BD66; - else if (info.SizeAndChecksums.Layerbreak != default) - info.CommonDiscInfo.Media = DiscType.BD50; - else if (info.SizeAndChecksums.PICIdentifier == SabreTools.Models.PIC.Constants.DiscTypeIdentifierROMUltra) - info.CommonDiscInfo.Media = DiscType.BD33; - else if (info.SizeAndChecksums.Size > 25_025_314_816) - info.CommonDiscInfo.Media = DiscType.BD33; - else - info.CommonDiscInfo.Media = DiscType.BD25; - break; - - case DiscType.DVD5: - case DiscType.DVD9: - if (info.SizeAndChecksums.Layerbreak != default) - info.CommonDiscInfo.Media = DiscType.DVD9; - else - info.CommonDiscInfo.Media = DiscType.DVD5; - break; - - case DiscType.HDDVDSL: - case DiscType.HDDVDDL: - if (info.SizeAndChecksums.Layerbreak != default) - info.CommonDiscInfo.Media = DiscType.HDDVDDL; - else - info.CommonDiscInfo.Media = DiscType.HDDVDSL; - break; - - case DiscType.UMDSL: - case DiscType.UMDDL: - if (info.SizeAndChecksums.Layerbreak != default) - info.CommonDiscInfo.Media = DiscType.UMDDL; - else - info.CommonDiscInfo.Media = DiscType.UMDSL; - break; - - // All other disc types are not processed - default: - break; - } - } - /// /// Normalize a split set of paths /// @@ -2427,217 +1888,5 @@ namespace MPF.Core } #endregion - - #region Helpers - - // Moved to RedumpLib - /// - /// Format a single site tag to string - /// - /// KeyValuePair representing the site tag and value - /// String-formatted tag and value - private static string FormatSiteTag(KeyValuePair kvp) - { - bool isMultiLine = SubmissionInfoTool.IsMultiLine(kvp.Key); - string line = $"{kvp.Key.ShortName()}{(isMultiLine ? "\n" : " ")}"; - - // Special case for boolean fields - if (IsBoolean(kvp.Key)) - { - if (kvp.Value != true.ToString()) - return string.Empty; - - return line.Trim(); - } - - return $"{line}{kvp.Value}{(isMultiLine ? "\n" : string.Empty)}"; - } - - // Moved to RedumpLib - /// - /// Check if a site code is boolean or not - /// - /// SiteCode to check - /// True if the code field is a flag with no value, false otherwise - /// TODO: This should move to Extensions at some point - private static bool IsBoolean(SiteCode? siteCode) - { - return siteCode switch - { - SiteCode.PostgapType => true, - SiteCode.VCD => true, - _ => false, - }; - } - - // Moved to RedumpLib - /// - /// Order comment code tags according to Redump requirements - /// - /// Ordered list of KeyValuePairs representing the tags and values - private static List> OrderCommentTags(Dictionary tags) - { - var sorted = new List>(); - - // If the input is invalid, just return an empty set - if (tags == null || tags.Count == 0) - return sorted; - - // Identifying Info - if (tags.ContainsKey(SiteCode.AlternativeTitle)) - sorted.Add(new KeyValuePair(SiteCode.AlternativeTitle, tags[SiteCode.AlternativeTitle])); - if (tags.ContainsKey(SiteCode.AlternativeForeignTitle)) - sorted.Add(new KeyValuePair(SiteCode.AlternativeForeignTitle, tags[SiteCode.AlternativeForeignTitle])); - if (tags.ContainsKey(SiteCode.InternalName)) - sorted.Add(new KeyValuePair(SiteCode.InternalName, tags[SiteCode.InternalName])); - if (tags.ContainsKey(SiteCode.InternalSerialName)) - sorted.Add(new KeyValuePair(SiteCode.InternalSerialName, tags[SiteCode.InternalSerialName])); - if (tags.ContainsKey(SiteCode.VolumeLabel)) - sorted.Add(new KeyValuePair(SiteCode.VolumeLabel, tags[SiteCode.VolumeLabel])); - if (tags.ContainsKey(SiteCode.Multisession)) - sorted.Add(new KeyValuePair(SiteCode.Multisession, tags[SiteCode.Multisession])); - if (tags.ContainsKey(SiteCode.UniversalHash)) - sorted.Add(new KeyValuePair(SiteCode.UniversalHash, tags[SiteCode.UniversalHash])); - if (tags.ContainsKey(SiteCode.RingNonZeroDataStart)) - sorted.Add(new KeyValuePair(SiteCode.RingNonZeroDataStart, tags[SiteCode.RingNonZeroDataStart])); - - if (tags.ContainsKey(SiteCode.XMID)) - sorted.Add(new KeyValuePair(SiteCode.XMID, tags[SiteCode.XMID])); - if (tags.ContainsKey(SiteCode.XeMID)) - sorted.Add(new KeyValuePair(SiteCode.XeMID, tags[SiteCode.XeMID])); - if (tags.ContainsKey(SiteCode.DMIHash)) - sorted.Add(new KeyValuePair(SiteCode.DMIHash, tags[SiteCode.DMIHash])); - if (tags.ContainsKey(SiteCode.PFIHash)) - sorted.Add(new KeyValuePair(SiteCode.PFIHash, tags[SiteCode.PFIHash])); - if (tags.ContainsKey(SiteCode.SSHash)) - sorted.Add(new KeyValuePair(SiteCode.SSHash, tags[SiteCode.SSHash])); - if (tags.ContainsKey(SiteCode.SSVersion)) - sorted.Add(new KeyValuePair(SiteCode.SSVersion, tags[SiteCode.SSVersion])); - - if (tags.ContainsKey(SiteCode.Filename)) - sorted.Add(new KeyValuePair(SiteCode.Filename, tags[SiteCode.Filename])); - - if (tags.ContainsKey(SiteCode.BBFCRegistrationNumber)) - sorted.Add(new KeyValuePair(SiteCode.BBFCRegistrationNumber, tags[SiteCode.BBFCRegistrationNumber])); - if (tags.ContainsKey(SiteCode.CDProjektID)) - sorted.Add(new KeyValuePair(SiteCode.CDProjektID, tags[SiteCode.CDProjektID])); - if (tags.ContainsKey(SiteCode.DiscHologramID)) - sorted.Add(new KeyValuePair(SiteCode.DiscHologramID, tags[SiteCode.DiscHologramID])); - if (tags.ContainsKey(SiteCode.DNASDiscID)) - sorted.Add(new KeyValuePair(SiteCode.DNASDiscID, tags[SiteCode.DNASDiscID])); - if (tags.ContainsKey(SiteCode.ISBN)) - sorted.Add(new KeyValuePair(SiteCode.ISBN, tags[SiteCode.ISBN])); - if (tags.ContainsKey(SiteCode.ISSN)) - sorted.Add(new KeyValuePair(SiteCode.ISSN, tags[SiteCode.ISSN])); - if (tags.ContainsKey(SiteCode.PPN)) - sorted.Add(new KeyValuePair(SiteCode.PPN, tags[SiteCode.PPN])); - if (tags.ContainsKey(SiteCode.VFCCode)) - sorted.Add(new KeyValuePair(SiteCode.VFCCode, tags[SiteCode.VFCCode])); - - if (tags.ContainsKey(SiteCode.Genre)) - sorted.Add(new KeyValuePair(SiteCode.Genre, tags[SiteCode.Genre])); - if (tags.ContainsKey(SiteCode.Series)) - sorted.Add(new KeyValuePair(SiteCode.Series, tags[SiteCode.Series])); - if (tags.ContainsKey(SiteCode.PostgapType)) - sorted.Add(new KeyValuePair(SiteCode.PostgapType, tags[SiteCode.PostgapType])); - if (tags.ContainsKey(SiteCode.VCD)) - sorted.Add(new KeyValuePair(SiteCode.VCD, tags[SiteCode.VCD])); - - // Publisher / Company IDs - if (tags.ContainsKey(SiteCode.AcclaimID)) - sorted.Add(new KeyValuePair(SiteCode.AcclaimID, tags[SiteCode.AcclaimID])); - if (tags.ContainsKey(SiteCode.ActivisionID)) - sorted.Add(new KeyValuePair(SiteCode.ActivisionID, tags[SiteCode.ActivisionID])); - if (tags.ContainsKey(SiteCode.BandaiID)) - sorted.Add(new KeyValuePair(SiteCode.BandaiID, tags[SiteCode.BandaiID])); - if (tags.ContainsKey(SiteCode.ElectronicArtsID)) - sorted.Add(new KeyValuePair(SiteCode.ElectronicArtsID, tags[SiteCode.ElectronicArtsID])); - if (tags.ContainsKey(SiteCode.FoxInteractiveID)) - sorted.Add(new KeyValuePair(SiteCode.FoxInteractiveID, tags[SiteCode.FoxInteractiveID])); - if (tags.ContainsKey(SiteCode.GTInteractiveID)) - sorted.Add(new KeyValuePair(SiteCode.GTInteractiveID, tags[SiteCode.GTInteractiveID])); - if (tags.ContainsKey(SiteCode.JASRACID)) - sorted.Add(new KeyValuePair(SiteCode.JASRACID, tags[SiteCode.JASRACID])); - if (tags.ContainsKey(SiteCode.KingRecordsID)) - sorted.Add(new KeyValuePair(SiteCode.KingRecordsID, tags[SiteCode.KingRecordsID])); - if (tags.ContainsKey(SiteCode.KoeiID)) - sorted.Add(new KeyValuePair(SiteCode.KoeiID, tags[SiteCode.KoeiID])); - if (tags.ContainsKey(SiteCode.KonamiID)) - sorted.Add(new KeyValuePair(SiteCode.KonamiID, tags[SiteCode.KonamiID])); - if (tags.ContainsKey(SiteCode.LucasArtsID)) - sorted.Add(new KeyValuePair(SiteCode.LucasArtsID, tags[SiteCode.LucasArtsID])); - if (tags.ContainsKey(SiteCode.MicrosoftID)) - sorted.Add(new KeyValuePair(SiteCode.MicrosoftID, tags[SiteCode.MicrosoftID])); - if (tags.ContainsKey(SiteCode.NaganoID)) - sorted.Add(new KeyValuePair(SiteCode.NaganoID, tags[SiteCode.NaganoID])); - if (tags.ContainsKey(SiteCode.NamcoID)) - sorted.Add(new KeyValuePair(SiteCode.NamcoID, tags[SiteCode.NamcoID])); - if (tags.ContainsKey(SiteCode.NipponIchiSoftwareID)) - sorted.Add(new KeyValuePair(SiteCode.NipponIchiSoftwareID, tags[SiteCode.NipponIchiSoftwareID])); - if (tags.ContainsKey(SiteCode.OriginID)) - sorted.Add(new KeyValuePair(SiteCode.OriginID, tags[SiteCode.OriginID])); - if (tags.ContainsKey(SiteCode.PonyCanyonID)) - sorted.Add(new KeyValuePair(SiteCode.PonyCanyonID, tags[SiteCode.PonyCanyonID])); - if (tags.ContainsKey(SiteCode.SegaID)) - sorted.Add(new KeyValuePair(SiteCode.SegaID, tags[SiteCode.SegaID])); - if (tags.ContainsKey(SiteCode.SelenID)) - sorted.Add(new KeyValuePair(SiteCode.SelenID, tags[SiteCode.SelenID])); - if (tags.ContainsKey(SiteCode.SierraID)) - sorted.Add(new KeyValuePair(SiteCode.SierraID, tags[SiteCode.SierraID])); - if (tags.ContainsKey(SiteCode.TaitoID)) - sorted.Add(new KeyValuePair(SiteCode.TaitoID, tags[SiteCode.TaitoID])); - if (tags.ContainsKey(SiteCode.UbisoftID)) - sorted.Add(new KeyValuePair(SiteCode.UbisoftID, tags[SiteCode.UbisoftID])); - if (tags.ContainsKey(SiteCode.ValveID)) - sorted.Add(new KeyValuePair(SiteCode.ValveID, tags[SiteCode.ValveID])); - - return sorted; - } - - // Moved to RedumpLib - /// - /// Order content code tags according to Redump requirements - /// - /// Ordered list of KeyValuePairs representing the tags and values - private static List> OrderContentTags(Dictionary tags) - { - var sorted = new List>(); - - // If the input is invalid, just return an empty set - if (tags == null || tags.Count == 0) - return sorted; - - // Games - if (tags.ContainsKey(SiteCode.Games)) - sorted.Add(new KeyValuePair(SiteCode.Games, tags[SiteCode.Games])); - if (tags.ContainsKey(SiteCode.NetYarozeGames)) - sorted.Add(new KeyValuePair(SiteCode.NetYarozeGames, tags[SiteCode.NetYarozeGames])); - - // Demos - if (tags.ContainsKey(SiteCode.PlayableDemos)) - sorted.Add(new KeyValuePair(SiteCode.PlayableDemos, tags[SiteCode.PlayableDemos])); - if (tags.ContainsKey(SiteCode.RollingDemos)) - sorted.Add(new KeyValuePair(SiteCode.RollingDemos, tags[SiteCode.RollingDemos])); - if (tags.ContainsKey(SiteCode.TechDemos)) - sorted.Add(new KeyValuePair(SiteCode.TechDemos, tags[SiteCode.TechDemos])); - - // Video - if (tags.ContainsKey(SiteCode.GameFootage)) - sorted.Add(new KeyValuePair(SiteCode.GameFootage, tags[SiteCode.GameFootage])); - if (tags.ContainsKey(SiteCode.Videos)) - sorted.Add(new KeyValuePair(SiteCode.Videos, tags[SiteCode.Videos])); - - // Miscellaneous - if (tags.ContainsKey(SiteCode.Patches)) - sorted.Add(new KeyValuePair(SiteCode.Patches, tags[SiteCode.Patches])); - if (tags.ContainsKey(SiteCode.Savegames)) - sorted.Add(new KeyValuePair(SiteCode.Savegames, tags[SiteCode.Savegames])); - if (tags.ContainsKey(SiteCode.Extras)) - sorted.Add(new KeyValuePair(SiteCode.Extras, tags[SiteCode.Extras])); - - return sorted; - } - - #endregion } } diff --git a/MPF.Core/MPF.Core.csproj b/MPF.Core/MPF.Core.csproj index cba9464e..ab80ff9d 100644 --- a/MPF.Core/MPF.Core.csproj +++ b/MPF.Core/MPF.Core.csproj @@ -31,7 +31,7 @@ - + diff --git a/MPF.Core/Modules/Aaru/Parameters.cs b/MPF.Core/Modules/Aaru/Parameters.cs index 2a773138..ef8b5770 100644 --- a/MPF.Core/Modules/Aaru/Parameters.cs +++ b/MPF.Core/Modules/Aaru/Parameters.cs @@ -10,6 +10,7 @@ using System.Xml.Serialization; using MPF.Core.Converters; using MPF.Core.Data; using SabreTools.Models.CueSheets; +using SabreTools.RedumpLib; using SabreTools.RedumpLib.Data; using Schemas; @@ -202,7 +203,7 @@ namespace MPF.Core.Modules.Aaru var outputDirectory = Path.GetDirectoryName(basePath); // Ensure that required sections exist - info = SubmissionInfoTool.EnsureAllSections(info); + info = Builder.EnsureAllSections(info); // TODO: Determine if there's an Aaru version anywhere info.DumpingInfo!.DumpingProgram = EnumConverter.LongName(this.InternalProgram); diff --git a/MPF.Core/Modules/CleanRIp/Parameters.cs b/MPF.Core/Modules/CleanRIp/Parameters.cs index 8735d458..15771391 100644 --- a/MPF.Core/Modules/CleanRIp/Parameters.cs +++ b/MPF.Core/Modules/CleanRIp/Parameters.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text.RegularExpressions; using MPF.Core.Converters; using MPF.Core.Data; +using SabreTools.RedumpLib; using SabreTools.RedumpLib.Data; #pragma warning disable IDE0051 // Remove unused private members @@ -64,7 +65,7 @@ namespace MPF.Core.Modules.CleanRip public override void GenerateSubmissionInfo(SubmissionInfo info, Options options, string basePath, Drive? drive, bool includeArtifacts) { // Ensure that required sections exist - info = SubmissionInfoTool.EnsureAllSections(info); + info = Builder.EnsureAllSections(info); // TODO: Determine if there's a CleanRip version anywhere info.DumpingInfo!.DumpingProgram = EnumConverter.LongName(this.InternalProgram); diff --git a/MPF.Core/Modules/DiscImageCreator/Parameters.cs b/MPF.Core/Modules/DiscImageCreator/Parameters.cs index f27d22d9..60f3fd94 100644 --- a/MPF.Core/Modules/DiscImageCreator/Parameters.cs +++ b/MPF.Core/Modules/DiscImageCreator/Parameters.cs @@ -6,6 +6,7 @@ using System.Text.RegularExpressions; using MPF.Core.Converters; using MPF.Core.Data; using MPF.Core.Utilities; +using SabreTools.RedumpLib; using SabreTools.RedumpLib.Data; namespace MPF.Core.Modules.DiscImageCreator @@ -384,7 +385,7 @@ namespace MPF.Core.Modules.DiscImageCreator var outputDirectory = Path.GetDirectoryName(basePath); // Ensure that required sections exist - info = SubmissionInfoTool.EnsureAllSections(info); + info = Builder.EnsureAllSections(info); // Get the dumping program and version var (dicCmd, dicVersion) = GetCommandFilePathAndVersion(basePath); diff --git a/MPF.Core/Modules/Redumper/Parameters.cs b/MPF.Core/Modules/Redumper/Parameters.cs index 3497750b..a49a6b55 100644 --- a/MPF.Core/Modules/Redumper/Parameters.cs +++ b/MPF.Core/Modules/Redumper/Parameters.cs @@ -6,6 +6,7 @@ using System.Text.RegularExpressions; using MPF.Core.Converters; using MPF.Core.Data; using MPF.Core.Utilities; +using SabreTools.RedumpLib; using SabreTools.RedumpLib.Data; #pragma warning disable IDE0051 // Remove unused private members @@ -255,7 +256,7 @@ namespace MPF.Core.Modules.Redumper public override void GenerateSubmissionInfo(SubmissionInfo info, Options options, string basePath, Drive? drive, bool includeArtifacts) { // Ensure that required sections exist - info = SubmissionInfoTool.EnsureAllSections(info); + info = Builder.EnsureAllSections(info); // Get the dumping program and version info.DumpingInfo!.DumpingProgram = $"{EnumConverter.LongName(this.InternalProgram)} {GetVersion($"{basePath}.log") ?? "Unknown Version"}"; diff --git a/MPF.Core/Modules/UmdImageCreator/Parameters.cs b/MPF.Core/Modules/UmdImageCreator/Parameters.cs index 1b5686ec..6b9c0a0e 100644 --- a/MPF.Core/Modules/UmdImageCreator/Parameters.cs +++ b/MPF.Core/Modules/UmdImageCreator/Parameters.cs @@ -5,6 +5,7 @@ using System.Linq; using MPF.Core.Converters; using MPF.Core.Data; using MPF.Core.Hashing; +using SabreTools.RedumpLib; using SabreTools.RedumpLib.Data; namespace MPF.Core.Modules.UmdImageCreator @@ -65,7 +66,7 @@ namespace MPF.Core.Modules.UmdImageCreator public override void GenerateSubmissionInfo(SubmissionInfo info, Options options, string basePath, Drive? drive, bool includeArtifacts) { // Ensure that required sections exist - info = SubmissionInfoTool.EnsureAllSections(info); + info = Builder.EnsureAllSections(info); // TODO: Determine if there's a UMDImageCreator version anywhere info.DumpingInfo!.DumpingProgram = EnumConverter.LongName(this.InternalProgram); diff --git a/MPF.Core/SubmissionInfoTool.cs b/MPF.Core/SubmissionInfoTool.cs index 7601ee11..6941ec60 100644 --- a/MPF.Core/SubmissionInfoTool.cs +++ b/MPF.Core/SubmissionInfoTool.cs @@ -2,14 +2,10 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Net; -using System.Text; -using System.Text.RegularExpressions; using System.Threading.Tasks; -using System.Xml; using MPF.Core.Data; using MPF.Core.Modules; -using Newtonsoft.Json; +using SabreTools.RedumpLib; using SabreTools.RedumpLib.Data; using SabreTools.RedumpLib.Web; @@ -23,267 +19,6 @@ namespace MPF.Core /// internal static class SubmissionInfoTool { - #region Creation - - // Moved to RedumpLib - /// - /// Create a SubmissionInfo from a JSON file path - /// - /// Path to the SubmissionInfo JSON - /// Filled SubmissionInfo on success, null on error - public static SubmissionInfo? CreateFromFile(string? path) - { - // If the path is invalid - if (string.IsNullOrWhiteSpace(path)) - return null; - - // If the file doesn't exist - if (!File.Exists(path)) - return null; - - // Try to open and deserialize the file - try - { - byte[] data = File.ReadAllBytes(path); - string dataString = Encoding.UTF8.GetString(data); - return JsonConvert.DeserializeObject(dataString); - } - catch - { - // We don't care what the exception was - return null; - } - } - - // Moved to RedumpLib - /// - /// Create a new SubmissionInfo object from a disc page - /// - /// String containing the HTML disc data - /// Filled SubmissionInfo object on success, null on error - /// Not currently working - private static SubmissionInfo? CreateFromID(string discData) - { - var info = new SubmissionInfo() - { - CommonDiscInfo = new CommonDiscInfoSection(), - VersionAndEditions = new VersionAndEditionsSection(), - }; - - // No disc data means we can't parse it - if (string.IsNullOrWhiteSpace(discData)) - return null; - - try - { - // Load the current disc page into an XML document - var redumpPage = new XmlDocument() { PreserveWhitespace = true }; - redumpPage.LoadXml(discData); - - // If the current page isn't valid, we can't parse it - if (!redumpPage.HasChildNodes) - return null; - - // Get the body node, if possible - var bodyNode = redumpPage["html"]?["body"]; - if (bodyNode == null || !bodyNode.HasChildNodes) - return null; - - // Loop through and get the main node, if possible - XmlNode? mainNode = null; - foreach (XmlNode? tempNode in bodyNode.ChildNodes) - { - // Invalid nodes are skipped - if (tempNode == null) - continue; - - // We only care about div elements - if (!string.Equals(tempNode.Name, "div", StringComparison.OrdinalIgnoreCase)) - continue; - - // We only care if it has attributes - if (tempNode.Attributes == null) - continue; - - // The main node has a class of "main" - if (string.Equals(tempNode.Attributes["class"]?.Value, "main", StringComparison.OrdinalIgnoreCase)) - { - mainNode = tempNode; - break; - } - } - - // If the main node is invalid, we can't do anything - if (mainNode == null || !mainNode.HasChildNodes) - return null; - - // Try to find elements as we're going - foreach (XmlNode? childNode in mainNode.ChildNodes) - { - // Invalid nodes are skipped - if (childNode == null) - continue; - - // The title is the only thing in h1 tags - if (string.Equals(childNode.Name, "h1", StringComparison.OrdinalIgnoreCase)) - info.CommonDiscInfo.Title = childNode.InnerText; - - // Most things are div elements but can be hard to parse out - else if (!string.Equals(childNode.Name, "div", StringComparison.OrdinalIgnoreCase)) - continue; - - // Only 2 of the internal divs have classes attached and one is not used here - if (childNode.Attributes != null && string.Equals(childNode.Attributes["class"]?.Value, "game", - StringComparison.OrdinalIgnoreCase)) - { - // If we don't have children nodes, skip this one over - if (!childNode.HasChildNodes) - continue; - - // The game node contains multiple other elements - foreach (XmlNode? gameNode in childNode.ChildNodes) - { - // Invalid nodes are skipped - if (gameNode == null) - continue; - - // Table elements contain multiple other parts of information - if (string.Equals(gameNode.Name, "table", StringComparison.OrdinalIgnoreCase)) - { - // All tables have some attribute we can use - if (gameNode.Attributes == null) - continue; - - // The gameinfo node contains most of the major information - if (string.Equals(gameNode.Attributes["class"]?.Value, "gameinfo", - StringComparison.OrdinalIgnoreCase)) - { - // If we don't have children nodes, skip this one over - if (!gameNode.HasChildNodes) - continue; - - // Loop through each of the rows - foreach (XmlNode? gameInfoNode in gameNode.ChildNodes) - { - // Invalid nodes are skipped - if (gameInfoNode == null) - continue; - - // If we run into anything not a row, ignore it - if (!string.Equals(gameInfoNode.Name, "tr", StringComparison.OrdinalIgnoreCase)) - continue; - - // If we don't have the required nodes, ignore it - if (gameInfoNode["th"] == null || gameInfoNode["td"] == null) - continue; - - var gameInfoNodeHeader = gameInfoNode["th"]; - var gameInfoNodeData = gameInfoNode["td"]; - - if (gameInfoNodeHeader == null || gameInfoNodeData == null) - { - // No-op for invalid data - } - else if (string.Equals(gameInfoNodeHeader.InnerText, "System", StringComparison.OrdinalIgnoreCase)) - { - info.CommonDiscInfo.System = Extensions.ToRedumpSystem(gameInfoNodeData["a"]?.InnerText ?? string.Empty); - } - else if (string.Equals(gameInfoNodeHeader.InnerText, "Media", StringComparison.OrdinalIgnoreCase)) - { - info.CommonDiscInfo.Media = Extensions.ToDiscType(gameInfoNodeData.InnerText); - } - else if (string.Equals(gameInfoNodeHeader.InnerText, "Category", StringComparison.OrdinalIgnoreCase)) - { - info.CommonDiscInfo.Category = Extensions.ToDiscCategory(gameInfoNodeData.InnerText); - } - else if (string.Equals(gameInfoNodeHeader.InnerText, "Region", StringComparison.OrdinalIgnoreCase)) - { - // TODO: COMPLETE - } - else if (string.Equals(gameInfoNodeHeader.InnerText, "Languages", StringComparison.OrdinalIgnoreCase)) - { - // TODO: COMPLETE - } - else if (string.Equals(gameInfoNodeHeader.InnerText, "Edition", StringComparison.OrdinalIgnoreCase)) - { - info.VersionAndEditions.OtherEditions = gameInfoNodeData.InnerText; - } - else if (string.Equals(gameInfoNodeHeader.InnerText, "Added", StringComparison.OrdinalIgnoreCase)) - { - if (DateTime.TryParse(gameInfoNodeData.InnerText, out DateTime added)) - info.Added = added; - } - else if (string.Equals(gameInfoNodeHeader.InnerText, "Last modified", StringComparison.OrdinalIgnoreCase)) - { - if (DateTime.TryParse(gameInfoNodeData.InnerText, out DateTime lastModified)) - info.LastModified = lastModified; - } - } - } - - // The gamecomments node contains way more than it implies - if (string.Equals(gameNode.Attributes["class"]?.Value, "gamecomments", StringComparison.OrdinalIgnoreCase)) - { - // TODO: COMPLETE - } - - // TODO: COMPLETE - } - - // The only other supported elements are divs - else if (!string.Equals(gameNode.Name, "div", StringComparison.OrdinalIgnoreCase)) - { - continue; - } - - // Check the div for dumper info - // TODO: COMPLETE - } - } - - // Figure out what the div contains, if possible - // TODO: COMPLETE - } - } - catch - { - return null; - } - - return info; - } - - // Moved to RedumpLib - /// - /// Ensure all required sections in a submission info exist - /// - /// SubmissionInfo object to verify - public static SubmissionInfo EnsureAllSections(SubmissionInfo? info) - { - // If there's no info, create one - info ??= new SubmissionInfo(); - - // Ensure all sections - info.CommonDiscInfo ??= new CommonDiscInfoSection(); - info.VersionAndEditions ??= new VersionAndEditionsSection(); - info.EDC ??= new EDCSection(); - info.ParentCloneRelationship ??= new ParentCloneRelationshipSection(); - info.Extras ??= new ExtrasSection(); - info.CopyProtection ??= new CopyProtectionSection(); - info.DumpersAndStatus ??= new DumpersAndStatusSection(); - info.TracksAndWriteOffsets ??= new TracksAndWriteOffsetsSection(); - info.SizeAndChecksums ??= new SizeAndChecksumsSection(); - info.DumpingInfo ??= new DumpingInfoSection(); - - // Ensure special dictionaries - info.CommonDiscInfo.CommentsSpecialFields ??= []; - info.CommonDiscInfo.ContentsSpecialFields ??= []; - - return info; - } - - #endregion - #region Extraction and Filling /// @@ -364,7 +99,7 @@ namespace MPF.Core }; // Ensure that required sections exist - info = EnsureAllSections(info); + info = Builder.EnsureAllSections(info); // Get specific tool output handling parameters?.GenerateSubmissionInfo(info, options, combinedBase, drive, options.IncludeArtifacts); @@ -714,393 +449,11 @@ namespace MPF.Core info.CommonDiscInfo.Contents = options.AddPlaceholders ? Template.OptionalValue : string.Empty; // Normalize the disc type with all current information - InfoTool.NormalizeDiscType(info); + Validator.NormalizeDiscType(info); return info; } - // Moved to RedumpLib - /// - /// Fill out an existing SubmissionInfo object based on a disc page - /// - /// RedumpWebClient for making the connection - /// Existing SubmissionInfo object to fill - /// Redump disc ID to retrieve - /// True to include all pullable information, false to do bare minimum -#if NET40 - public static bool FillFromId(RedumpWebClient wc, SubmissionInfo info, int id, bool includeAllData) -#elif NETFRAMEWORK - public async static Task FillFromId(RedumpWebClient wc, SubmissionInfo info, int id, bool includeAllData) -#else - public async static Task FillFromId(RedumpHttpClient wc, SubmissionInfo info, int id, bool includeAllData) -#endif - { - // Ensure that required sections exist - info = EnsureAllSections(info); -#if NET40 - var discData = wc.DownloadSingleSiteID(id); -#elif NETFRAMEWORK - var discData = await Task.Run(() => wc.DownloadSingleSiteID(id)); -#else - var discData = await wc.DownloadSingleSiteID(id); -#endif - if (string.IsNullOrEmpty(discData)) - return false; - - // Title, Disc Number/Letter, Disc Title - var match = Constants.TitleRegex.Match(discData); - if (match.Success) - { - string title = WebUtility.HtmlDecode(match.Groups[1].Value); - - // If we have parenthesis, title is everything before the first one - int firstParenLocation = title.IndexOf(" ("); - if (firstParenLocation >= 0) - { - info.CommonDiscInfo!.Title = title[..firstParenLocation]; - var subMatches = Constants.DiscNumberLetterRegex.Matches(title); - foreach (Match subMatch in subMatches.Cast()) - { - var subMatchValue = subMatch.Groups[1].Value; - - // Disc number or letter - if (subMatchValue.StartsWith("Disc")) - info.CommonDiscInfo.DiscNumberLetter = subMatchValue.Remove(0, "Disc ".Length); - - // Issue number - else if (subMatchValue.All(c => char.IsNumber(c))) - info.CommonDiscInfo.Title += $" ({subMatchValue})"; - - // Disc title - else - info.CommonDiscInfo.DiscTitle = subMatchValue; - } - } - // Otherwise, leave the title as-is - else - { - info.CommonDiscInfo!.Title = title; - } - } - - // Foreign Title - match = Constants.ForeignTitleRegex.Match(discData); - if (match.Success) - info.CommonDiscInfo!.ForeignTitleNonLatin = WebUtility.HtmlDecode(match.Groups[1].Value); - else - info.CommonDiscInfo!.ForeignTitleNonLatin = null; - - // Category - match = Constants.CategoryRegex.Match(discData); - if (match.Success) - info.CommonDiscInfo.Category = Extensions.ToDiscCategory(match.Groups[1].Value); - else - info.CommonDiscInfo.Category = DiscCategory.Games; - - // Region - if (info.CommonDiscInfo.Region == null) - { - match = Constants.RegionRegex.Match(discData); - if (match.Success) - info.CommonDiscInfo.Region = Extensions.ToRegion(match.Groups[1].Value); - } - - // Languages - var matches = Constants.LanguagesRegex.Matches(discData); - if (matches.Count > 0) - { - var tempLanguages = new List(); - foreach (Match submatch in matches.Cast()) - { - tempLanguages.Add(Extensions.ToLanguage(submatch.Groups[1].Value)); - } - - info.CommonDiscInfo.Languages = tempLanguages.Where(l => l != null).ToArray(); - } - - // Serial - if (includeAllData) - { - // TODO: Re-enable if there's a way of verifying against a disc - //match = Constants.SerialRegex.Match(discData); - //if (match.Success) - // info.CommonDiscInfo.Serial = $"(VERIFY THIS) {WebUtility.HtmlDecode(match.Groups[1].Value)}"; - } - - // Error count - if (string.IsNullOrEmpty(info.CommonDiscInfo.ErrorsCount)) - { - match = Constants.ErrorCountRegex.Match(discData); - if (match.Success) - info.CommonDiscInfo.ErrorsCount = match.Groups[1].Value; - } - - // Version - if (info.VersionAndEditions!.Version == null) - { - match = Constants.VersionRegex.Match(discData); - if (match.Success) - info.VersionAndEditions.Version = $"(VERIFY THIS) {WebUtility.HtmlDecode(match.Groups[1].Value)}"; - } - - // Dumpers - matches = Constants.DumpersRegex.Matches(discData); - if (matches.Count > 0) - { - // Start with any currently listed dumpers - var tempDumpers = new List(); - if (info.DumpersAndStatus!.Dumpers != null && info.DumpersAndStatus.Dumpers.Length > 0) - { - foreach (string dumper in info.DumpersAndStatus.Dumpers) - tempDumpers.Add(dumper); - } - - foreach (Match submatch in matches.Cast()) - { - tempDumpers.Add(WebUtility.HtmlDecode(submatch.Groups[1].Value)); - } - - info.DumpersAndStatus.Dumpers = [.. tempDumpers]; - } - - // TODO: Unify handling of fields that can include site codes (Comments/Contents) - - // Comments - if (includeAllData) - { - match = Constants.CommentsRegex.Match(discData); - if (match.Success) - { - // Process the old comments block - string oldComments = info.CommonDiscInfo.Comments - + (string.IsNullOrEmpty(info.CommonDiscInfo.Comments) ? string.Empty : "\n") - + WebUtility.HtmlDecode(match.Groups[1].Value) - .Replace("\r\n", "\n") - .Replace("
\n", "\n") - .Replace("
", string.Empty) - .Replace("", string.Empty) - .Replace("[+]", string.Empty) - .ReplaceHtmlWithSiteCodes(); - oldComments = Regex.Replace(oldComments, @"
", string.Empty, RegexOptions.Compiled); - - // Create state variables - bool addToLast = false; - SiteCode? lastSiteCode = null; - string newComments = string.Empty; - - // Process the comments block line-by-line - string[] commentsSeparated = oldComments.Split('\n'); - for (int i = 0; i < commentsSeparated.Length; i++) - { - string commentLine = commentsSeparated[i].Trim(); - - // If we have an empty line, we want to treat this as intentional - if (string.IsNullOrWhiteSpace(commentLine)) - { - addToLast = false; - lastSiteCode = null; - newComments += $"{commentLine}\n"; - continue; - } - - // Otherwise, we need to find what tag is in use - bool foundTag = false; - foreach (SiteCode? siteCode in Enum.GetValues(typeof(SiteCode))) - { - // If we have a null site code, just skip - if (siteCode == null) - continue; - - // If the line doesn't contain this tag, just skip - var shortName = siteCode.ShortName(); - if (shortName == null || !commentLine.Contains(shortName)) - continue; - - // Mark as having found a tag - foundTag = true; - - // Cache the current site code - lastSiteCode = siteCode; - - // A subset of tags can be multiline - addToLast = IsMultiLine(siteCode); - - // Skip certain site codes because of data issues - switch (siteCode) - { - // Multiple - case SiteCode.InternalSerialName: - case SiteCode.Multisession: - case SiteCode.VolumeLabel: - continue; - - // Audio CD - case SiteCode.RingNonZeroDataStart: - case SiteCode.UniversalHash: - continue; - - // Microsoft Xbox and Xbox 360 - case SiteCode.DMIHash: - case SiteCode.PFIHash: - case SiteCode.SSHash: - case SiteCode.SSVersion: - case SiteCode.XMID: - case SiteCode.XeMID: - continue; - - // Microsoft Xbox One and Series X/S - case SiteCode.Filename: - continue; - - // Nintendo Gamecube - case SiteCode.InternalName: - continue; - } - - // If we don't already have this site code, add it to the dictionary - if (!info.CommonDiscInfo.CommentsSpecialFields!.ContainsKey(siteCode.Value)) - info.CommonDiscInfo.CommentsSpecialFields[siteCode.Value] = $"(VERIFY THIS) {commentLine.Replace(shortName, string.Empty).Trim()}"; - - // Otherwise, append the value to the existing key - else - info.CommonDiscInfo.CommentsSpecialFields[siteCode.Value] += $", {commentLine.Replace(shortName, string.Empty).Trim()}"; - - break; - } - - // If we didn't find a known tag, just add the line, just in case - if (!foundTag) - { - if (addToLast && lastSiteCode != null) - { - if (!string.IsNullOrWhiteSpace(info.CommonDiscInfo.CommentsSpecialFields![lastSiteCode.Value])) - info.CommonDiscInfo.CommentsSpecialFields[lastSiteCode.Value] += "\n"; - - info.CommonDiscInfo.CommentsSpecialFields[lastSiteCode.Value] += commentLine; - } - else - { - newComments += $"{commentLine}\n"; - } - } - } - - // Set the new comments field - info.CommonDiscInfo.Comments = newComments; - } - } - - // Contents - if (includeAllData) - { - match = Constants.ContentsRegex.Match(discData); - if (match.Success) - { - // Process the old contents block - string oldContents = info.CommonDiscInfo.Contents - + (string.IsNullOrEmpty(info.CommonDiscInfo.Contents) ? string.Empty : "\n") - + WebUtility.HtmlDecode(match.Groups[1].Value) - .Replace("\r\n", "\n") - .Replace("
\n", "\n") - .Replace("
", string.Empty) - .Replace("
", string.Empty) - .Replace("[+]", string.Empty) - .ReplaceHtmlWithSiteCodes(); - oldContents = Regex.Replace(oldContents, @"
", string.Empty, RegexOptions.Compiled); - - // Create state variables - bool addToLast = false; - SiteCode? lastSiteCode = null; - string newContents = string.Empty; - - // Process the contents block line-by-line - string[] contentsSeparated = oldContents.Split('\n'); - for (int i = 0; i < contentsSeparated.Length; i++) - { - string contentLine = contentsSeparated[i].Trim(); - - // If we have an empty line, we want to treat this as intentional - if (string.IsNullOrWhiteSpace(contentLine)) - { - addToLast = false; - lastSiteCode = null; - newContents += $"{contentLine}\n"; - continue; - } - - // Otherwise, we need to find what tag is in use - bool foundTag = false; - foreach (SiteCode? siteCode in Enum.GetValues(typeof(SiteCode))) - { - // If we have a null site code, just skip - if (siteCode == null) - continue; - - // If the line doesn't contain this tag, just skip - var shortName = siteCode.ShortName(); - if (shortName == null || !contentLine.Contains(shortName)) - continue; - - // Cache the current site code - lastSiteCode = siteCode; - - // If we don't already have this site code, add it to the dictionary - if (!info.CommonDiscInfo.ContentsSpecialFields!.ContainsKey(siteCode.Value)) - info.CommonDiscInfo.ContentsSpecialFields[siteCode.Value] = $"(VERIFY THIS) {contentLine.Replace(shortName, string.Empty).Trim()}"; - - // A subset of tags can be multiline - addToLast = IsMultiLine(siteCode); - - // Mark as having found a tag - foundTag = true; - break; - } - - // If we didn't find a known tag, just add the line, just in case - if (!foundTag) - { - if (addToLast && lastSiteCode != null) - { - if (!string.IsNullOrWhiteSpace(info.CommonDiscInfo.ContentsSpecialFields![lastSiteCode.Value])) - info.CommonDiscInfo.ContentsSpecialFields[lastSiteCode.Value] += "\n"; - - info.CommonDiscInfo.ContentsSpecialFields[lastSiteCode.Value] += contentLine; - } - else - { - newContents += $"{contentLine}\n"; - } - } - } - - // Set the new contents field - info.CommonDiscInfo.Contents = newContents; - } - } - - // Added - match = Constants.AddedRegex.Match(discData); - if (match.Success) - { - if (DateTime.TryParse(match.Groups[1].Value, out DateTime added)) - info.Added = added; - else - info.Added = null; - } - - // Last Modified - match = Constants.LastModifiedRegex.Match(discData); - if (match.Success) - { - if (DateTime.TryParse(match.Groups[1].Value, out DateTime lastModified)) - info.LastModified = lastModified; - else - info.LastModified = null; - } - - return true; - } - /// /// Fill in a SubmissionInfo object from Redump, if possible /// @@ -1173,10 +526,14 @@ namespace MPF.Core } #if NET40 - (bool singleFound, var foundIds) = ValidateSingleTrack(wc, info, hashData, resultProgress); + (bool singleFound, var foundIds, string? result) = Validator.ValidateSingleTrack(wc, info, hashData); #else - (bool singleFound, var foundIds) = await ValidateSingleTrack(wc, info, hashData, resultProgress); + (bool singleFound, var foundIds, string? result) = await Validator.ValidateSingleTrack(wc, info, hashData); #endif + if (singleFound) + resultProgress?.Report(Result.Success(result)); + else + resultProgress?.Report(Result.Failure(result)); // Ensure that all tracks are found allFound &= singleFound; @@ -1200,10 +557,14 @@ namespace MPF.Core if (!info.PartiallyMatchedIDs.Any() && info.CommonDiscInfo?.CommentsSpecialFields?.ContainsKey(SiteCode.UniversalHash) == true) { #if NET40 - (bool singleFound, var foundIds) = ValidateUniversalHash(wc, info, resultProgress); + (bool singleFound, var foundIds, string? result) = Validator.ValidateUniversalHash(wc, info); #else - (bool singleFound, var foundIds) = await ValidateUniversalHash(wc, info, resultProgress); + (bool singleFound, var foundIds, string? result) = await Validator.ValidateUniversalHash(wc, info); #endif + if (singleFound) + resultProgress?.Report(Result.Success(result)); + else + resultProgress?.Report(Result.Failure(result)); // Ensure that the hash is found allFound = singleFound; @@ -1237,18 +598,18 @@ namespace MPF.Core { // Skip if the track count doesn't match #if NET40 - if (!ValidateTrackCount(wc, fullyMatchedIDs[i], trackCount)) + if (!Validator.ValidateTrackCount(wc, fullyMatchedIDs[i], trackCount)) #else - if (!await ValidateTrackCount(wc, fullyMatchedIDs[i], trackCount)) + if (!await Validator.ValidateTrackCount(wc, fullyMatchedIDs[i], trackCount)) #endif continue; // Fill in the fields from the existing ID resultProgress?.Report(Result.Success($"Filling fields from existing ID {fullyMatchedIDs[i]}...")); #if NET40 - _ = FillFromId(wc, info, fullyMatchedIDs[i], options.PullAllInformation); + _ = Builder.FillFromId(wc, info, fullyMatchedIDs[i], options.PullAllInformation); #else - _ = await FillFromId(wc, info, fullyMatchedIDs[i], options.PullAllInformation); + _ = await Builder.FillFromId(wc, info, fullyMatchedIDs[i], options.PullAllInformation); #endif resultProgress?.Report(Result.Success("Information filling complete!")); @@ -1269,358 +630,6 @@ namespace MPF.Core return true; } - // Moved to RedumpLib - /// - /// Inject information from a seed SubmissionInfo into the existing one - /// - /// Existing submission information - /// User-supplied submission information - public static void InjectSubmissionInformation(SubmissionInfo? info, SubmissionInfo? seed) - { - // If we have any invalid info - if (seed == null) - return; - - // Ensure that required sections exist - info = EnsureAllSections(info); - - // Otherwise, inject information as necessary - if (info.CommonDiscInfo != null && seed.CommonDiscInfo != null) - { - // Info that only overwrites if supplied - if (!string.IsNullOrWhiteSpace(seed.CommonDiscInfo.Title)) info.CommonDiscInfo.Title = seed.CommonDiscInfo.Title; - if (!string.IsNullOrWhiteSpace(seed.CommonDiscInfo.ForeignTitleNonLatin)) info.CommonDiscInfo.ForeignTitleNonLatin = seed.CommonDiscInfo.ForeignTitleNonLatin; - if (!string.IsNullOrWhiteSpace(seed.CommonDiscInfo.DiscNumberLetter)) info.CommonDiscInfo.DiscNumberLetter = seed.CommonDiscInfo.DiscNumberLetter; - if (!string.IsNullOrWhiteSpace(seed.CommonDiscInfo.DiscTitle)) info.CommonDiscInfo.DiscTitle = seed.CommonDiscInfo.DiscTitle; - if (seed.CommonDiscInfo.Category != null) info.CommonDiscInfo.Category = seed.CommonDiscInfo.Category; - if (seed.CommonDiscInfo.Region != null) info.CommonDiscInfo.Region = seed.CommonDiscInfo.Region; - if (seed.CommonDiscInfo.Languages != null) info.CommonDiscInfo.Languages = seed.CommonDiscInfo.Languages; - if (seed.CommonDiscInfo.LanguageSelection != null) info.CommonDiscInfo.LanguageSelection = seed.CommonDiscInfo.LanguageSelection; - if (!string.IsNullOrWhiteSpace(seed.CommonDiscInfo.Serial)) info.CommonDiscInfo.Serial = seed.CommonDiscInfo.Serial; - if (!string.IsNullOrWhiteSpace(seed.CommonDiscInfo.Barcode)) info.CommonDiscInfo.Barcode = seed.CommonDiscInfo.Barcode; - if (!string.IsNullOrWhiteSpace(seed.CommonDiscInfo.Comments)) info.CommonDiscInfo.Comments = seed.CommonDiscInfo.Comments; - if (seed.CommonDiscInfo.CommentsSpecialFields != null) info.CommonDiscInfo.CommentsSpecialFields = seed.CommonDiscInfo.CommentsSpecialFields; - if (!string.IsNullOrWhiteSpace(seed.CommonDiscInfo.Contents)) info.CommonDiscInfo.Contents = seed.CommonDiscInfo.Contents; - if (seed.CommonDiscInfo.ContentsSpecialFields != null) info.CommonDiscInfo.ContentsSpecialFields = seed.CommonDiscInfo.ContentsSpecialFields; - - // Info that always overwrites - info.CommonDiscInfo.Layer0MasteringRing = seed.CommonDiscInfo.Layer0MasteringRing; - info.CommonDiscInfo.Layer0MasteringSID = seed.CommonDiscInfo.Layer0MasteringSID; - info.CommonDiscInfo.Layer0ToolstampMasteringCode = seed.CommonDiscInfo.Layer0ToolstampMasteringCode; - info.CommonDiscInfo.Layer0MouldSID = seed.CommonDiscInfo.Layer0MouldSID; - info.CommonDiscInfo.Layer0AdditionalMould = seed.CommonDiscInfo.Layer0AdditionalMould; - - info.CommonDiscInfo.Layer1MasteringRing = seed.CommonDiscInfo.Layer1MasteringRing; - info.CommonDiscInfo.Layer1MasteringSID = seed.CommonDiscInfo.Layer1MasteringSID; - info.CommonDiscInfo.Layer1ToolstampMasteringCode = seed.CommonDiscInfo.Layer1ToolstampMasteringCode; - info.CommonDiscInfo.Layer1MouldSID = seed.CommonDiscInfo.Layer1MouldSID; - info.CommonDiscInfo.Layer1AdditionalMould = seed.CommonDiscInfo.Layer1AdditionalMould; - - info.CommonDiscInfo.Layer2MasteringRing = seed.CommonDiscInfo.Layer2MasteringRing; - info.CommonDiscInfo.Layer2MasteringSID = seed.CommonDiscInfo.Layer2MasteringSID; - info.CommonDiscInfo.Layer2ToolstampMasteringCode = seed.CommonDiscInfo.Layer2ToolstampMasteringCode; - - info.CommonDiscInfo.Layer3MasteringRing = seed.CommonDiscInfo.Layer3MasteringRing; - info.CommonDiscInfo.Layer3MasteringSID = seed.CommonDiscInfo.Layer3MasteringSID; - info.CommonDiscInfo.Layer3ToolstampMasteringCode = seed.CommonDiscInfo.Layer3ToolstampMasteringCode; - } - - if (info.VersionAndEditions != null && seed.VersionAndEditions != null) - { - // Info that only overwrites if supplied - if (!string.IsNullOrWhiteSpace(seed.VersionAndEditions.Version)) info.VersionAndEditions.Version = seed.VersionAndEditions.Version; - if (!string.IsNullOrWhiteSpace(seed.VersionAndEditions.OtherEditions)) info.VersionAndEditions.OtherEditions = seed.VersionAndEditions.OtherEditions; - } - - if (info.CopyProtection != null && seed.CopyProtection != null) - { - // Info that only overwrites if supplied - if (!string.IsNullOrWhiteSpace(seed.CopyProtection.Protection)) info.CopyProtection.Protection = seed.CopyProtection.Protection; - } - } - - #endregion - - #region Helpers - - // Moved to RedumpLib - /// - /// Check if a site code is multi-line or not - /// - /// SiteCode to check - /// True if the code field is multiline by default, false otherwise - /// TODO: This should move to Extensions at some point - public static bool IsMultiLine(SiteCode? siteCode) - { - return siteCode switch - { - SiteCode.Extras => true, - SiteCode.Filename => true, - SiteCode.Games => true, - SiteCode.GameFootage => true, - SiteCode.Multisession => true, - SiteCode.NetYarozeGames => true, - SiteCode.Patches => true, - SiteCode.PlayableDemos => true, - SiteCode.RollingDemos => true, - SiteCode.Savegames => true, - SiteCode.TechDemos => true, - SiteCode.Videos => true, - _ => false, - }; - } - - // Moved to RedumpLib - /// - /// Process a text block and replace with internal identifiers - /// - /// Text block to process - /// Processed text block, if possible - private static string ReplaceHtmlWithSiteCodes(this string text) - { - if (string.IsNullOrWhiteSpace(text)) - return text; - - foreach (SiteCode? siteCode in Enum.GetValues(typeof(SiteCode))) - { - var longname = siteCode.LongName(); - if (!string.IsNullOrEmpty(longname)) - text = text.Replace(longname, siteCode.ShortName()); - } - - // For some outdated tags, we need to use alternate names - text = text.Replace("Demos:", ((SiteCode?)SiteCode.PlayableDemos).ShortName()); - text = text.Replace("DMI:", ((SiteCode?)SiteCode.DMIHash).ShortName()); - text = text.Replace("LucasArts ID:", ((SiteCode?)SiteCode.LucasArtsID).ShortName()); - text = text.Replace("PFI:", ((SiteCode?)SiteCode.PFIHash).ShortName()); - text = text.Replace("SS:", ((SiteCode?)SiteCode.SSHash).ShortName()); - text = text.Replace("SSv1:", ((SiteCode?)SiteCode.SSHash).ShortName()); - text = text.Replace("SSv1:", ((SiteCode?)SiteCode.SSHash).ShortName()); - text = text.Replace("SSv2:", ((SiteCode?)SiteCode.SSHash).ShortName()); - text = text.Replace("SSv2:", ((SiteCode?)SiteCode.SSHash).ShortName()); - text = text.Replace("SS version:", ((SiteCode?)SiteCode.SSVersion).ShortName()); - text = text.Replace("Universal Hash (SHA-1):", ((SiteCode?)SiteCode.UniversalHash).ShortName()); - text = text.Replace("XeMID:", ((SiteCode?)SiteCode.XeMID).ShortName()); - text = text.Replace("XMID:", ((SiteCode?)SiteCode.XMID).ShortName()); - - return text; - } - - // Moved to RedumpLib - /// - /// List the disc IDs associated with a given quicksearch query - /// - /// RedumpWebClient for making the connection - /// Query string to attempt to search for - /// True to filter forward slashes, false otherwise - /// All disc IDs for the given query, null on error -#if NET40 - private static List? ListSearchResults(RedumpWebClient wc, string? query, bool filterForwardSlashes = true) -#elif NETFRAMEWORK - private async static Task?> ListSearchResults(RedumpWebClient wc, string? query, bool filterForwardSlashes = true) -#else - private async static Task?> ListSearchResults(RedumpHttpClient wc, string? query, bool filterForwardSlashes = true) -#endif - { - // If there is an invalid query - if (string.IsNullOrWhiteSpace(query)) - return null; - - var ids = new List(); - - // Strip quotes - query = query!.Trim('"', '\''); - - // Special characters become dashes - query = query.Replace(' ', '-'); - if (filterForwardSlashes) - query = query.Replace('/', '-'); - query = query.Replace('\\', '/'); - - // Lowercase is defined per language - query = query.ToLowerInvariant(); - - // Keep getting quicksearch pages until there are none left - try - { - int pageNumber = 1; - while (true) - { -#if NET40 - List pageIds = wc.CheckSingleSitePage(string.Format(Constants.QuickSearchUrl, query, pageNumber++)); -#elif NETFRAMEWORK - List pageIds = await Task.Run(() => wc.CheckSingleSitePage(string.Format(Constants.QuickSearchUrl, query, pageNumber++))); -#else - List pageIds = await wc.CheckSingleSitePage(string.Format(Constants.QuickSearchUrl, query, pageNumber++)); -#endif - ids.AddRange(pageIds); - if (pageIds.Count <= 1) - break; - } - } - catch (Exception ex) - { - Console.WriteLine($"An exception occurred while trying to log in: {ex}"); - return null; - } - - return ids; - } - - // Moved to RedumpLib - /// - /// Validate a single track against Redump, if possible - /// - /// RedumpWebClient for making the connection - /// Existing SubmissionInfo object to fill - /// DAT-formatted hash data to parse out - /// Optional result progress callback - /// True if the track was found, false otherwise; List of found values, if possible -#if NET40 - private static (bool, List?) ValidateSingleTrack(RedumpWebClient wc, SubmissionInfo info, string hashData, IProgress? resultProgress = null) -#elif NETFRAMEWORK - private async static Task<(bool, List?)> ValidateSingleTrack(RedumpWebClient wc, SubmissionInfo info, string hashData, IProgress? resultProgress = null) -#else - private async static Task<(bool, List?)> ValidateSingleTrack(RedumpHttpClient wc, SubmissionInfo info, string hashData, IProgress? resultProgress = null) -#endif - { - // If the line isn't parseable, we can't validate - if (!InfoTool.GetISOHashValues(hashData, out long _, out var _, out var _, out var sha1)) - { - resultProgress?.Report(Result.Failure("Line could not be parsed for hash data")); - return (false, null); - } - - // Get all matching IDs for the track -#if NET40 - var newIds = ListSearchResults(wc, sha1); -#else - var newIds = await ListSearchResults(wc, sha1); -#endif - - // If we got null back, there was an error - if (newIds == null) - { - resultProgress?.Report(Result.Failure("There was an unknown error retrieving information from Redump")); - return (false, null); - } - - // If no IDs match any track, just return - if (!newIds.Any()) - return (false, null); - - // Join the list of found IDs to the existing list, if possible - if (info.PartiallyMatchedIDs != null && info.PartiallyMatchedIDs.Any()) - info.PartiallyMatchedIDs.AddRange(newIds); - else - info.PartiallyMatchedIDs = newIds; - - return (true, newIds); - } - - // Moved to RedumpLib - /// - /// Validate a universal hash against Redump, if possible - /// - /// RedumpWebClient for making the connection - /// Existing SubmissionInfo object to fill - /// Optional result progress callback - /// True if the track was found, false otherwise; List of found values, if possible -#if NET40 - private static (bool, List?) ValidateUniversalHash(RedumpWebClient wc, SubmissionInfo info, IProgress? resultProgress = null) -#elif NETFRAMEWORK - private async static Task<(bool, List?)> ValidateUniversalHash(RedumpWebClient wc, SubmissionInfo info, IProgress? resultProgress = null) -#else - private async static Task<(bool, List?)> ValidateUniversalHash(RedumpHttpClient wc, SubmissionInfo info, IProgress? resultProgress = null) -#endif - { - // If we don't have special fields - if (info.CommonDiscInfo?.CommentsSpecialFields == null) - { - resultProgress?.Report(Result.Failure("Universal hash was missing")); - return (false, null); - } - - // If we don't have a universal hash - var universalHash = info.CommonDiscInfo.CommentsSpecialFields[SiteCode.UniversalHash]; - if (string.IsNullOrEmpty(universalHash)) - { - resultProgress?.Report(Result.Failure("Universal hash was missing")); - return (false, null); - } - - // Format the universal hash for finding within the comments - universalHash = $"{universalHash[..^1]}/comments/only"; - - // Get all matching IDs for the hash -#if NET40 - var newIds = ListSearchResults(wc, universalHash, filterForwardSlashes: false); -#else - var newIds = await ListSearchResults(wc, universalHash, filterForwardSlashes: false); -#endif - - // If we got null back, there was an error - if (newIds == null) - { - resultProgress?.Report(Result.Failure("There was an unknown error retrieving information from Redump")); - return (false, null); - } - - // If no IDs match any track, just return - if (!newIds.Any()) - return (false, null); - - // Join the list of found IDs to the existing list, if possible - if (info.PartiallyMatchedIDs != null && info.PartiallyMatchedIDs.Any()) - info.PartiallyMatchedIDs.AddRange(newIds); - else - info.PartiallyMatchedIDs = newIds; - - return (true, newIds); - } - - // Moved to RedumpLib - /// - /// Validate that the current track count and remote track count match - /// - /// RedumpWebClient for making the connection - /// Redump disc ID to retrieve - /// Local count of tracks for the current disc - /// True if the track count matches, false otherwise -#if NET40 - private static bool ValidateTrackCount(RedumpWebClient wc, int id, int localCount) -#elif NETFRAMEWORK - private async static Task ValidateTrackCount(RedumpWebClient wc, int id, int localCount) -#else - private async static Task ValidateTrackCount(RedumpHttpClient wc, int id, int localCount) -#endif - { - // If we can't pull the remote data, we can't match -#if NET40 - string? discData = wc.DownloadSingleSiteID(id); -#elif NETFRAMEWORK - string? discData = await Task.Run(() => wc.DownloadSingleSiteID(id)); -#else - string? discData = await wc.DownloadSingleSiteID(id); -#endif - if (string.IsNullOrEmpty(discData)) - return false; - - // Discs with only 1 track don't have a track count listed - var match = Constants.TrackCountRegex.Match(discData); - if (!match.Success && localCount == 1) - return true; - else if (!match.Success) - return false; - - // If the count isn't parseable, we're not taking chances - if (!Int32.TryParse(match.Groups[1].Value, out int remoteCount)) - return false; - - // Finally check to see if the counts match - return localCount == remoteCount; - } - #endregion } } diff --git a/MPF.Core/Utilities/EnumExtensions.cs b/MPF.Core/Utilities/EnumExtensions.cs index 6c45e530..d44acfb2 100644 --- a/MPF.Core/Utilities/EnumExtensions.cs +++ b/MPF.Core/Utilities/EnumExtensions.cs @@ -8,34 +8,6 @@ namespace MPF.Core.Utilities { public static class EnumExtensions { - // Moved to RedumpLib - /// - /// Determine if a system is okay if it's not detected by Windows - /// - /// RedumpSystem value to check - /// True if Windows show see a disc when dumping, false otherwise - public static bool DetectedByWindows(this RedumpSystem? system) - { - return system switch - { - RedumpSystem.AmericanLaserGames3DO - or RedumpSystem.AppleMacintosh - or RedumpSystem.Atari3DO - or RedumpSystem.AtariJaguarCDInteractiveMultimediaSystem - or RedumpSystem.NewJatreCDi - or RedumpSystem.NintendoGameCube - or RedumpSystem.NintendoWii - or RedumpSystem.NintendoWiiU - or RedumpSystem.PhilipsCDi - or RedumpSystem.PhilipsCDiDigitalVideo - or RedumpSystem.Panasonic3DOInteractiveMultiplayer - or RedumpSystem.PanasonicM2 - or RedumpSystem.PioneerLaserActive - or RedumpSystem.SuperAudioCD => false, - _ => true, - }; - } - /// /// Determine if the media supports drive speeds /// @@ -56,72 +28,6 @@ namespace MPF.Core.Utilities }; } - // Moved to RedumpLib - /// - /// Determine if a system has reversed ringcodes - /// - /// RedumpSystem value to check - /// True if the system has reversed ringcodes, false otherwise - public static bool HasReversedRingcodes(this RedumpSystem? system) - { - return system switch - { - RedumpSystem.SonyPlayStation2 - or RedumpSystem.SonyPlayStation3 - or RedumpSystem.SonyPlayStation4 - or RedumpSystem.SonyPlayStation5 - or RedumpSystem.SonyPlayStationPortable => true, - _ => false, - }; - } - - // Moved to RedumpLib - /// - /// Determine if a system is considered audio-only - /// - /// RedumpSystem value to check - /// True if the system is audio-only, false otherwise - /// - /// Philips CD-i should NOT be in this list. It's being included until there's a - /// reasonable distinction between CD-i and CD-i ready on the database side. - /// - public static bool IsAudio(this RedumpSystem? system) - { - return system switch - { - RedumpSystem.AtariJaguarCDInteractiveMultimediaSystem - or RedumpSystem.AudioCD - or RedumpSystem.DVDAudio - or RedumpSystem.HasbroiONEducationalGamingSystem - or RedumpSystem.HasbroVideoNow - or RedumpSystem.HasbroVideoNowColor - or RedumpSystem.HasbroVideoNowJr - or RedumpSystem.HasbroVideoNowXP - or RedumpSystem.PhilipsCDi - or RedumpSystem.PlayStationGameSharkUpdates - or RedumpSystem.SuperAudioCD => true, - _ => false, - }; - } - - // Moved to RedumpLib - /// - /// Determine if a system is considered XGD - /// - /// RedumpSystem value to check - /// True if the system is XGD, false otherwise - public static bool IsXGD(this RedumpSystem? system) - { - return system switch - { - RedumpSystem.MicrosoftXbox - or RedumpSystem.MicrosoftXbox360 - or RedumpSystem.MicrosoftXboxOne - or RedumpSystem.MicrosoftXboxSeriesXS => true, - _ => false, - }; - } - /// /// List all programs with their short usable names /// diff --git a/MPF.Core/Utilities/OptionsLoader.cs b/MPF.Core/Utilities/OptionsLoader.cs index 6adb6646..b61f8750 100644 --- a/MPF.Core/Utilities/OptionsLoader.cs +++ b/MPF.Core/Utilities/OptionsLoader.cs @@ -4,6 +4,7 @@ using System.IO; using MPF.Core.Converters; using MPF.Core.Data; using Newtonsoft.Json; +using SabreTools.RedumpLib; using SabreTools.RedumpLib.Data; namespace MPF.Core.Utilities @@ -177,12 +178,12 @@ namespace MPF.Core.Utilities else if (args[startIndex].StartsWith("-l=") || args[startIndex].StartsWith("--load-seed=")) { string seedInfo = args[startIndex].Split('=')[1]; - info = SubmissionInfoTool.CreateFromFile(seedInfo); + info = Builder.CreateFromFile(seedInfo); } else if (args[startIndex] == "-l" || args[startIndex] == "--load-seed") { string seedInfo = args[startIndex + 1]; - info = SubmissionInfoTool.CreateFromFile(seedInfo); + info = Builder.CreateFromFile(seedInfo); startIndex++; } diff --git a/MPF.Test/Library/InfoToolTests.cs b/MPF.Test/Library/InfoToolTests.cs index 0bff1a93..12619ed5 100644 --- a/MPF.Test/Library/InfoToolTests.cs +++ b/MPF.Test/Library/InfoToolTests.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.IO; using MPF.Core; +using SabreTools.RedumpLib; using SabreTools.RedumpLib.Data; using Xunit; @@ -8,47 +9,6 @@ namespace MPF.Test.Library { public class InfoToolTests { - [Theory] - [InlineData(null, 0, 0, 0, 0, null)] - [InlineData(null, 12345, 0, 0, 0, null)] - [InlineData(null, 12345, 1, 0, 0, null)] - [InlineData(null, 12345, 1, 2, 0, null)] - [InlineData(null, 12345, 1, 2, 3, null)] - [InlineData(MediaType.CDROM, 0, 0, 0, 0, "CD-ROM")] - [InlineData(MediaType.CDROM, 12345, 0, 0, 0, "CD-ROM")] - [InlineData(MediaType.CDROM, 12345, 1, 0, 0, "CD-ROM")] - [InlineData(MediaType.CDROM, 12345, 1, 2, 0, "CD-ROM")] - [InlineData(MediaType.CDROM, 12345, 1, 2, 3, "CD-ROM")] - [InlineData(MediaType.DVD, 0, 0, 0, 0, "DVD-ROM-5")] - [InlineData(MediaType.DVD, 12345, 0, 0, 0, "DVD-ROM-5")] - [InlineData(MediaType.DVD, 12345, 1, 0, 0, "DVD-ROM-9")] - [InlineData(MediaType.DVD, 12345, 1, 2, 0, "DVD-ROM-9")] - [InlineData(MediaType.DVD, 12345, 1, 2, 3, "DVD-ROM-9")] - [InlineData(MediaType.BluRay, 0, 0, 0, 0, "BD-ROM-25")] - [InlineData(MediaType.BluRay, 12345, 0, 0, 0, "BD-ROM-25")] - [InlineData(MediaType.BluRay, 26_843_531_857, 0, 0, 0, "BD-ROM-33")] - [InlineData(MediaType.BluRay, 12345, 1, 0, 0, "BD-ROM-50")] - [InlineData(MediaType.BluRay, 53_687_063_713, 1, 0, 0, "BD-ROM-66")] - [InlineData(MediaType.BluRay, 12345, 1, 2, 0, "BD-ROM-100")] - [InlineData(MediaType.BluRay, 12345, 1, 2, 3, "BD-ROM-128")] - [InlineData(MediaType.UMD, 0, 0, 0, 0, "UMD-SL")] - [InlineData(MediaType.UMD, 12345, 0, 0, 0, "UMD-SL")] - [InlineData(MediaType.UMD, 12345, 1, 0, 0, "UMD-DL")] - [InlineData(MediaType.UMD, 12345, 1, 2, 0, "UMD-DL")] - [InlineData(MediaType.UMD, 12345, 1, 2, 3, "UMD-DL")] - public void GetFixedMediaTypeTest( - MediaType? mediaType, - long size, - long layerbreak, - long layerbreak2, - long layerbreak3, - string? expected) - { - // TODO: Add tests around BDU - var actual = InfoTool.GetFixedMediaType(mediaType, null, size, layerbreak, layerbreak2, layerbreak3); - Assert.Equal(expected, actual); - } - [Theory] [InlineData(null, "")] [InlineData(" ", "")] @@ -90,7 +50,7 @@ namespace MPF.Test.Library }; // Process the special fields - InfoTool.ProcessSpecialFields(info); + Formatter.ProcessSpecialFields(info); // Validate the basics Assert.NotNull(info.CommonDiscInfo.Comments); @@ -117,7 +77,7 @@ namespace MPF.Test.Library }; // Process the special fields - InfoTool.ProcessSpecialFields(info); + Formatter.ProcessSpecialFields(info); // Validate Assert.Null(info.CommonDiscInfo); @@ -146,7 +106,7 @@ namespace MPF.Test.Library }; // Process the special fields - InfoTool.ProcessSpecialFields(info); + Formatter.ProcessSpecialFields(info); // Validate the basics Assert.NotNull(info.CommonDiscInfo.Comments); @@ -180,7 +140,7 @@ namespace MPF.Test.Library }; // Process the special fields - InfoTool.ProcessSpecialFields(info); + Formatter.ProcessSpecialFields(info); // Validate the basics Assert.NotNull(info.CommonDiscInfo.Comments); diff --git a/MPF.Test/MPF.Test.csproj b/MPF.Test/MPF.Test.csproj index adef720d..9853ba6b 100644 --- a/MPF.Test/MPF.Test.csproj +++ b/MPF.Test/MPF.Test.csproj @@ -17,7 +17,7 @@ - + diff --git a/MPF.UI.Core/MPF.UI.Core.csproj b/MPF.UI.Core/MPF.UI.Core.csproj index 03367096..61ee1e7d 100644 --- a/MPF.UI.Core/MPF.UI.Core.csproj +++ b/MPF.UI.Core/MPF.UI.Core.csproj @@ -32,7 +32,7 @@ - + diff --git a/MPF.UI.Core/Windows/MainWindow.xaml.cs b/MPF.UI.Core/Windows/MainWindow.xaml.cs index a531f680..3a9cd322 100644 --- a/MPF.UI.Core/Windows/MainWindow.xaml.cs +++ b/MPF.UI.Core/Windows/MainWindow.xaml.cs @@ -4,6 +4,7 @@ using System.Windows; using System.Windows.Controls; using MPF.Core; using MPF.Core.UI.ViewModels; +using SabreTools.RedumpLib; using SabreTools.RedumpLib.Data; using WPFCustomMessageBox; using WinForms = System.Windows.Forms; @@ -197,7 +198,7 @@ namespace MPF.UI.Core.Windows { var submissionInfo = MainViewModel.CreateDebugSubmissionInfo(); var result = ShowDiscInformationWindow(submissionInfo); - InfoTool.ProcessSpecialFields(result.Item2); + Formatter.ProcessSpecialFields(result.Item2); } /// diff --git a/MPF/MPF.csproj b/MPF/MPF.csproj index 08ec6606..0c1554a5 100644 --- a/MPF/MPF.csproj +++ b/MPF/MPF.csproj @@ -45,7 +45,7 @@ runtime; compile; build; native; analyzers; buildtransitive - +