using System;
using System.Collections.Generic;
using SabreTools.Metadata.DatItems;
using SabreTools.Metadata.DatItems.Formats;
namespace SabreTools.Metadata.DatFiles.Formats
{
///
/// Represents a Logiqx-derived DAT
///
public sealed class Logiqx : SerializableDatFile
{
#region Constants
///
/// DTD for original Logiqx DATs
///
/// This has been edited to reflect actual current standards
internal const string LogiqxDTD = @"
";
///
/// XSD for No-Intro Logiqx-derived DATs
///
internal const string NoIntroXSD = @"
";
#endregion
#region Properties
///
public override Data.Models.Metadata.ItemType[] SupportedTypes
=> [
Data.Models.Metadata.ItemType.Archive,
Data.Models.Metadata.ItemType.BiosSet,
Data.Models.Metadata.ItemType.DeviceRef,
Data.Models.Metadata.ItemType.Disk,
Data.Models.Metadata.ItemType.Driver,
Data.Models.Metadata.ItemType.Media,
Data.Models.Metadata.ItemType.Release,
Data.Models.Metadata.ItemType.Rom,
Data.Models.Metadata.ItemType.Sample,
Data.Models.Metadata.ItemType.SoftwareList,
];
///
/// Indicates if game should be used instead of machine
///
private readonly bool _useGame;
#endregion
///
/// Constructor designed for casting a base DatFile
///
/// Parent DatFile to copy from
/// True if the output uses "game", false if the output uses "machine"
public Logiqx(DatFile? datFile, bool useGame) : base(datFile)
{
_useGame = useGame;
if (useGame)
Header.DatFormat = DatFormat.LogiqxDeprecated;
else
Header.DatFormat = DatFormat.Logiqx;
}
///
protected internal override List? GetMissingRequiredFields(DatItem datItem)
{
List missingFields = [];
switch (datItem)
{
case Release release:
if (string.IsNullOrEmpty(release.Name))
missingFields.Add(nameof(Data.Models.Metadata.Release.Name));
if (string.IsNullOrEmpty(release.Region))
missingFields.Add(nameof(Data.Models.Metadata.Release.Region));
break;
case BiosSet biosset:
if (string.IsNullOrEmpty(biosset.Name))
missingFields.Add(nameof(Data.Models.Metadata.BiosSet.Name));
if (string.IsNullOrEmpty(biosset.Description))
missingFields.Add(nameof(Data.Models.Metadata.BiosSet.Description));
break;
case Rom rom:
if (string.IsNullOrEmpty(rom.Name))
missingFields.Add(nameof(Data.Models.Metadata.Rom.Name));
if (rom.Size is null || rom.Size < 0)
missingFields.Add(nameof(Data.Models.Metadata.Rom.Size));
if (string.IsNullOrEmpty(rom.CRC16)
&& string.IsNullOrEmpty(rom.CRC32)
&& string.IsNullOrEmpty(rom.CRC64)
&& string.IsNullOrEmpty(rom.MD2)
&& string.IsNullOrEmpty(rom.MD4)
&& string.IsNullOrEmpty(rom.MD5)
&& string.IsNullOrEmpty(rom.RIPEMD128)
&& string.IsNullOrEmpty(rom.RIPEMD160)
&& string.IsNullOrEmpty(rom.SHA1)
&& string.IsNullOrEmpty(rom.SHA256)
&& string.IsNullOrEmpty(rom.SHA384)
&& string.IsNullOrEmpty(rom.SHA512)
&& string.IsNullOrEmpty(rom.SpamSum))
{
missingFields.Add(nameof(Data.Models.Metadata.Rom.SHA1));
}
break;
case Disk disk:
if (string.IsNullOrEmpty(disk.Name))
missingFields.Add(nameof(Data.Models.Metadata.Disk.Name));
if (string.IsNullOrEmpty(disk.MD5)
&& string.IsNullOrEmpty(disk.SHA1))
{
missingFields.Add(nameof(Data.Models.Metadata.Disk.SHA1));
}
break;
case Media media:
if (string.IsNullOrEmpty(media.Name))
missingFields.Add(nameof(Data.Models.Metadata.Media.Name));
if (string.IsNullOrEmpty(media.MD5)
&& string.IsNullOrEmpty(media.SHA1)
&& string.IsNullOrEmpty(media.SHA256)
&& string.IsNullOrEmpty(media.SpamSum))
{
missingFields.Add(nameof(Data.Models.Metadata.Media.SHA1));
}
break;
case DeviceRef deviceref:
if (string.IsNullOrEmpty(deviceref.Name))
missingFields.Add(nameof(Data.Models.Metadata.DeviceRef.Name));
break;
case Sample sample:
if (string.IsNullOrEmpty(sample.Name))
missingFields.Add(nameof(Data.Models.Metadata.Sample.Name));
break;
case Archive archive:
if (string.IsNullOrEmpty(archive.Name))
missingFields.Add(nameof(Data.Models.Metadata.Archive.Name));
break;
case Driver driver:
if (driver.Status is null)
missingFields.Add(nameof(Data.Models.Metadata.Driver.Status));
if (driver.Emulation is null)
missingFields.Add(nameof(Data.Models.Metadata.Driver.Emulation));
if (driver.Cocktail is null)
missingFields.Add(nameof(Data.Models.Metadata.Driver.Cocktail));
if (driver.SaveState is null)
missingFields.Add(nameof(Data.Models.Metadata.Driver.SaveState));
break;
case DatItems.Formats.SoftwareList softwarelist:
if (string.IsNullOrEmpty(softwarelist.Tag))
missingFields.Add(nameof(Data.Models.Metadata.SoftwareList.Tag));
if (string.IsNullOrEmpty(softwarelist.Name))
missingFields.Add(nameof(Data.Models.Metadata.SoftwareList.Name));
if (softwarelist.Status == null)
missingFields.Add(nameof(Data.Models.Metadata.SoftwareList.Status));
break;
default:
// Item type is not supported
break;
}
return missingFields;
}
///
public override bool WriteToFile(string outfile, bool ignoreblanks = false, bool throwOnError = false)
{
try
{
_logger.User($"Writing to '{outfile}'...");
// Serialize the input file
var metadata = ConvertToMetadata(ignoreblanks);
var datafile = new Serialization.CrossModel.Logiqx().Deserialize(metadata, _useGame);
// TODO: Enable No-Intro doctype writing instead of Logiqx
// Only write the doctype if we don't have No-Intro data
bool success;
if (string.IsNullOrEmpty(Header.Id))
success = new Serialization.Writers.Logiqx().SerializeFile(datafile, outfile);
else
success = new Serialization.Writers.Logiqx().SerializeFile(datafile, outfile);
if (!success)
{
_logger.Warning($"File '{outfile}' could not be written! See the log for more details.");
return false;
}
}
catch (Exception ex) when (!throwOnError)
{
_logger.Error(ex);
return false;
}
_logger.User($"'{outfile}' written!{Environment.NewLine}");
return true;
}
}
}