diff --git a/SabreTools.DatFiles/Formats/SoftwareList.Writer.cs b/SabreTools.DatFiles/Formats/SoftwareList.Writer.cs index c26793d7..b7e824dd 100644 --- a/SabreTools.DatFiles/Formats/SoftwareList.Writer.cs +++ b/SabreTools.DatFiles/Formats/SoftwareList.Writer.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Linq; using SabreTools.Core; -using SabreTools.Core.Tools; using SabreTools.DatItems; using SabreTools.DatItems.Formats; @@ -21,6 +20,7 @@ namespace SabreTools.DatFiles.Formats ItemType.DipSwitch, ItemType.Disk, ItemType.Info, + ItemType.PartFeature, ItemType.Rom, ItemType.SharedFeat, ]; @@ -139,8 +139,10 @@ namespace SabreTools.DatFiles.Formats { logger.User($"Writing to '{outfile}'..."); - var softwarelist = CreateSoftwareList(ignoreblanks); - if (!(new Serialization.Files.SoftwareList().SerializeToFileWithDocType(softwarelist, outfile))) + // Serialize the input file + var metadata = ConvertMetadata(ignoreblanks); + var softwarelist = new Serialization.CrossModel.SoftwareList().Deserialize(metadata); + if (!(new Serialization.Files.SoftwareList().SerializeToFileWithDocType(softwarelist!, outfile))) { logger.Warning($"File '{outfile}' could not be written! See the log for more details."); return false; @@ -155,432 +157,5 @@ namespace SabreTools.DatFiles.Formats logger.User($"'{outfile}' written!{Environment.NewLine}"); return true; } - - #region Converters - - /// - /// Create a SoftwareList from the current internal information - /// - /// True if blank roms should be skipped on output, false otherwise - private Models.SoftwareList.SoftwareList CreateSoftwareList(bool ignoreblanks) - { - var softwarelist = new Models.SoftwareList.SoftwareList - { - Name = Header.GetStringFieldValue(Models.Metadata.Header.NameKey), - Description = Header.GetStringFieldValue(Models.Metadata.Header.DescriptionKey), - Notes = Header.GetStringFieldValue(Models.Metadata.Header.CommentKey), - Software = CreateSoftware(ignoreblanks), - }; - - return softwarelist; - } - - /// - /// Create an array of Software from the current internal information - /// - /// True if blank roms should be skipped on output, false otherwise - private Models.SoftwareList.Software[]? CreateSoftware(bool ignoreblanks) - { - // If we don't have items, we can't do anything - if (this.Items == null || !this.Items.Any()) - return null; - - // Create a list of hold the games - var software = new List(); - - // Loop through the sorted items and create games for them - foreach (string key in Items.SortedKeys) - { - var items = Items.FilteredItems(key); - if (items == null || !items.Any()) - continue; - - // Get the first item for game information - var machine = items[0].GetFieldValue(DatItem.MachineKey); - var sw = CreateSoftware(machine!); - - // Create holders for all item types - var infos = new List(); - var sharedfeats = new List(); - var parts = new List(); - - // Loop through and convert the items to respective lists - for (int index = 0; index < items.Count; index++) - { - // Get the item - var item = items[index]; - - // Check for a "null" item - item = ProcessNullifiedItem(item); - - // Skip if we're ignoring the item - if (ShouldIgnore(item, ignoreblanks)) - continue; - - switch (item) - { - case Info info: - infos.Add(CreateInfo(info)); - break; - case SharedFeat sharedFeature: - sharedfeats.Add(CreateSharedFeat(sharedFeature)); - break; - case Rom rom: - parts.Add(CreatePart(rom)); - break; - case Disk disk: - parts.Add(CreatePart(disk)); - break; - case DipSwitch dipswitch: - parts.Add(CreatePart(dipswitch)); - break; - } - } - - // Process the parts to ensure we don't have duplicates - parts = SantitizeParts(parts); - - // Assign the values to the game - sw.Info = [.. infos]; - sw.SharedFeat = [.. sharedfeats]; - sw.Part = [.. parts]; - - // Add the game to the list - software.Add(sw); - } - - return [.. software]; - } - - /// - /// Create a Software from the current internal information - /// - private Models.SoftwareList.Software CreateSoftware(Machine machine) - { - var software = new Models.SoftwareList.Software - { - Name = machine.GetStringFieldValue(Models.Metadata.Machine.NameKey), - CloneOf = machine.GetStringFieldValue(Models.Metadata.Machine.CloneOfKey), - Supported = machine.GetStringFieldValue(Models.Metadata.Machine.SupportedKey).AsEnumValue().AsStringValue(useSecond: true), - Description = machine.GetStringFieldValue(Models.Metadata.Machine.DescriptionKey), - Year = machine.GetStringFieldValue(Models.Metadata.Machine.YearKey), - Publisher = machine.GetStringFieldValue(Models.Metadata.Machine.PublisherKey), - Notes = machine.GetStringFieldValue(Models.Metadata.Machine.CommentKey), - }; - - return software; - } - - /// - /// Create a Info from the current Info DatItem - /// - private static Models.SoftwareList.Info CreateInfo(Info item) - { - var info = new Models.SoftwareList.Info - { - Name = item.GetName(), - Value = item.GetStringFieldValue(Models.Metadata.Info.ValueKey), - }; - return info; - } - - /// - /// Create a SharedFeat from the current SharedFeature DatItem - /// - private static Models.SoftwareList.SharedFeat CreateSharedFeat(SharedFeat item) - { - var sharedfeat = new Models.SoftwareList.SharedFeat - { - Name = item.GetName(), - Value = item.GetStringFieldValue(Models.Metadata.SharedFeat.ValueKey), - }; - return sharedfeat; - } - - /// - /// Create a Part from the current Rom DatItem - /// - private static Models.SoftwareList.Part CreatePart(Rom item) - { - var part = new Models.SoftwareList.Part - { - Name = item.GetFieldValue(Rom.PartKey)?.GetName(), - Interface = item.GetFieldValue(Rom.PartKey)?.GetStringFieldValue(Models.Metadata.Part.InterfaceKey), - Feature = CreateFeatures(item.GetFieldValue(Rom.PartKey)?.GetFieldValue(Models.Metadata.Part.FeatureKey)), - DataArea = CreateDataAreas(item), - DiskArea = null, - DipSwitch = null, - }; - return part; - } - - /// - /// Create a Part from the current Disk DatItem - /// - private static Models.SoftwareList.Part CreatePart(Disk item) - { - var part = new Models.SoftwareList.Part - { - Name = item.GetFieldValue(Disk.PartKey)?.GetName(), - Interface = item.GetFieldValue(Disk.PartKey)?.GetStringFieldValue(Models.Metadata.Part.InterfaceKey), - Feature = CreateFeatures(item.GetFieldValue(Disk.PartKey)?.GetFieldValue(Models.Metadata.Part.FeatureKey)), - DataArea = null, - DiskArea = CreateDiskAreas(item), - DipSwitch = null, - }; - return part; - } - - /// - /// Create a Part from the current DipSwitch DatItem - /// - private static Models.SoftwareList.Part CreatePart(DipSwitch item) - { - var part = new Models.SoftwareList.Part - { - Name = item.GetFieldValue(DipSwitch.PartKey)?.GetName(), - Interface = item.GetFieldValue(DipSwitch.PartKey)?.GetStringFieldValue(Models.Metadata.Part.InterfaceKey), - Feature = CreateFeatures(item.GetFieldValue(DipSwitch.PartKey)?.GetFieldValue(Models.Metadata.Part.FeatureKey)), - DataArea = null, - DiskArea = null, - DipSwitch = CreateDipSwitches(item), - }; - return part; - } - - /// - /// Create a Feature array from the current list of PartFeature DatItems - /// - private static Models.SoftwareList.Feature[]? CreateFeatures(PartFeature[]? items) - { - // If we don't have features, we can't do anything - if (items == null || !items.Any()) - return null; - - var features = new List(); - foreach (var item in items) - { - var feature = new Models.SoftwareList.Feature - { - Name = item.GetName(), - Value = item.GetStringFieldValue(Models.Metadata.Feature.ValueKey), - }; - features.Add(feature); - } - - return [.. features]; - } - - /// - /// Create a DataArea array from the current Rom DatItem - /// - private static Models.SoftwareList.DataArea[]? CreateDataAreas(Rom item) - { - var dataArea = new Models.SoftwareList.DataArea - { - Name = item.GetFieldValue(Rom.DataAreaKey)?.GetName(), - Size = item.GetFieldValue(Rom.DataAreaKey)?.GetInt64FieldValue(Models.Metadata.DataArea.SizeKey)?.ToString(), - Width = item.GetFieldValue(Rom.DataAreaKey)?.GetInt64FieldValue(Models.Metadata.DataArea.WidthKey)?.ToString(), - Endianness = item.GetFieldValue(Rom.DataAreaKey)?.GetStringFieldValue(Models.Metadata.DataArea.EndiannessKey).AsEnumValue().AsStringValue(), - Rom = CreateRom(item), - }; - return [dataArea]; - } - - /// - /// Create a Rom array from the current Rom DatItem - /// - private static Models.SoftwareList.Rom[]? CreateRom(Rom item) - { - var rom = new Models.SoftwareList.Rom - { - Name = item.GetName(), - Size = item.GetStringFieldValue(Models.Metadata.Rom.SizeKey), - Length = null, - CRC = item.GetStringFieldValue(Models.Metadata.Rom.CRCKey), - SHA1 = item.GetStringFieldValue(Models.Metadata.Rom.SHA1Key), - Offset = item.GetStringFieldValue(Models.Metadata.Rom.OffsetKey), - Value = item.GetStringFieldValue(Models.Metadata.Rom.ValueKey), - Status = item.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue().AsStringValue(useSecond: false), - LoadFlag = item.GetStringFieldValue(Models.Metadata.Rom.LoadFlagKey).AsEnumValue().AsStringValue(), - }; - return [rom]; - } - - /// - /// Create a DiskArea array from the current Disk DatItem - /// - private static Models.SoftwareList.DiskArea[]? CreateDiskAreas(Disk item) - { - var diskArea = new Models.SoftwareList.DiskArea - { - Disk = CreateDisk(item), - }; - return [diskArea]; - } - - /// - /// Create a Disk array from the current Disk DatItem - /// - private static Models.SoftwareList.Disk[]? CreateDisk(Disk item) - { - var disk = new Models.SoftwareList.Disk - { - Name = item.GetName(), - MD5 = item.GetStringFieldValue(Models.Metadata.Disk.MD5Key), - SHA1 = item.GetStringFieldValue(Models.Metadata.Disk.SHA1Key), - Status = item.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue().AsStringValue(useSecond: false), - Writeable = item.GetBoolFieldValue(Models.Metadata.Disk.WritableKey)?.ToString(), - }; - return [disk]; - } - - /// - /// Create a DipSwitch array from the current DipSwitch DatItem - /// - private static Models.SoftwareList.DipSwitch[]? CreateDipSwitches(DipSwitch item) - { - var dipValues = new List(); - foreach (var setting in item.GetFieldValue(Models.Metadata.DipSwitch.DipValueKey) ?? []) - { - var dipValue = new Models.SoftwareList.DipValue - { - Name = setting.GetName(), - Value = setting.GetStringFieldValue(Models.Metadata.DipValue.ValueKey), - Default = setting.GetBoolFieldValue(Models.Metadata.DipValue.DefaultKey).FromYesNo(), - }; - - dipValues.Add(dipValue); - } - - var dipSwitch = new Models.SoftwareList.DipSwitch { DipValue = [.. dipValues] }; - return [dipSwitch]; - } - - /// - /// Sanitize Parts list to ensure no duplicates exist - /// - private static List SantitizeParts(List parts) - { - // If we have no parts, we can't do anything - if (!parts.Any()) - return parts; - - var grouped = parts.GroupBy(p => p.Name); - - var tempParts = new List(); - foreach (var grouping in grouped) - { - var tempPart = new Models.SoftwareList.Part(); - - var tempFeatures = new List(); - var tempDataAreas = new List(); - var tempDiskAreas = new List(); - var tempDipSwitches = new List(); - - foreach (var part in grouping) - { - tempPart.Name ??= part.Name; - tempPart.Interface ??= part.Interface; - - if (part.Feature != null) - tempFeatures.AddRange(part.Feature); - if (part.DataArea != null) - tempDataAreas.AddRange(part.DataArea); - if (part.DiskArea != null) - tempDiskAreas.AddRange(part.DiskArea); - if (part.DipSwitch != null) - tempDipSwitches.AddRange(part.DipSwitch); - } - - tempDataAreas = SantitizeDataAreas(tempDataAreas); - tempDiskAreas = SantitizeDiskAreas(tempDiskAreas); - - if (tempFeatures.Count > 0) - tempPart.Feature = [.. tempFeatures]; - if (tempDataAreas.Count > 0) - tempPart.DataArea = [.. tempDataAreas]; - if (tempDiskAreas.Count > 0) - tempPart.DiskArea = [.. tempDiskAreas]; - if (tempDipSwitches.Count > 0) - tempPart.DipSwitch = [.. tempDipSwitches]; - - tempParts.Add(tempPart); - } - - return tempParts; - } - - /// - /// Sanitize DataAreas list to ensure no duplicates exist - /// - private static List SantitizeDataAreas(List dataAreas) - { - // If we have no DataAreas, we can't do anything - if (!dataAreas.Any()) - return dataAreas; - - var grouped = dataAreas.GroupBy(p => p.Name); - - var tempDataAreas = new List(); - foreach (var grouping in grouped) - { - var tempDataArea = new Models.SoftwareList.DataArea(); - var tempRoms = new List(); - - foreach (var dataArea in grouping) - { - tempDataArea.Name ??= dataArea.Name; - tempDataArea.Size ??= dataArea.Size; - tempDataArea.Width ??= dataArea.Width; - tempDataArea.Endianness ??= dataArea.Endianness; - - if (dataArea.Rom != null) - tempRoms.AddRange(dataArea.Rom); - } - - if (tempRoms.Count > 0) - tempDataArea.Rom = [.. tempRoms]; - - tempDataAreas.Add(tempDataArea); - } - - return tempDataAreas; - } - - /// - /// Sanitize DiskArea list to ensure no duplicates exist - /// - private static List SantitizeDiskAreas(List diskAreas) - { - // If we have no DiskAreas, we can't do anything - if (!diskAreas.Any()) - return diskAreas; - - var grouped = diskAreas.GroupBy(p => p.Name); - - var tempDiskAreas = new List(); - foreach (var grouping in grouped) - { - var tempDiskArea = new Models.SoftwareList.DiskArea(); - var tempDisks = new List(); - - foreach (var dataArea in grouping) - { - tempDiskArea.Name ??= dataArea.Name; - if (dataArea.Disk != null) - tempDisks.AddRange(dataArea.Disk); - } - - if (tempDisks.Count > 0) - tempDiskArea.Disk = [.. tempDisks]; - - tempDiskAreas.Add(tempDiskArea); - } - - return tempDiskAreas; - } - - #endregion } }