Support WoD info CMP block type

This commit is contained in:
Matt Nadareski
2026-01-24 11:37:29 -05:00
parent 6bfe68b8cf
commit f16ed9742f
10 changed files with 161 additions and 2 deletions

View File

@@ -27,6 +27,7 @@ namespace SabreTools.Serialization.Test.CrossModel
Assert.NotNull(newMf.Game);
var newGame = Assert.Single(newMf.Game);
Validate(newGame);
Validate(newMf.Info);
}
[Fact]
@@ -51,6 +52,7 @@ namespace SabreTools.Serialization.Test.CrossModel
Assert.NotNull(newMf.Game);
var newGame = Assert.Single(newMf.Game);
Validate(newGame);
Validate(newMf.Info);
}
/// <summary>
@@ -229,10 +231,16 @@ namespace SabreTools.Serialization.Test.CrossModel
gameBase.DipSwitch = [dipswitch];
gameBase.Driver = driver;
var info = new Data.Models.ClrMamePro.Info
{
Source = ["XXXXXX"],
};
return new Data.Models.ClrMamePro.MetadataFile
{
ClrMamePro = cmp,
Game = [gameBase],
Info = info,
};
}
@@ -501,5 +509,16 @@ namespace SabreTools.Serialization.Test.CrossModel
Assert.Equal("XXXXXX", driver.PaletteSize);
Assert.Equal("XXXXXX", driver.Blit);
}
/// <summary>
/// Validate a ClrMamePro
/// </summary>
private static void Validate(Data.Models.ClrMamePro.Info? info)
{
Assert.NotNull(info);
Assert.NotNull(info.Source);
string source = Assert.Single(info.Source);
Assert.Equal("XXXXXX", source);
}
}
}

View File

@@ -93,6 +93,7 @@ namespace SabreTools.Serialization.Test.Readers
Assert.NotNull(newMf.Game);
var newGame = Assert.Single(newMf.Game);
Validate(newGame);
Validate(newMf.Info);
}
[Fact]
@@ -118,6 +119,7 @@ namespace SabreTools.Serialization.Test.Readers
Assert.NotNull(newMf.Game);
var newGame = Assert.Single(newMf.Game);
Validate(newGame);
Validate(newMf.Info);
}
[Fact]
@@ -346,10 +348,16 @@ namespace SabreTools.Serialization.Test.Readers
gameBase.DipSwitch = [dipswitch];
gameBase.Driver = driver;
var info = new Data.Models.ClrMamePro.Info
{
Source = ["XXXXXX"],
};
return new Data.Models.ClrMamePro.MetadataFile
{
ClrMamePro = cmp,
Game = [gameBase],
Info = info,
};
}
@@ -618,5 +626,16 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Equal("XXXXXX", driver.PaletteSize);
Assert.Equal("XXXXXX", driver.Blit);
}
/// <summary>
/// Validate a ClrMamePro
/// </summary>
private static void Validate(Data.Models.ClrMamePro.Info? info)
{
Assert.NotNull(info);
Assert.NotNull(info.Source);
string source = Assert.Single(info.Source);
Assert.Equal("XXXXXX", source);
}
}
}

View File

@@ -28,6 +28,10 @@ namespace SabreTools.Serialization.CrossModel
= Array.ConvertAll(machines, m => ConvertMachineFromInternalModel(m, game));
}
var info = obj.Read<Data.Models.Metadata.InfoSource>(Data.Models.Metadata.MetadataFile.InfoSourceKey);
if (info != null)
metadataFile.Info = ConvertInfoSourceFromInternalModel(info);
return metadataFile;
}
@@ -344,5 +348,19 @@ namespace SabreTools.Serialization.CrossModel
};
return video;
}
/// <summary>
/// Convert from <see cref="Models.Metadata.InfoSource"/> to <see cref="Models.ClrMamePro.Info"/>
/// </summary>
private static Info ConvertInfoSourceFromInternalModel(Data.Models.Metadata.InfoSource item)
{
var info = new Info();
var sources = item.Read<string[]>(Data.Models.Metadata.InfoSource.SourceKey);
if (sources != null && sources.Length > 0)
info.Source = [.. sources];
return info;
}
}
}

View File

@@ -22,6 +22,9 @@ namespace SabreTools.Serialization.CrossModel
= Array.ConvertAll(obj.Game, ConvertMachineToInternalModel);
}
if (obj?.Info != null)
metadataFile[Data.Models.Metadata.MetadataFile.InfoSourceKey] = ConvertInfoSourceToInternalModel(obj.Info);
return metadataFile;
}
@@ -359,5 +362,22 @@ namespace SabreTools.Serialization.CrossModel
};
return video;
}
/// <summary>
/// Convert from <see cref="Models.ClrMamePro.Info"/> to <see cref="Models.Metadata.InfoSource"/>
/// </summary>
private static Data.Models.Metadata.InfoSource ConvertInfoSourceToInternalModel(Info item)
{
var infoSource = new Data.Models.Metadata.InfoSource();
var sources = item.Source;
if (sources != null && sources.Length > 0)
{
string[] sourcesCopy = [.. sources];
infoSource[Data.Models.Metadata.InfoSource.SourceKey] = sourcesCopy;
}
return infoSource;
}
}
}

View File

@@ -0,0 +1,11 @@
namespace SabreTools.Data.Models.ClrMamePro
{
/// <summary>
/// Top-level item that contains a list of sources
/// </summary>
public class Info
{
/// <remarks>source</remarks>
public string[]? Source { get; set; }
}
}

View File

@@ -7,5 +7,8 @@ namespace SabreTools.Data.Models.ClrMamePro
/// <remarks>game, machine, resource, set</remarks>
public GameBase[]? Game { get; set; }
/// <remarks>info</remarks>
public Info? Info { get; set; }
}
}
}

View File

@@ -0,0 +1,16 @@
using System.Xml.Serialization;
using Newtonsoft.Json;
namespace SabreTools.Data.Models.Metadata
{
[JsonObject("infosource"), XmlRoot("infosource")]
public class InfoSource : DictionaryBase
{
#region Keys
/// <remarks>string[]</remarks>
public const string SourceKey = "source";
#endregion
}
}

View File

@@ -17,6 +17,10 @@ namespace SabreTools.Data.Models.Metadata
[NoFilter]
public const string HeaderKey = "header";
/// <remarks>InfoSource</remarks>
[NoFilter]
public const string InfoSourceKey = "infosource";
#endregion
}
}
}

View File

@@ -95,6 +95,7 @@ namespace SabreTools.Serialization.Readers
var chips = new List<Chip>();
var videos = new List<Video>();
var dipSwitches = new List<DipSwitch>();
var sources = new List<string>();
while (!reader.EndOfStream)
{
@@ -143,6 +144,11 @@ namespace SabreTools.Serialization.Readers
videos.Clear();
dipSwitches.Clear();
break;
case "info":
dat.Info?.Source = [.. sources];
sources.Clear();
break;
}
continue;
}
@@ -159,6 +165,9 @@ namespace SabreTools.Serialization.Readers
case "game":
game = new Game();
break;
case "info":
dat.Info = new Info();
break;
case "machine":
game = new Machine();
break;
@@ -281,6 +290,21 @@ namespace SabreTools.Serialization.Readers
}
}
// If we're in an info block
else if (reader.TopLevel == "info"
&& reader.RowType == CmpRowType.Standalone)
{
switch (reader.Standalone?.Key?.ToLowerInvariant())
{
case "source":
string? source = reader.Standalone?.Value;
if (source != null)
sources.Add(source);
break;
}
}
// If we're in an item block
else if ((reader.TopLevel == "game"
|| reader.TopLevel == "machine"

View File

@@ -76,6 +76,9 @@ namespace SabreTools.Serialization.Writers
// Write out the games, if they exist
WriteGames(obj.Game, writer);
// Write out the info, if it exists
WriteInfo(obj.Info, writer);
// Return the stream
stream.SeekIfPossible(0, SeekOrigin.Begin);
return stream;
@@ -493,6 +496,28 @@ namespace SabreTools.Serialization.Writers
writer.WriteEndElement(); // driver
}
/// <summary>
/// Write info information to the current writer
/// </summary>
/// <param name="info">ClrMamePro representing the info information</param>
/// <param name="writer">ClrMameProWriter representing the output</param>
private static void WriteInfo(Info? info, ClrMameProWriter writer)
{
// If the info information is missing, we can't do anything
if (info?.Source == null)
return;
writer.WriteStartElement("info");
foreach (var source in info.Source)
{
writer.WriteOptionalStandalone("source", source);
}
writer.WriteEndElement(); // info
writer.Flush();
}
#endregion
}
}