[ALL] Add read/write support for MAME Listrom format

This commit is contained in:
Matt Nadareski
2017-06-06 00:41:16 -07:00
parent 945d5a24e0
commit 0e4fea9d20
8 changed files with 355 additions and 6 deletions

View File

@@ -106,6 +106,9 @@ namespace SabreTools.Library.Dats
case DatFormat.CSV:
ParseCSVTSV(filename, sysid, srcid, ',', keep, clean, remUnicode);
break;
case DatFormat.Listroms:
ParseListroms(filename, sysid, srcid, keep, clean, remUnicode);
break;
case DatFormat.Logiqx:
case DatFormat.OfflineList:
case DatFormat.SabreDat:
@@ -2342,6 +2345,197 @@ namespace SabreTools.Library.Dats
xtr.Dispose();
}
/// <summary>
/// Parse a MAME Listroms DAT and return all found games and roms within
/// </summary>
/// <param name="filename">Name of the file to be parsed</param>
/// <param name="sysid">System ID for the DAT</param>
/// <param name="srcid">Source ID for the DAT</param>
/// <param name="keep">True if full pathnames are to be kept, false otherwise (default)</param>
/// <param name="clean">True if game names are sanitized, false otherwise (default)</param>
/// <param name="remUnicode">True if we should remove non-ASCII characters from output, false otherwise (default)</param>
/// <remarks>
/// In a new style MAME listroms DAT, each game has the following format:
///
/// ROMs required for driver "005".
/// Name Size Checksum
/// 1346b.cpu-u25 2048 CRC(8e68533e) SHA1(a257c556d31691068ed5c991f1fb2b51da4826db)
/// 6331.sound-u8 32 BAD CRC(1d298cb0) SHA1(bb0bb62365402543e3154b9a77be9c75010e6abc) BAD_DUMP
///
/// </remarks>
private void ParseListroms(
// Standard Dat parsing
string filename,
int sysid,
int srcid,
// Miscellaneous
bool keep,
bool clean,
bool remUnicode)
{
// Open a file reader
Encoding enc = Style.GetEncoding(filename);
StreamReader sr = new StreamReader(FileTools.TryOpenRead(filename), enc);
string gamename = "";
while (!sr.EndOfStream)
{
string line = sr.ReadLine().Trim();
// If we have a blank line, we just skip it
if (String.IsNullOrEmpty(line))
{
continue;
}
// If we have the descriptor line, ignore it
else if (line == "Name Size Checksum")
{
continue;
}
// If we have the beginning of a game, set the name of the game
else if (line.StartsWith("ROMs required for driver"))
{
gamename = Regex.Match(line, @"^ROMs required for driver ""(.*?)""\.").Groups[1].Value;
}
// Otherwise, we assume we have a rom that we need to add
else
{
// First we separate the ROM into pieces
string[] split = line.Split(new char[0], StringSplitOptions.RemoveEmptyEntries);
// Standard Disks have 2 pieces (name, sha1)
if (split.Length == 2)
{
Disk disk = new Disk()
{
Name = split[0],
SHA1 = Style.CleanListromHashData(split[1]),
Machine = new Machine()
{
Name = gamename,
},
};
ParseAddHelper(disk, clean, remUnicode);
}
// Baddump Disks have 4 pieces (name, BAD, sha1, BAD_DUMP)
else if (split.Length == 4 && line.EndsWith("BAD_DUMP"))
{
Disk disk = new Disk()
{
Name = split[0],
SHA1 = Style.CleanListromHashData(split[2]),
ItemStatus = ItemStatus.BadDump,
Machine = new Machine()
{
Name = gamename,
},
};
ParseAddHelper(disk, clean, remUnicode);
}
// Standard ROMs have 4 pieces (name, size, crc, sha1)
else if (split.Length == 4)
{
if (!Int64.TryParse(split[1], out long size))
{
size = 0;
}
Rom rom = new Rom()
{
Name = split[0],
Size = size,
CRC = Style.CleanListromHashData(split[2]),
SHA1 = Style.CleanListromHashData(split[3]),
Machine = new Machine()
{
Name = gamename,
},
};
ParseAddHelper(rom, clean, remUnicode);
}
// Nodump Disks have 5 pieces (name, NO, GOOD, DUMP, KNOWN)
else if (split.Length == 5 && line.EndsWith("NO GOOD DUMP KNOWN"))
{
Disk disk = new Disk()
{
Name = split[0],
ItemStatus = ItemStatus.Nodump,
Machine = new Machine()
{
Name = gamename,
},
};
ParseAddHelper(disk, clean, remUnicode);
}
// Baddump ROMs have 6 pieces (name, size, BAD, crc, sha1, BAD_DUMP)
else if (split.Length == 6 && line.EndsWith("BAD_DUMP"))
{
if (!Int64.TryParse(split[1], out long size))
{
size = 0;
}
Rom rom = new Rom()
{
Name = split[0],
Size = size,
CRC = Style.CleanListromHashData(split[3]),
SHA1 = Style.CleanListromHashData(split[4]),
ItemStatus = ItemStatus.BadDump,
Machine = new Machine()
{
Name = gamename,
},
};
}
// Nodump ROMs have 6 pieces (name, size, NO, GOOD, DUMP, KNOWN)
else if (split.Length == 6 && line.EndsWith("NO GOOD DUMP KNOWN"))
{
if (!Int64.TryParse(split[1], out long size))
{
size = 0;
}
Rom rom = new Rom()
{
Name = split[0],
Size = size,
ItemStatus = ItemStatus.Nodump,
Machine = new Machine()
{
Name = gamename,
},
};
}
// If we have something else, it's invalid
else
{
Globals.Logger.Warning("Invalid line detected: '" + line + "'");
}
}
}
}
/// <summary>
/// Parse a Redump MD5 and return all found games and roms within
/// </summary>

View File

@@ -513,6 +513,10 @@ namespace SabreTools.Library.Dats
case DatFormat.DOSCenter:
state += "game (\n\tname \"" + rom.Machine.Name + ".zip\"\n";
break;
case DatFormat.Listroms:
state += "ROMs required for driver \"" + rom.Machine.Name + "\".\n" +
"Name Size Checksum\n";
break;
case DatFormat.Logiqx:
state += "\t<machine name=\"" + HttpUtility.HtmlEncode(rom.Machine.Name) + "\"" +
(ExcludeOf ? "" :
@@ -611,6 +615,9 @@ namespace SabreTools.Library.Dats
case DatFormat.DOSCenter:
state += (String.IsNullOrEmpty(rom.Machine.SampleOf) ? "" : "\tsampleof \"" + rom.Machine.SampleOf + "\"\n") + ")\n";
break;
case DatFormat.Listroms:
state += "\n";
break;
case DatFormat.Logiqx:
state += "\t</machine>\n";
break;
@@ -881,6 +888,96 @@ namespace SabreTools.Library.Dats
break;
}
break;
case DatFormat.Listroms:
switch (rom.Type)
{
case ItemType.Archive:
case ItemType.BiosSet:
case ItemType.Release:
case ItemType.Sample:
// We don't output these at all
break;
case ItemType.Disk:
// The name is padded out to a particular length
if (rom.Name.Length < 43)
{
state += rom.Name.PadRight(43, ' ');
}
else
{
state += rom.Name + " ";
}
// If we have a baddump, put the first indicator
if (((Disk)rom).ItemStatus == ItemStatus.BadDump)
{
state += " BAD";
}
// If we have a nodump, write out the indicator
if (((Disk)rom).ItemStatus == ItemStatus.Nodump)
{
state += " NO GOOD DUMP KNOWN";
}
// Otherwise, write out the SHA-1 hash
else
{
state += " SHA1(" + ((Disk)rom).SHA1 + ")";
}
// If we have a baddump, put the second indicator
if (((Disk)rom).ItemStatus == ItemStatus.BadDump)
{
state += " BAD_DUMP";
}
state += "\n";
break;
case ItemType.Rom:
// The name is padded out to a particular length
if (rom.Name.Length < 40)
{
state += rom.Name.PadRight(43 - (((Rom)rom).Size.ToString().Length), ' ');
}
else
{
state += rom.Name + " ";
}
// If we don't have a nodump, write out the size
if (((Rom)rom).ItemStatus != ItemStatus.Nodump)
{
state += ((Rom)rom).Size;
}
// If we have a baddump, put the first indicator
if (((Rom)rom).ItemStatus == ItemStatus.BadDump)
{
state += " BAD";
}
// If we have a nodump, write out the indicator
if (((Rom)rom).ItemStatus == ItemStatus.Nodump)
{
state += " NO GOOD DUMP KNOWN";
}
// Otherwise, write out the CRC and SHA-1 hashes
else
{
state += " CRC(" + ((Rom)rom).CRC + ")";
state += " SHA1(" + ((Rom)rom).SHA1 + ")";
}
// If we have a baddump, put the second indicator
if (((Rom)rom).ItemStatus == ItemStatus.BadDump)
{
state += " BAD_DUMP";
}
state += "\n";
break;
}
break;
case DatFormat.Logiqx:
switch (rom.Type)
{