[DatFiles/] Whitespace and cleanup

This commit is contained in:
Matt Nadareski
2019-01-11 13:43:15 -08:00
parent 621ae2f230
commit 51e92c4472
14 changed files with 8457 additions and 8474 deletions

View File

@@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using SabreTools.Library.Data; using SabreTools.Library.Data;
using SabreTools.Library.DatItems; using SabreTools.Library.DatItems;
using SabreTools.Library.Tools; using SabreTools.Library.Tools;
@@ -19,248 +18,248 @@ using NaturalSort;
namespace SabreTools.Library.DatFiles namespace SabreTools.Library.DatFiles
{ {
/// <summary> /// <summary>
/// Represents parsing and writing of an AttractMode DAT /// Represents parsing and writing of an AttractMode DAT
/// </summary> /// </summary>
internal class AttractMode : DatFile internal class AttractMode : DatFile
{ {
/// <summary> /// <summary>
/// Constructor designed for casting a base DatFile /// Constructor designed for casting a base DatFile
/// </summary> /// </summary>
/// <param name="datFile">Parent DatFile to copy from</param> /// <param name="datFile">Parent DatFile to copy from</param>
public AttractMode(DatFile datFile) public AttractMode(DatFile datFile)
: base(datFile, cloneHeader: false) : base(datFile, cloneHeader: false)
{ {
} }
/// <summary> /// <summary>
/// Parse an AttractMode DAT and return all found games within /// Parse an AttractMode DAT and return all found games within
/// </summary> /// </summary>
/// <param name="filename">Name of the file to be parsed</param> /// <param name="filename">Name of the file to be parsed</param>
/// <param name="sysid">System ID for the DAT</param> /// <param name="sysid">System ID for the DAT</param>
/// <param name="srcid">Source 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="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="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> /// <param name="remUnicode">True if we should remove non-ASCII characters from output, false otherwise (default)</param>
public override void ParseFile( public override void ParseFile(
// Standard Dat parsing // Standard Dat parsing
string filename, string filename,
int sysid, int sysid,
int srcid, int srcid,
// Miscellaneous // Miscellaneous
bool keep, bool keep,
bool clean, bool clean,
bool remUnicode) bool remUnicode)
{ {
// Open a file reader // Open a file reader
Encoding enc = Utilities.GetEncoding(filename); Encoding enc = Utilities.GetEncoding(filename);
StreamReader sr = new StreamReader(Utilities.TryOpenRead(filename), enc); StreamReader sr = new StreamReader(Utilities.TryOpenRead(filename), enc);
sr.ReadLine(); // Skip the first line since it's the header sr.ReadLine(); // Skip the first line since it's the header
while (!sr.EndOfStream) while (!sr.EndOfStream)
{ {
string line = sr.ReadLine(); string line = sr.ReadLine();
/* /*
The gameinfo order is as follows The gameinfo order is as follows
0 - game name 0 - game name
1 - game description 1 - game description
2 - emulator name (filename) 2 - emulator name (filename)
3 - cloneof 3 - cloneof
4 - year 4 - year
5 - manufacturer 5 - manufacturer
6 - category 6 - category
7 - players 7 - players
8 - rotation 8 - rotation
9 - control 9 - control
10 - status 10 - status
11 - displaycount 11 - displaycount
12 - displaytype 12 - displaytype
13 - alt romname 13 - alt romname
14 - alt title 14 - alt title
15 - extra 15 - extra
16 - buttons 16 - buttons
*/ */
string[] gameinfo = line.Split(';'); string[] gameinfo = line.Split(';');
Rom rom = new Rom Rom rom = new Rom
{ {
Name = "-", Name = "-",
Size = Constants.SizeZero, Size = Constants.SizeZero,
CRC = Constants.CRCZero, CRC = Constants.CRCZero,
MD5 = Constants.MD5Zero, MD5 = Constants.MD5Zero,
SHA1 = Constants.SHA1Zero, SHA1 = Constants.SHA1Zero,
ItemStatus = ItemStatus.None, ItemStatus = ItemStatus.None,
MachineName = gameinfo[0], MachineName = gameinfo[0],
MachineDescription = gameinfo[1], MachineDescription = gameinfo[1],
CloneOf = gameinfo[3], CloneOf = gameinfo[3],
Year = gameinfo[4], Year = gameinfo[4],
Manufacturer = gameinfo[5], Manufacturer = gameinfo[5],
Comment = gameinfo[15], Comment = gameinfo[15],
}; };
// Now process and add the rom // Now process and add the rom
ParseAddHelper(rom, clean, remUnicode); ParseAddHelper(rom, clean, remUnicode);
} }
sr.Dispose(); sr.Dispose();
} }
/// <summary> /// <summary>
/// Create and open an output file for writing direct from a dictionary /// Create and open an output file for writing direct from a dictionary
/// </summary> /// </summary>
/// <param name="outfile">Name of the file to write to</param> /// <param name="outfile">Name of the file to write to</param>
/// <returns>True if the DAT was written correctly, false otherwise</returns> /// <returns>True if the DAT was written correctly, false otherwise</returns>
public bool WriteToFile(string outfile) public bool WriteToFile(string outfile)
{ {
try try
{ {
Globals.Logger.User("Opening file for writing: {0}", outfile); Globals.Logger.User("Opening file for writing: {0}", outfile);
FileStream fs = Utilities.TryCreate(outfile); FileStream fs = Utilities.TryCreate(outfile);
// If we get back null for some reason, just log and return // If we get back null for some reason, just log and return
if (fs == null) if (fs == null)
{ {
Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile); Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile);
return false; return false;
} }
StreamWriter sw = new StreamWriter(fs, new UTF8Encoding(false)); StreamWriter sw = new StreamWriter(fs, new UTF8Encoding(false));
// Write out the header // Write out the header
WriteHeader(sw); WriteHeader(sw);
// Write out each of the machines and roms // Write out each of the machines and roms
string lastgame = null; string lastgame = null;
// Get a properly sorted set of keys // Get a properly sorted set of keys
List<string> keys = Keys; List<string> keys = Keys;
keys.Sort(new NaturalComparer()); keys.Sort(new NaturalComparer());
foreach (string key in keys) foreach (string key in keys)
{ {
List<DatItem> roms = this[key]; List<DatItem> roms = this[key];
// Resolve the names in the block // Resolve the names in the block
roms = DatItem.ResolveNames(roms); roms = DatItem.ResolveNames(roms);
for (int index = 0; index < roms.Count; index++) for (int index = 0; index < roms.Count; index++)
{ {
DatItem item = roms[index]; DatItem item = roms[index];
// There are apparently times when a null rom can skip by, skip them // There are apparently times when a null rom can skip by, skip them
if (item.Name == null || item.MachineName == null) if (item.Name == null || item.MachineName == null)
{ {
Globals.Logger.Warning("Null rom found!"); Globals.Logger.Warning("Null rom found!");
continue; continue;
} }
// If we have a new game, output the beginning of the new item // If we have a new game, output the beginning of the new item
if (lastgame == null || lastgame.ToLowerInvariant() != item.MachineName.ToLowerInvariant()) if (lastgame == null || lastgame.ToLowerInvariant() != item.MachineName.ToLowerInvariant())
{ {
WriteStartGame(sw, item); WriteStartGame(sw, item);
} }
// If we have a "null" game (created by DATFromDir or something similar), log it to file // If we have a "null" game (created by DATFromDir or something similar), log it to file
if (item.ItemType == ItemType.Rom if (item.ItemType == ItemType.Rom
&& ((Rom)item).Size == -1 && ((Rom)item).Size == -1
&& ((Rom)item).CRC == "null") && ((Rom)item).CRC == "null")
{ {
Globals.Logger.Verbose("Empty folder found: {0}", item.MachineName); Globals.Logger.Verbose("Empty folder found: {0}", item.MachineName);
item.Name = (item.Name == "null" ? "-" : item.Name); item.Name = (item.Name == "null" ? "-" : item.Name);
((Rom)item).Size = Constants.SizeZero; ((Rom)item).Size = Constants.SizeZero;
} }
// Set the new data to compare against // Set the new data to compare against
lastgame = item.MachineName; lastgame = item.MachineName;
} }
} }
Globals.Logger.Verbose("File written!" + Environment.NewLine); Globals.Logger.Verbose("File written!" + Environment.NewLine);
sw.Dispose(); sw.Dispose();
fs.Dispose(); fs.Dispose();
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return false; return false;
} }
return true; return true;
} }
/// <summary> /// <summary>
/// Write out DAT header using the supplied StreamWriter /// Write out DAT header using the supplied StreamWriter
/// </summary> /// </summary>
/// <param name="sw">StreamWriter to output to</param> /// <param name="sw">StreamWriter to output to</param>
/// <returns>True if the data was written, false on error</returns> /// <returns>True if the data was written, false on error</returns>
private bool WriteHeader(StreamWriter sw) private bool WriteHeader(StreamWriter sw)
{ {
try try
{ {
string header = "#Title;Name;Emulator;CloneOf;Year;Manufacturer;Category;Players;Rotation;Control;Status;DisplayCount;DisplayType;AltRomname;AltTitle;Extra;Buttons\n"; string header = "#Title;Name;Emulator;CloneOf;Year;Manufacturer;Category;Players;Rotation;Control;Status;DisplayCount;DisplayType;AltRomname;AltTitle;Extra;Buttons\n";
// Write the header out // Write the header out
sw.Write(header); sw.Write(header);
sw.Flush(); sw.Flush();
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return false; return false;
} }
return true; return true;
} }
/// <summary> /// <summary>
/// Write out Game start using the supplied StreamWriter /// Write out Game start using the supplied StreamWriter
/// </summary> /// </summary>
/// <param name="sw">StreamWriter to output to</param> /// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param> /// <param name="rom">DatItem object to be output</param>
/// <returns>True if the data was written, false on error</returns> /// <returns>True if the data was written, false on error</returns>
private bool WriteStartGame(StreamWriter sw, DatItem rom) private bool WriteStartGame(StreamWriter sw, DatItem rom)
{ {
try try
{ {
// No game should start with a path separator // No game should start with a path separator
if (rom.MachineName.StartsWith(Path.DirectorySeparatorChar.ToString())) if (rom.MachineName.StartsWith(Path.DirectorySeparatorChar.ToString()))
{ {
rom.MachineName = rom.MachineName.Substring(1); rom.MachineName = rom.MachineName.Substring(1);
} }
string state = (!ExcludeFields[(int)Field.MachineName] ? rom.MachineName : "") + ";" string state = (!ExcludeFields[(int)Field.MachineName] ? rom.MachineName : "") + ";"
+ (!ExcludeFields[(int)Field.Description] ? rom.MachineDescription : "") + ";" + (!ExcludeFields[(int)Field.Description] ? rom.MachineDescription : "") + ";"
+ FileName + ";" + FileName + ";"
+ (!ExcludeFields[(int)Field.CloneOf] ? rom.CloneOf : "") + ";" + (!ExcludeFields[(int)Field.CloneOf] ? rom.CloneOf : "") + ";"
+ (!ExcludeFields[(int)Field.Year] ? rom.Year : "") + ";" + (!ExcludeFields[(int)Field.Year] ? rom.Year : "") + ";"
+ (!ExcludeFields[(int)Field.Manufacturer] ? rom.Manufacturer : "") + ";" + (!ExcludeFields[(int)Field.Manufacturer] ? rom.Manufacturer : "") + ";"
/* + rom.Category */ + ";" /* + rom.Category */ + ";"
/* + rom.Players */ + ";" /* + rom.Players */ + ";"
/* + rom.Rotation */ + ";" /* + rom.Rotation */ + ";"
/* + rom.Control */ + ";" /* + rom.Control */ + ";"
/* + rom.Status */ + ";" /* + rom.Status */ + ";"
/* + rom.DisplayCount */ + ";" /* + rom.DisplayCount */ + ";"
/* + rom.DisplayType */ + ";" /* + rom.DisplayType */ + ";"
/* + rom.AltRomname */ + ";" /* + rom.AltRomname */ + ";"
/* + rom.AltTitle */ + ";" /* + rom.AltTitle */ + ";"
+ (!ExcludeFields[(int)Field.Comment] ? rom.Comment : "") + ";" + (!ExcludeFields[(int)Field.Comment] ? rom.Comment : "") + ";"
/* + rom.Buttons */ + "\n"; /* + rom.Buttons */ + "\n";
sw.Write(state); sw.Write(state);
sw.Flush(); sw.Flush();
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return false; return false;
} }
return true; return true;
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using SabreTools.Library.Data; using SabreTools.Library.Data;
using SabreTools.Library.DatItems; using SabreTools.Library.DatItems;
using SabreTools.Library.Tools; using SabreTools.Library.Tools;
@@ -19,313 +18,313 @@ using NaturalSort;
namespace SabreTools.Library.DatFiles namespace SabreTools.Library.DatFiles
{ {
/// <summary> /// <summary>
/// Represents parsing and writing of a DosCenter DAT /// Represents parsing and writing of a DosCenter DAT
/// </summary> /// </summary>
internal class DosCenter : DatFile internal class DosCenter : DatFile
{ {
/// <summary> /// <summary>
/// Constructor designed for casting a base DatFile /// Constructor designed for casting a base DatFile
/// </summary> /// </summary>
/// <param name="datFile">Parent DatFile to copy from</param> /// <param name="datFile">Parent DatFile to copy from</param>
public DosCenter(DatFile datFile) public DosCenter(DatFile datFile)
: base(datFile, cloneHeader: false) : base(datFile, cloneHeader: false)
{ {
} }
/// <summary> /// <summary>
/// Parse a DosCenter DAT and return all found games and roms within /// Parse a DosCenter DAT and return all found games and roms within
/// </summary> /// </summary>
/// <param name="filename">Name of the file to be parsed</param> /// <param name="filename">Name of the file to be parsed</param>
/// <param name="sysid">System ID for the DAT</param> /// <param name="sysid">System ID for the DAT</param>
/// <param name="srcid">Source 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="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="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> /// <param name="remUnicode">True if we should remove non-ASCII characters from output, false otherwise (default)</param>
/// TODO: Pull parsing into this file instead of relying on CMP /// TODO: Pull parsing into this file instead of relying on CMP
public override void ParseFile( public override void ParseFile(
// Standard Dat parsing // Standard Dat parsing
string filename, string filename,
int sysid, int sysid,
int srcid, int srcid,
// Miscellaneous // Miscellaneous
bool keep, bool keep,
bool clean, bool clean,
bool remUnicode) bool remUnicode)
{ {
// ClrMamePro and DosCenter parsing are identical so it just calls one implementation // ClrMamePro and DosCenter parsing are identical so it just calls one implementation
new ClrMamePro(this).ParseFile(filename, sysid, srcid, keep, clean, remUnicode); new ClrMamePro(this).ParseFile(filename, sysid, srcid, keep, clean, remUnicode);
} }
/// <summary> /// <summary>
/// Create and open an output file for writing direct from a dictionary /// Create and open an output file for writing direct from a dictionary
/// </summary> /// </summary>
/// <param name="outfile">Name of the file to write to</param> /// <param name="outfile">Name of the file to write to</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param> /// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the DAT was written correctly, false otherwise</returns> /// <returns>True if the DAT was written correctly, false otherwise</returns>
public override bool WriteToFile(string outfile, bool ignoreblanks = false) public override bool WriteToFile(string outfile, bool ignoreblanks = false)
{ {
try try
{ {
Globals.Logger.User("Opening file for writing: {0}", outfile); Globals.Logger.User("Opening file for writing: {0}", outfile);
FileStream fs = Utilities.TryCreate(outfile); FileStream fs = Utilities.TryCreate(outfile);
// If we get back null for some reason, just log and return // If we get back null for some reason, just log and return
if (fs == null) if (fs == null)
{ {
Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile); Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile);
return false; return false;
} }
StreamWriter sw = new StreamWriter(fs, new UTF8Encoding(false)); StreamWriter sw = new StreamWriter(fs, new UTF8Encoding(false));
// Write out the header // Write out the header
WriteHeader(sw); WriteHeader(sw);
// Write out each of the machines and roms // Write out each of the machines and roms
string lastgame = null; string lastgame = null;
// Get a properly sorted set of keys // Get a properly sorted set of keys
List<string> keys = Keys; List<string> keys = Keys;
keys.Sort(new NaturalComparer()); keys.Sort(new NaturalComparer());
foreach (string key in keys) foreach (string key in keys)
{ {
List<DatItem> roms = this[key]; List<DatItem> roms = this[key];
// Resolve the names in the block // Resolve the names in the block
roms = DatItem.ResolveNames(roms); roms = DatItem.ResolveNames(roms);
for (int index = 0; index < roms.Count; index++) for (int index = 0; index < roms.Count; index++)
{ {
DatItem rom = roms[index]; DatItem rom = roms[index];
// There are apparently times when a null rom can skip by, skip them // There are apparently times when a null rom can skip by, skip them
if (rom.Name == null || rom.MachineName == null) if (rom.Name == null || rom.MachineName == null)
{ {
Globals.Logger.Warning("Null rom found!"); Globals.Logger.Warning("Null rom found!");
continue; continue;
} }
List<string> newsplit = rom.MachineName.Split('\\').ToList(); List<string> newsplit = rom.MachineName.Split('\\').ToList();
// If we have a different game and we're not at the start of the list, output the end of last item // If we have a different game and we're not at the start of the list, output the end of last item
if (lastgame != null && lastgame.ToLowerInvariant() != rom.MachineName.ToLowerInvariant()) if (lastgame != null && lastgame.ToLowerInvariant() != rom.MachineName.ToLowerInvariant())
{ {
WriteEndGame(sw, rom); WriteEndGame(sw, rom);
} }
// If we have a new game, output the beginning of the new item // If we have a new game, output the beginning of the new item
if (lastgame == null || lastgame.ToLowerInvariant() != rom.MachineName.ToLowerInvariant()) if (lastgame == null || lastgame.ToLowerInvariant() != rom.MachineName.ToLowerInvariant())
{ {
WriteStartGame(sw, rom); WriteStartGame(sw, rom);
} }
// If we have a "null" game (created by DATFromDir or something similar), log it to file // If we have a "null" game (created by DATFromDir or something similar), log it to file
if (rom.ItemType == ItemType.Rom if (rom.ItemType == ItemType.Rom
&& ((Rom)rom).Size == -1 && ((Rom)rom).Size == -1
&& ((Rom)rom).CRC == "null") && ((Rom)rom).CRC == "null")
{ {
Globals.Logger.Verbose("Empty folder found: {0}", rom.MachineName); Globals.Logger.Verbose("Empty folder found: {0}", rom.MachineName);
rom.Name = (rom.Name == "null" ? "-" : rom.Name); rom.Name = (rom.Name == "null" ? "-" : rom.Name);
((Rom)rom).Size = Constants.SizeZero; ((Rom)rom).Size = Constants.SizeZero;
((Rom)rom).CRC = ((Rom)rom).CRC == "null" ? Constants.CRCZero : null; ((Rom)rom).CRC = ((Rom)rom).CRC == "null" ? Constants.CRCZero : null;
((Rom)rom).MD5 = ((Rom)rom).MD5 == "null" ? Constants.MD5Zero : null; ((Rom)rom).MD5 = ((Rom)rom).MD5 == "null" ? Constants.MD5Zero : null;
((Rom)rom).SHA1 = ((Rom)rom).SHA1 == "null" ? Constants.SHA1Zero : null; ((Rom)rom).SHA1 = ((Rom)rom).SHA1 == "null" ? Constants.SHA1Zero : null;
((Rom)rom).SHA256 = ((Rom)rom).SHA256 == "null" ? Constants.SHA256Zero : null; ((Rom)rom).SHA256 = ((Rom)rom).SHA256 == "null" ? Constants.SHA256Zero : null;
((Rom)rom).SHA384 = ((Rom)rom).SHA384 == "null" ? Constants.SHA384Zero : null; ((Rom)rom).SHA384 = ((Rom)rom).SHA384 == "null" ? Constants.SHA384Zero : null;
((Rom)rom).SHA512 = ((Rom)rom).SHA512 == "null" ? Constants.SHA512Zero : null; ((Rom)rom).SHA512 = ((Rom)rom).SHA512 == "null" ? Constants.SHA512Zero : null;
} }
// Now, output the rom data // Now, output the rom data
WriteDatItem(sw, rom, ignoreblanks); WriteDatItem(sw, rom, ignoreblanks);
// Set the new data to compare against // Set the new data to compare against
lastgame = rom.MachineName; lastgame = rom.MachineName;
} }
} }
// Write the file footer out // Write the file footer out
WriteFooter(sw); WriteFooter(sw);
Globals.Logger.Verbose("File written!" + Environment.NewLine); Globals.Logger.Verbose("File written!" + Environment.NewLine);
sw.Dispose(); sw.Dispose();
fs.Dispose(); fs.Dispose();
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return false; return false;
} }
return true; return true;
} }
/// <summary> /// <summary>
/// Write out DAT header using the supplied StreamWriter /// Write out DAT header using the supplied StreamWriter
/// </summary> /// </summary>
/// <param name="sw">StreamWriter to output to</param> /// <param name="sw">StreamWriter to output to</param>
/// <returns>True if the data was written, false on error</returns> /// <returns>True if the data was written, false on error</returns>
private bool WriteHeader(StreamWriter sw) private bool WriteHeader(StreamWriter sw)
{ {
try try
{ {
string header = "DOSCenter (\n" + string header = "DOSCenter (\n" +
"\tName: " + Name + "\n" + "\tName: " + Name + "\n" +
"\tDescription: " + Description + "\n" + "\tDescription: " + Description + "\n" +
"\tVersion: " + Version + "\n" + "\tVersion: " + Version + "\n" +
"\tDate: " + Date + "\n" + "\tDate: " + Date + "\n" +
"\tAuthor: " + Author + "\n" + "\tAuthor: " + Author + "\n" +
"\tHomepage: " + Homepage + "\n" + "\tHomepage: " + Homepage + "\n" +
"\tComment: " + Comment + "\n" + "\tComment: " + Comment + "\n" +
")\n"; ")\n";
// Write the header out // Write the header out
sw.Write(header); sw.Write(header);
sw.Flush(); sw.Flush();
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return false; return false;
} }
return true; return true;
} }
/// <summary> /// <summary>
/// Write out Game start using the supplied StreamWriter /// Write out Game start using the supplied StreamWriter
/// </summary> /// </summary>
/// <param name="sw">StreamWriter to output to</param> /// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param> /// <param name="rom">DatItem object to be output</param>
/// <returns>True if the data was written, false on error</returns> /// <returns>True if the data was written, false on error</returns>
private bool WriteStartGame(StreamWriter sw, DatItem rom) private bool WriteStartGame(StreamWriter sw, DatItem rom)
{ {
try try
{ {
// No game should start with a path separator // No game should start with a path separator
if (rom.MachineName.StartsWith(Path.DirectorySeparatorChar.ToString())) if (rom.MachineName.StartsWith(Path.DirectorySeparatorChar.ToString()))
{ {
rom.MachineName = rom.MachineName.Substring(1); rom.MachineName = rom.MachineName.Substring(1);
} }
string state = "game (\n\tname \"" + (!ExcludeFields[(int)Field.MachineName] ? rom.MachineName + ".zip" : "") + "\"\n"; string state = "game (\n\tname \"" + (!ExcludeFields[(int)Field.MachineName] ? rom.MachineName + ".zip" : "") + "\"\n";
sw.Write(state); sw.Write(state);
sw.Flush(); sw.Flush();
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return false; return false;
} }
return true; return true;
} }
/// <summary> /// <summary>
/// Write out Game end using the supplied StreamWriter /// Write out Game end using the supplied StreamWriter
/// </summary> /// </summary>
/// <param name="sw">StreamWriter to output to</param> /// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param> /// <param name="rom">DatItem object to be output</param>
/// <returns>True if the data was written, false on error</returns> /// <returns>True if the data was written, false on error</returns>
private bool WriteEndGame(StreamWriter sw, DatItem rom) private bool WriteEndGame(StreamWriter sw, DatItem rom)
{ {
try try
{ {
string state = (!ExcludeFields[(int)Field.SampleOf] && String.IsNullOrWhiteSpace(rom.SampleOf) ? "" : "\tsampleof \"" + rom.SampleOf + "\"\n") + ")\n"; string state = (!ExcludeFields[(int)Field.SampleOf] && String.IsNullOrWhiteSpace(rom.SampleOf) ? "" : "\tsampleof \"" + rom.SampleOf + "\"\n") + ")\n";
sw.Write(state); sw.Write(state);
sw.Flush(); sw.Flush();
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return false; return false;
} }
return true; return true;
} }
/// <summary> /// <summary>
/// Write out DatItem using the supplied StreamWriter /// Write out DatItem using the supplied StreamWriter
/// </summary> /// </summary>
/// <param name="sw">StreamWriter to output to</param> /// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param> /// <param name="rom">DatItem object to be output</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param> /// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the data was written, false on error</returns> /// <returns>True if the data was written, false on error</returns>
private bool WriteDatItem(StreamWriter sw, DatItem rom, bool ignoreblanks = false) private bool WriteDatItem(StreamWriter sw, DatItem rom, bool ignoreblanks = false)
{ {
// If we are in ignore blanks mode AND we have a blank (0-size) rom, skip // If we are in ignore blanks mode AND we have a blank (0-size) rom, skip
if (ignoreblanks if (ignoreblanks
&& (rom.ItemType == ItemType.Rom && (rom.ItemType == ItemType.Rom
&& (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1))) && (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1)))
{ {
return true; return true;
} }
try try
{ {
string state = ""; string state = "";
// Pre-process the item name // Pre-process the item name
ProcessItemName(rom, true); ProcessItemName(rom, true);
switch (rom.ItemType) switch (rom.ItemType)
{ {
case ItemType.Archive: case ItemType.Archive:
case ItemType.BiosSet: case ItemType.BiosSet:
case ItemType.Disk: case ItemType.Disk:
case ItemType.Release: case ItemType.Release:
case ItemType.Sample: case ItemType.Sample:
// We don't output these at all for DosCenter // We don't output these at all for DosCenter
break; break;
case ItemType.Rom: case ItemType.Rom:
state += "\tfile ( name " + (!ExcludeFields[(int)Field.Name] ? ((Rom)rom).Name : "") state += "\tfile ( name " + (!ExcludeFields[(int)Field.Name] ? ((Rom)rom).Name : "")
+ (!ExcludeFields[(int)Field.Size] && ((Rom)rom).Size != -1 ? " size " + ((Rom)rom).Size : "") + (!ExcludeFields[(int)Field.Size] && ((Rom)rom).Size != -1 ? " size " + ((Rom)rom).Size : "")
+ (!ExcludeFields[(int)Field.Date] && !String.IsNullOrWhiteSpace(((Rom)rom).Date) ? " date " + ((Rom)rom).Date : "") + (!ExcludeFields[(int)Field.Date] && !String.IsNullOrWhiteSpace(((Rom)rom).Date) ? " date " + ((Rom)rom).Date : "")
+ (!ExcludeFields[(int)Field.CRC] && !String.IsNullOrWhiteSpace(((Rom)rom).CRC) ? " crc " + ((Rom)rom).CRC.ToLowerInvariant() : "") + (!ExcludeFields[(int)Field.CRC] && !String.IsNullOrWhiteSpace(((Rom)rom).CRC) ? " crc " + ((Rom)rom).CRC.ToLowerInvariant() : "")
+ " )\n"; + " )\n";
break; break;
} }
sw.Write(state); sw.Write(state);
sw.Flush(); sw.Flush();
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return false; return false;
} }
return true; return true;
} }
/// <summary> /// <summary>
/// Write out DAT footer using the supplied StreamWriter /// Write out DAT footer using the supplied StreamWriter
/// </summary> /// </summary>
/// <param name="sw">StreamWriter to output to</param> /// <param name="sw">StreamWriter to output to</param>
/// <returns>True if the data was written, false on error</returns> /// <returns>True if the data was written, false on error</returns>
private bool WriteFooter(StreamWriter sw) private bool WriteFooter(StreamWriter sw)
{ {
try try
{ {
string footer = ")\n"; string footer = ")\n";
// Write the footer out // Write the footer out
sw.Write(footer); sw.Write(footer);
sw.Flush(); sw.Flush();
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return false; return false;
} }
return true; return true;
} }
} }
} }

View File

@@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using SabreTools.Library.Data; using SabreTools.Library.Data;
using SabreTools.Library.DatItems; using SabreTools.Library.DatItems;
using SabreTools.Library.Tools; using SabreTools.Library.Tools;
@@ -19,282 +18,282 @@ using NaturalSort;
namespace SabreTools.Library.DatFiles namespace SabreTools.Library.DatFiles
{ {
/// <summary> /// <summary>
/// Represents parsing and writing of a hashfile such as an SFV, MD5, or SHA-1 file /// Represents parsing and writing of a hashfile such as an SFV, MD5, or SHA-1 file
/// </summary> /// </summary>
internal class Hashfile : DatFile internal class Hashfile : DatFile
{ {
// Private instance variables specific to Hashfile DATs // Private instance variables specific to Hashfile DATs
Hash _hash; Hash _hash;
/// <summary> /// <summary>
/// Constructor designed for casting a base DatFile /// Constructor designed for casting a base DatFile
/// </summary> /// </summary>
/// <param name="datFile">Parent DatFile to copy from</param> /// <param name="datFile">Parent DatFile to copy from</param>
/// <param name="hash">Type of hash that is associated with this DAT</param> /// <param name="hash">Type of hash that is associated with this DAT</param>
public Hashfile(DatFile datFile, Hash hash) public Hashfile(DatFile datFile, Hash hash)
: base(datFile, cloneHeader: false) : base(datFile, cloneHeader: false)
{ {
_hash = hash; _hash = hash;
} }
/// <summary> /// <summary>
/// Parse a hashfile or SFV and return all found games and roms within /// Parse a hashfile or SFV and return all found games and roms within
/// </summary> /// </summary>
/// <param name="filename">Name of the file to be parsed</param> /// <param name="filename">Name of the file to be parsed</param>
/// <param name="sysid">System ID for the DAT</param> /// <param name="sysid">System ID for the DAT</param>
/// <param name="srcid">Source 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="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="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> /// <param name="remUnicode">True if we should remove non-ASCII characters from output, false otherwise (default)</param>
public override void ParseFile( public override void ParseFile(
// Standard Dat parsing // Standard Dat parsing
string filename, string filename,
int sysid, int sysid,
int srcid, int srcid,
// Miscellaneous // Miscellaneous
bool keep, bool keep,
bool clean, bool clean,
bool remUnicode) bool remUnicode)
{ {
// Open a file reader // Open a file reader
Encoding enc = Utilities.GetEncoding(filename); Encoding enc = Utilities.GetEncoding(filename);
StreamReader sr = new StreamReader(Utilities.TryOpenRead(filename), enc); StreamReader sr = new StreamReader(Utilities.TryOpenRead(filename), enc);
while (!sr.EndOfStream) while (!sr.EndOfStream)
{ {
string line = sr.ReadLine(); string line = sr.ReadLine();
// Split the line and get the name and hash // Split the line and get the name and hash
string[] split = line.Split(' '); string[] split = line.Split(' ');
string name = ""; string name = "";
string hash = ""; string hash = "";
// If we have CRC, then it's an SFV file and the name is first are // If we have CRC, then it's an SFV file and the name is first are
if ((_hash & Hash.CRC) != 0) if ((_hash & Hash.CRC) != 0)
{ {
name = split[0].Replace("*", String.Empty); name = split[0].Replace("*", String.Empty);
hash = split[1]; hash = split[1];
} }
// Otherwise, the name is second // Otherwise, the name is second
else else
{ {
name = split[1].Replace("*", String.Empty); name = split[1].Replace("*", String.Empty);
hash = split[0]; hash = split[0];
} }
Rom rom = new Rom Rom rom = new Rom
{ {
Name = name, Name = name,
Size = -1, Size = -1,
CRC = ((_hash & Hash.CRC) != 0 ? Utilities.CleanHashData(hash, Constants.CRCLength) : null), CRC = ((_hash & Hash.CRC) != 0 ? Utilities.CleanHashData(hash, Constants.CRCLength) : null),
MD5 = ((_hash & Hash.MD5) != 0 ? Utilities.CleanHashData(hash, Constants.MD5Length) : null), MD5 = ((_hash & Hash.MD5) != 0 ? Utilities.CleanHashData(hash, Constants.MD5Length) : null),
SHA1 = ((_hash & Hash.SHA1) != 0 ? Utilities.CleanHashData(hash, Constants.SHA1Length) : null), SHA1 = ((_hash & Hash.SHA1) != 0 ? Utilities.CleanHashData(hash, Constants.SHA1Length) : null),
SHA256 = ((_hash & Hash.SHA256) != 0 ? Utilities.CleanHashData(hash, Constants.SHA256Length) : null), SHA256 = ((_hash & Hash.SHA256) != 0 ? Utilities.CleanHashData(hash, Constants.SHA256Length) : null),
SHA384 = ((_hash & Hash.SHA384) != 0 ? Utilities.CleanHashData(hash, Constants.SHA384Length) : null), SHA384 = ((_hash & Hash.SHA384) != 0 ? Utilities.CleanHashData(hash, Constants.SHA384Length) : null),
SHA512 = ((_hash & Hash.SHA512) != 0 ? Utilities.CleanHashData(hash, Constants.SHA512Length) : null), SHA512 = ((_hash & Hash.SHA512) != 0 ? Utilities.CleanHashData(hash, Constants.SHA512Length) : null),
ItemStatus = ItemStatus.None, ItemStatus = ItemStatus.None,
MachineName = Path.GetFileNameWithoutExtension(filename), MachineName = Path.GetFileNameWithoutExtension(filename),
SystemID = sysid, SystemID = sysid,
SourceID = srcid, SourceID = srcid,
}; };
// Now process and add the rom // Now process and add the rom
ParseAddHelper(rom, clean, remUnicode); ParseAddHelper(rom, clean, remUnicode);
} }
sr.Dispose(); sr.Dispose();
} }
/// <summary> /// <summary>
/// Create and open an output file for writing direct from a dictionary /// Create and open an output file for writing direct from a dictionary
/// </summary> /// </summary>
/// <param name="outfile">Name of the file to write to</param> /// <param name="outfile">Name of the file to write to</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param> /// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the DAT was written correctly, false otherwise</returns> /// <returns>True if the DAT was written correctly, false otherwise</returns>
public override bool WriteToFile(string outfile, bool ignoreblanks = false) public override bool WriteToFile(string outfile, bool ignoreblanks = false)
{ {
try try
{ {
Globals.Logger.User("Opening file for writing: {0}", outfile); Globals.Logger.User("Opening file for writing: {0}", outfile);
FileStream fs = Utilities.TryCreate(outfile); FileStream fs = Utilities.TryCreate(outfile);
// If we get back null for some reason, just log and return // If we get back null for some reason, just log and return
if (fs == null) if (fs == null)
{ {
Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile); Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile);
return false; return false;
} }
StreamWriter sw = new StreamWriter(fs, new UTF8Encoding(false)); StreamWriter sw = new StreamWriter(fs, new UTF8Encoding(false));
// Get a properly sorted set of keys // Get a properly sorted set of keys
List<string> keys = Keys; List<string> keys = Keys;
keys.Sort(new NaturalComparer()); keys.Sort(new NaturalComparer());
foreach (string key in keys) foreach (string key in keys)
{ {
List<DatItem> roms = this[key]; List<DatItem> roms = this[key];
// Resolve the names in the block // Resolve the names in the block
roms = DatItem.ResolveNames(roms); roms = DatItem.ResolveNames(roms);
for (int index = 0; index < roms.Count; index++) for (int index = 0; index < roms.Count; index++)
{ {
DatItem rom = roms[index]; DatItem rom = roms[index];
// There are apparently times when a null rom can skip by, skip them // There are apparently times when a null rom can skip by, skip them
if (rom.Name == null || rom.MachineName == null) if (rom.Name == null || rom.MachineName == null)
{ {
Globals.Logger.Warning("Null rom found!"); Globals.Logger.Warning("Null rom found!");
continue; continue;
} }
// If we have a "null" game (created by DATFromDir or something similar), log it to file // If we have a "null" game (created by DATFromDir or something similar), log it to file
if (rom.ItemType == ItemType.Rom if (rom.ItemType == ItemType.Rom
&& ((Rom)rom).Size == -1 && ((Rom)rom).Size == -1
&& ((Rom)rom).CRC == "null") && ((Rom)rom).CRC == "null")
{ {
Globals.Logger.Verbose("Empty folder found: {0}", rom.MachineName); Globals.Logger.Verbose("Empty folder found: {0}", rom.MachineName);
} }
// Now, output the rom data // Now, output the rom data
WriteDatItem(sw, rom, ignoreblanks); WriteDatItem(sw, rom, ignoreblanks);
} }
} }
Globals.Logger.Verbose("File written!" + Environment.NewLine); Globals.Logger.Verbose("File written!" + Environment.NewLine);
sw.Dispose(); sw.Dispose();
fs.Dispose(); fs.Dispose();
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return false; return false;
} }
return true; return true;
} }
/// <summary> /// <summary>
/// Write out DatItem using the supplied StreamWriter /// Write out DatItem using the supplied StreamWriter
/// </summary> /// </summary>
/// <param name="sw">StreamWriter to output to</param> /// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param> /// <param name="rom">DatItem object to be output</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param> /// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the data was written, false on error</returns> /// <returns>True if the data was written, false on error</returns>
private bool WriteDatItem(StreamWriter sw, DatItem rom, bool ignoreblanks = false) private bool WriteDatItem(StreamWriter sw, DatItem rom, bool ignoreblanks = false)
{ {
// If we are in ignore blanks mode AND we have a blank (0-size) rom, skip // If we are in ignore blanks mode AND we have a blank (0-size) rom, skip
if (ignoreblanks if (ignoreblanks
&& (rom.ItemType == ItemType.Rom && (rom.ItemType == ItemType.Rom
&& (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1))) && (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1)))
{ {
return true; return true;
} }
try try
{ {
string state = ""; string state = "";
// Pre-process the item name // Pre-process the item name
ProcessItemName(rom, true); ProcessItemName(rom, true);
switch (_hash) switch (_hash)
{ {
case Hash.MD5: case Hash.MD5:
if (rom.ItemType == ItemType.Rom) if (rom.ItemType == ItemType.Rom)
{ {
state += (!ExcludeFields[(int)Field.MD5] ? ((Rom)rom).MD5 : "") state += (!ExcludeFields[(int)Field.MD5] ? ((Rom)rom).MD5 : "")
+ " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "") + " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "")
+ (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n"; + (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
} }
else if (rom.ItemType == ItemType.Disk) else if (rom.ItemType == ItemType.Disk)
{ {
state += (!ExcludeFields[(int)Field.MD5] ? ((Disk)rom).MD5 : "") state += (!ExcludeFields[(int)Field.MD5] ? ((Disk)rom).MD5 : "")
+ " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "") + " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "")
+ (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n"; + (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
} }
break; break;
case Hash.CRC: case Hash.CRC:
if (rom.ItemType == ItemType.Rom) if (rom.ItemType == ItemType.Rom)
{ {
state += (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "") state += (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "")
+ (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + (!ExcludeFields[(int)Field.Name] ? rom.Name : "")
+ " " + (!ExcludeFields[(int)Field.CRC] ? ((Rom)rom).CRC : "") + "\n"; + " " + (!ExcludeFields[(int)Field.CRC] ? ((Rom)rom).CRC : "") + "\n";
} }
break; break;
case Hash.SHA1: case Hash.SHA1:
if (rom.ItemType == ItemType.Rom) if (rom.ItemType == ItemType.Rom)
{ {
state += (!ExcludeFields[(int)Field.SHA1] ? ((Rom)rom).SHA1 : "") state += (!ExcludeFields[(int)Field.SHA1] ? ((Rom)rom).SHA1 : "")
+ " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "") + " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "")
+ (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n"; + (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
} }
else if (rom.ItemType == ItemType.Disk) else if (rom.ItemType == ItemType.Disk)
{ {
state += (!ExcludeFields[(int)Field.SHA1] ? ((Disk)rom).SHA1 : "") state += (!ExcludeFields[(int)Field.SHA1] ? ((Disk)rom).SHA1 : "")
+ " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "") + " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "")
+ (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n"; + (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
} }
break; break;
case Hash.SHA256: case Hash.SHA256:
if (rom.ItemType == ItemType.Rom) if (rom.ItemType == ItemType.Rom)
{ {
state += (!ExcludeFields[(int)Field.SHA256] ? ((Rom)rom).SHA256 : "") state += (!ExcludeFields[(int)Field.SHA256] ? ((Rom)rom).SHA256 : "")
+ " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "") + " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "")
+ (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n"; + (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
} }
else if (rom.ItemType == ItemType.Disk) else if (rom.ItemType == ItemType.Disk)
{ {
state += (!ExcludeFields[(int)Field.SHA256] ? ((Disk)rom).SHA256 : "") state += (!ExcludeFields[(int)Field.SHA256] ? ((Disk)rom).SHA256 : "")
+ " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "") + " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "")
+ (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n"; + (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
} }
break; break;
case Hash.SHA384: case Hash.SHA384:
if (rom.ItemType == ItemType.Rom) if (rom.ItemType == ItemType.Rom)
{ {
state += (!ExcludeFields[(int)Field.SHA384] ? ((Rom)rom).SHA384 : "") state += (!ExcludeFields[(int)Field.SHA384] ? ((Rom)rom).SHA384 : "")
+ " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "") + " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "")
+ (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n"; + (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
} }
else if (rom.ItemType == ItemType.Disk) else if (rom.ItemType == ItemType.Disk)
{ {
state += (!ExcludeFields[(int)Field.SHA384] ? ((Disk)rom).SHA384 : "") state += (!ExcludeFields[(int)Field.SHA384] ? ((Disk)rom).SHA384 : "")
+ " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "") + " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "")
+ (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n"; + (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
} }
break; break;
case Hash.SHA512: case Hash.SHA512:
if (rom.ItemType == ItemType.Rom) if (rom.ItemType == ItemType.Rom)
{ {
state += (!ExcludeFields[(int)Field.SHA512] ? ((Rom)rom).SHA512 : "") state += (!ExcludeFields[(int)Field.SHA512] ? ((Rom)rom).SHA512 : "")
+ " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "") + " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "")
+ (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n"; + (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
} }
else if (rom.ItemType == ItemType.Disk) else if (rom.ItemType == ItemType.Disk)
{ {
state += (!ExcludeFields[(int)Field.SHA512] ? ((Disk)rom).SHA512 : "") state += (!ExcludeFields[(int)Field.SHA512] ? ((Disk)rom).SHA512 : "")
+ " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "") + " *" + (!ExcludeFields[(int)Field.MachineName] && GameName ? rom.MachineName + Path.DirectorySeparatorChar : "")
+ (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n"; + (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
} }
break; break;
} }
sw.Write(state); sw.Write(state);
sw.Flush(); sw.Flush();
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return false; return false;
} }
return true; return true;
} }
} }
} }

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using SabreTools.Library.Data; using SabreTools.Library.Data;
using SabreTools.Library.DatItems; using SabreTools.Library.DatItems;
using SabreTools.Library.Tools; using SabreTools.Library.Tools;
@@ -20,497 +19,497 @@ using NaturalSort;
namespace SabreTools.Library.DatFiles namespace SabreTools.Library.DatFiles
{ {
/// <summary> /// <summary>
/// Represents parsing and writing of a MAME Listrom DAT /// Represents parsing and writing of a MAME Listrom DAT
/// </summary> /// </summary>
internal class Listrom : DatFile internal class Listrom : DatFile
{ {
/// <summary> /// <summary>
/// Constructor designed for casting a base DatFile /// Constructor designed for casting a base DatFile
/// </summary> /// </summary>
/// <param name="datFile">Parent DatFile to copy from</param> /// <param name="datFile">Parent DatFile to copy from</param>
public Listrom(DatFile datFile) public Listrom(DatFile datFile)
: base(datFile, cloneHeader: false) : base(datFile, cloneHeader: false)
{ {
} }
/// <summary> /// <summary>
/// Parse a MAME Listrom DAT and return all found games and roms within /// Parse a MAME Listrom DAT and return all found games and roms within
/// </summary> /// </summary>
/// <param name="filename">Name of the file to be parsed</param> /// <param name="filename">Name of the file to be parsed</param>
/// <param name="sysid">System ID for the DAT</param> /// <param name="sysid">System ID for the DAT</param>
/// <param name="srcid">Source 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="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="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> /// <param name="remUnicode">True if we should remove non-ASCII characters from output, false otherwise (default)</param>
/// <remarks> /// <remarks>
/// In a new style MAME listrom DAT, each game has the following format: /// In a new style MAME listrom DAT, each game has the following format:
/// ///
/// ROMs required for driver "005". /// ROMs required for driver "005".
/// Name Size Checksum /// Name Size Checksum
/// 1346b.cpu-u25 2048 CRC(8e68533e) SHA1(a257c556d31691068ed5c991f1fb2b51da4826db) /// 1346b.cpu-u25 2048 CRC(8e68533e) SHA1(a257c556d31691068ed5c991f1fb2b51da4826db)
/// 6331.sound-u8 32 BAD CRC(1d298cb0) SHA1(bb0bb62365402543e3154b9a77be9c75010e6abc) BAD_DUMP /// 6331.sound-u8 32 BAD CRC(1d298cb0) SHA1(bb0bb62365402543e3154b9a77be9c75010e6abc) BAD_DUMP
/// 16v8h-blue.u24 279 NO GOOD DUMP KNOWN /// 16v8h-blue.u24 279 NO GOOD DUMP KNOWN
/// </remarks> /// </remarks>
public override void ParseFile( public override void ParseFile(
// Standard Dat parsing // Standard Dat parsing
string filename, string filename,
int sysid, int sysid,
int srcid, int srcid,
// Miscellaneous // Miscellaneous
bool keep, bool keep,
bool clean, bool clean,
bool remUnicode) bool remUnicode)
{ {
// Open a file reader // Open a file reader
Encoding enc = Utilities.GetEncoding(filename); Encoding enc = Utilities.GetEncoding(filename);
StreamReader sr = new StreamReader(Utilities.TryOpenRead(filename), enc); StreamReader sr = new StreamReader(Utilities.TryOpenRead(filename), enc);
string gamename = ""; string gamename = "";
while (!sr.EndOfStream) while (!sr.EndOfStream)
{ {
string line = sr.ReadLine().Trim(); string line = sr.ReadLine().Trim();
// If we have a blank line, we just skip it // If we have a blank line, we just skip it
if (String.IsNullOrWhiteSpace(line)) if (String.IsNullOrWhiteSpace(line))
{ {
continue; continue;
} }
// If we have the descriptor line, ignore it // If we have the descriptor line, ignore it
else if (line == "Name Size Checksum") else if (line == "Name Size Checksum")
{ {
continue; continue;
} }
// If we have the beginning of a game, set the name of the game // If we have the beginning of a game, set the name of the game
else if (line.StartsWith("ROMs required for")) else if (line.StartsWith("ROMs required for"))
{ {
gamename = Regex.Match(line, @"^ROMs required for \S*? ""(.*?)""\.").Groups[1].Value; gamename = Regex.Match(line, @"^ROMs required for \S*? ""(.*?)""\.").Groups[1].Value;
} }
// If we have a machine with no required roms (usually internal devices), skip it // If we have a machine with no required roms (usually internal devices), skip it
else if (line.StartsWith("No ROMs required for")) else if (line.StartsWith("No ROMs required for"))
{ {
continue; continue;
} }
// Otherwise, we assume we have a rom that we need to add // Otherwise, we assume we have a rom that we need to add
else else
{ {
// First, we preprocess the line so that the rom name is consistently correct // First, we preprocess the line so that the rom name is consistently correct
string romname = ""; string romname = "";
string[] split = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); string[] split = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
// If the line doesn't have the 4 spaces of padding, check for 3 // If the line doesn't have the 4 spaces of padding, check for 3
if (split.Length == 1) if (split.Length == 1)
{ {
split = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); split = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
} }
// If the split is still unsuccessful, log it and skip // If the split is still unsuccessful, log it and skip
if (split.Length == 1) if (split.Length == 1)
{ {
Globals.Logger.Warning("Possibly malformed line: '{0}'", line); Globals.Logger.Warning("Possibly malformed line: '{0}'", line);
} }
romname = split[0]; romname = split[0];
line = line.Substring(romname.Length); line = line.Substring(romname.Length);
// Next we separate the ROM into pieces // Next we separate the ROM into pieces
split = line.Split(new char[0], StringSplitOptions.RemoveEmptyEntries); split = line.Split(new char[0], StringSplitOptions.RemoveEmptyEntries);
// Standard Disks have 2 pieces (name, sha1) // Standard Disks have 2 pieces (name, sha1)
if (split.Length == 1) if (split.Length == 1)
{ {
Disk disk = new Disk() Disk disk = new Disk()
{ {
Name = romname, Name = romname,
SHA1 = Utilities.CleanListromHashData(split[0]), SHA1 = Utilities.CleanListromHashData(split[0]),
MachineName = gamename, MachineName = gamename,
}; };
ParseAddHelper(disk, clean, remUnicode); ParseAddHelper(disk, clean, remUnicode);
} }
// Baddump Disks have 4 pieces (name, BAD, sha1, BAD_DUMP) // Baddump Disks have 4 pieces (name, BAD, sha1, BAD_DUMP)
else if (split.Length == 3 && line.EndsWith("BAD_DUMP")) else if (split.Length == 3 && line.EndsWith("BAD_DUMP"))
{ {
Disk disk = new Disk() Disk disk = new Disk()
{ {
Name = romname, Name = romname,
SHA1 = Utilities.CleanListromHashData(split[1]), SHA1 = Utilities.CleanListromHashData(split[1]),
ItemStatus = ItemStatus.BadDump, ItemStatus = ItemStatus.BadDump,
MachineName = gamename, MachineName = gamename,
}; };
ParseAddHelper(disk, clean, remUnicode); ParseAddHelper(disk, clean, remUnicode);
} }
// Standard ROMs have 4 pieces (name, size, crc, sha1) // Standard ROMs have 4 pieces (name, size, crc, sha1)
else if (split.Length == 3) else if (split.Length == 3)
{ {
if (!Int64.TryParse(split[0], out long size)) if (!Int64.TryParse(split[0], out long size))
{ {
size = 0; size = 0;
} }
Rom rom = new Rom() Rom rom = new Rom()
{ {
Name = romname, Name = romname,
Size = size, Size = size,
CRC = Utilities.CleanListromHashData(split[1]), CRC = Utilities.CleanListromHashData(split[1]),
SHA1 = Utilities.CleanListromHashData(split[2]), SHA1 = Utilities.CleanListromHashData(split[2]),
MachineName = gamename, MachineName = gamename,
}; };
ParseAddHelper(rom, clean, remUnicode); ParseAddHelper(rom, clean, remUnicode);
} }
// Nodump Disks have 5 pieces (name, NO, GOOD, DUMP, KNOWN) // Nodump Disks have 5 pieces (name, NO, GOOD, DUMP, KNOWN)
else if (split.Length == 4 && line.EndsWith("NO GOOD DUMP KNOWN")) else if (split.Length == 4 && line.EndsWith("NO GOOD DUMP KNOWN"))
{ {
Disk disk = new Disk() Disk disk = new Disk()
{ {
Name = romname, Name = romname,
ItemStatus = ItemStatus.Nodump, ItemStatus = ItemStatus.Nodump,
MachineName = gamename, MachineName = gamename,
}; };
ParseAddHelper(disk, clean, remUnicode); ParseAddHelper(disk, clean, remUnicode);
} }
// Baddump ROMs have 6 pieces (name, size, BAD, crc, sha1, BAD_DUMP) // Baddump ROMs have 6 pieces (name, size, BAD, crc, sha1, BAD_DUMP)
else if (split.Length == 5 && line.EndsWith("BAD_DUMP")) else if (split.Length == 5 && line.EndsWith("BAD_DUMP"))
{ {
if (!Int64.TryParse(split[0], out long size)) if (!Int64.TryParse(split[0], out long size))
{ {
size = 0; size = 0;
} }
Rom rom = new Rom() Rom rom = new Rom()
{ {
Name = romname, Name = romname,
Size = size, Size = size,
CRC = Utilities.CleanListromHashData(split[2]), CRC = Utilities.CleanListromHashData(split[2]),
SHA1 = Utilities.CleanListromHashData(split[3]), SHA1 = Utilities.CleanListromHashData(split[3]),
ItemStatus = ItemStatus.BadDump, ItemStatus = ItemStatus.BadDump,
MachineName = gamename, MachineName = gamename,
}; };
ParseAddHelper(rom, clean, remUnicode); ParseAddHelper(rom, clean, remUnicode);
} }
// Nodump ROMs have 6 pieces (name, size, NO, GOOD, DUMP, KNOWN) // Nodump ROMs have 6 pieces (name, size, NO, GOOD, DUMP, KNOWN)
else if (split.Length == 5 && line.EndsWith("NO GOOD DUMP KNOWN")) else if (split.Length == 5 && line.EndsWith("NO GOOD DUMP KNOWN"))
{ {
if (!Int64.TryParse(split[0], out long size)) if (!Int64.TryParse(split[0], out long size))
{ {
size = 0; size = 0;
} }
Rom rom = new Rom() Rom rom = new Rom()
{ {
Name = romname, Name = romname,
Size = size, Size = size,
ItemStatus = ItemStatus.Nodump, ItemStatus = ItemStatus.Nodump,
MachineName = gamename, MachineName = gamename,
}; };
ParseAddHelper(rom, clean, remUnicode); ParseAddHelper(rom, clean, remUnicode);
} }
// If we have something else, it's invalid // If we have something else, it's invalid
else else
{ {
Globals.Logger.Warning("Invalid line detected: '{0} {1}'", romname, line); Globals.Logger.Warning("Invalid line detected: '{0} {1}'", romname, line);
} }
} }
} }
} }
/// <summary> /// <summary>
/// Create and open an output file for writing direct from a dictionary /// Create and open an output file for writing direct from a dictionary
/// </summary> /// </summary>
/// <param name="outfile">Name of the file to write to</param> /// <param name="outfile">Name of the file to write to</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param> /// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the DAT was written correctly, false otherwise</returns> /// <returns>True if the DAT was written correctly, false otherwise</returns>
public override bool WriteToFile(string outfile, bool ignoreblanks = false) public override bool WriteToFile(string outfile, bool ignoreblanks = false)
{ {
try try
{ {
Globals.Logger.User("Opening file for writing: {0}", outfile); Globals.Logger.User("Opening file for writing: {0}", outfile);
FileStream fs = Utilities.TryCreate(outfile); FileStream fs = Utilities.TryCreate(outfile);
// If we get back null for some reason, just log and return // If we get back null for some reason, just log and return
if (fs == null) if (fs == null)
{ {
Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile); Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile);
return false; return false;
} }
StreamWriter sw = new StreamWriter(fs, new UTF8Encoding(false)); StreamWriter sw = new StreamWriter(fs, new UTF8Encoding(false));
// Write out each of the machines and roms // Write out each of the machines and roms
string lastgame = null; string lastgame = null;
// Get a properly sorted set of keys // Get a properly sorted set of keys
List<string> keys = Keys; List<string> keys = Keys;
keys.Sort(new NaturalComparer()); keys.Sort(new NaturalComparer());
foreach (string key in keys) foreach (string key in keys)
{ {
List<DatItem> roms = this[key]; List<DatItem> roms = this[key];
// Resolve the names in the block // Resolve the names in the block
roms = DatItem.ResolveNames(roms); roms = DatItem.ResolveNames(roms);
for (int index = 0; index < roms.Count; index++) for (int index = 0; index < roms.Count; index++)
{ {
DatItem rom = roms[index]; DatItem rom = roms[index];
// There are apparently times when a null rom can skip by, skip them // There are apparently times when a null rom can skip by, skip them
if (rom.Name == null || rom.MachineName == null) if (rom.Name == null || rom.MachineName == null)
{ {
Globals.Logger.Warning("Null rom found!"); Globals.Logger.Warning("Null rom found!");
continue; continue;
} }
// If we have a different game and we're not at the start of the list, output the end of last item // If we have a different game and we're not at the start of the list, output the end of last item
if (lastgame != null && lastgame.ToLowerInvariant() != rom.MachineName.ToLowerInvariant()) if (lastgame != null && lastgame.ToLowerInvariant() != rom.MachineName.ToLowerInvariant())
{ {
WriteEndGame(sw); WriteEndGame(sw);
} }
// If we have a new game, output the beginning of the new item // If we have a new game, output the beginning of the new item
if (lastgame == null || lastgame.ToLowerInvariant() != rom.MachineName.ToLowerInvariant()) if (lastgame == null || lastgame.ToLowerInvariant() != rom.MachineName.ToLowerInvariant())
{ {
WriteStartGame(sw, rom); WriteStartGame(sw, rom);
} }
// If we have a "null" game (created by DATFromDir or something similar), log it to file // If we have a "null" game (created by DATFromDir or something similar), log it to file
if (rom.ItemType == ItemType.Rom if (rom.ItemType == ItemType.Rom
&& ((Rom)rom).Size == -1 && ((Rom)rom).Size == -1
&& ((Rom)rom).CRC == "null") && ((Rom)rom).CRC == "null")
{ {
Globals.Logger.Verbose("Empty folder found: {0}", rom.MachineName); Globals.Logger.Verbose("Empty folder found: {0}", rom.MachineName);
rom.Name = (rom.Name == "null" ? "-" : rom.Name); rom.Name = (rom.Name == "null" ? "-" : rom.Name);
((Rom)rom).Size = Constants.SizeZero; ((Rom)rom).Size = Constants.SizeZero;
((Rom)rom).CRC = ((Rom)rom).CRC == "null" ? Constants.CRCZero : null; ((Rom)rom).CRC = ((Rom)rom).CRC == "null" ? Constants.CRCZero : null;
((Rom)rom).MD5 = ((Rom)rom).MD5 == "null" ? Constants.MD5Zero : null; ((Rom)rom).MD5 = ((Rom)rom).MD5 == "null" ? Constants.MD5Zero : null;
((Rom)rom).SHA1 = ((Rom)rom).SHA1 == "null" ? Constants.SHA1Zero : null; ((Rom)rom).SHA1 = ((Rom)rom).SHA1 == "null" ? Constants.SHA1Zero : null;
((Rom)rom).SHA256 = ((Rom)rom).SHA256 == "null" ? Constants.SHA256Zero : null; ((Rom)rom).SHA256 = ((Rom)rom).SHA256 == "null" ? Constants.SHA256Zero : null;
((Rom)rom).SHA384 = ((Rom)rom).SHA384 == "null" ? Constants.SHA384Zero : null; ((Rom)rom).SHA384 = ((Rom)rom).SHA384 == "null" ? Constants.SHA384Zero : null;
((Rom)rom).SHA512 = ((Rom)rom).SHA512 == "null" ? Constants.SHA512Zero : null; ((Rom)rom).SHA512 = ((Rom)rom).SHA512 == "null" ? Constants.SHA512Zero : null;
} }
// Now, output the rom data // Now, output the rom data
WriteDatItem(sw, rom, ignoreblanks); WriteDatItem(sw, rom, ignoreblanks);
// Set the new data to compare against // Set the new data to compare against
lastgame = rom.MachineName; lastgame = rom.MachineName;
} }
} }
Globals.Logger.Verbose("File written!" + Environment.NewLine); Globals.Logger.Verbose("File written!" + Environment.NewLine);
sw.Dispose(); sw.Dispose();
fs.Dispose(); fs.Dispose();
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return false; return false;
} }
return true; return true;
} }
/// <summary> /// <summary>
/// Write out Game start using the supplied StreamWriter /// Write out Game start using the supplied StreamWriter
/// </summary> /// </summary>
/// <param name="sw">StreamWriter to output to</param> /// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param> /// <param name="rom">DatItem object to be output</param>
/// <returns>True if the data was written, false on error</returns> /// <returns>True if the data was written, false on error</returns>
private bool WriteStartGame(StreamWriter sw, DatItem rom) private bool WriteStartGame(StreamWriter sw, DatItem rom)
{ {
try try
{ {
// No game should start with a path separator // No game should start with a path separator
if (rom.MachineName.StartsWith(Path.DirectorySeparatorChar.ToString())) if (rom.MachineName.StartsWith(Path.DirectorySeparatorChar.ToString()))
{ {
rom.MachineName = rom.MachineName.Substring(1); rom.MachineName = rom.MachineName.Substring(1);
} }
string state = "ROMs required for driver \"" + (!ExcludeFields[(int)Field.MachineName] ? rom.MachineName : "") + "\".\n" + string state = "ROMs required for driver \"" + (!ExcludeFields[(int)Field.MachineName] ? rom.MachineName : "") + "\".\n" +
"Name Size Checksum\n"; "Name Size Checksum\n";
sw.Write(state); sw.Write(state);
sw.Flush(); sw.Flush();
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return false; return false;
} }
return true; return true;
} }
/// <summary> /// <summary>
/// Write out Game end using the supplied StreamWriter /// Write out Game end using the supplied StreamWriter
/// </summary> /// </summary>
/// <param name="sw">StreamWriter to output to</param> /// <param name="sw">StreamWriter to output to</param>
/// <returns>True if the data was written, false on error</returns> /// <returns>True if the data was written, false on error</returns>
private bool WriteEndGame(StreamWriter sw) private bool WriteEndGame(StreamWriter sw)
{ {
try try
{ {
string state = "\n"; string state = "\n";
sw.Write(state); sw.Write(state);
sw.Flush(); sw.Flush();
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return false; return false;
} }
return true; return true;
} }
/// <summary> /// <summary>
/// Write out DatItem using the supplied StreamWriter /// Write out DatItem using the supplied StreamWriter
/// </summary> /// </summary>
/// <param name="sw">StreamWriter to output to</param> /// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param> /// <param name="rom">DatItem object to be output</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param> /// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the data was written, false on error</returns> /// <returns>True if the data was written, false on error</returns>
private bool WriteDatItem(StreamWriter sw, DatItem rom, bool ignoreblanks = false) private bool WriteDatItem(StreamWriter sw, DatItem rom, bool ignoreblanks = false)
{ {
// If we are in ignore blanks mode AND we have a blank (0-size) rom, skip // If we are in ignore blanks mode AND we have a blank (0-size) rom, skip
if (ignoreblanks if (ignoreblanks
&& (rom.ItemType == ItemType.Rom && (rom.ItemType == ItemType.Rom
&& (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1))) && (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1)))
{ {
return true; return true;
} }
try try
{ {
string state = ""; string state = "";
// Pre-process the item name // Pre-process the item name
ProcessItemName(rom, true); ProcessItemName(rom, true);
switch (rom.ItemType) switch (rom.ItemType)
{ {
case ItemType.Archive: case ItemType.Archive:
case ItemType.BiosSet: case ItemType.BiosSet:
case ItemType.Release: case ItemType.Release:
case ItemType.Sample: case ItemType.Sample:
// We don't output these at all // We don't output these at all
break; break;
case ItemType.Disk: case ItemType.Disk:
// The name is padded out to a particular length // The name is padded out to a particular length
if (rom.Name.Length < 43) if (rom.Name.Length < 43)
{ {
state += rom.Name.PadRight(43, ' '); state += rom.Name.PadRight(43, ' ');
} }
else else
{ {
state += rom.Name + " "; state += rom.Name + " ";
} }
// If we have a baddump, put the first indicator // If we have a baddump, put the first indicator
if (!ExcludeFields[(int)Field.Status] && ((Disk)rom).ItemStatus == ItemStatus.BadDump) if (!ExcludeFields[(int)Field.Status] && ((Disk)rom).ItemStatus == ItemStatus.BadDump)
{ {
state += " BAD"; state += " BAD";
} }
// If we have a nodump, write out the indicator // If we have a nodump, write out the indicator
if (!ExcludeFields[(int)Field.Status] && ((Disk)rom).ItemStatus == ItemStatus.Nodump) if (!ExcludeFields[(int)Field.Status] && ((Disk)rom).ItemStatus == ItemStatus.Nodump)
{ {
state += " NO GOOD DUMP KNOWN"; state += " NO GOOD DUMP KNOWN";
} }
// Otherwise, write out the SHA-1 hash // Otherwise, write out the SHA-1 hash
else if (!ExcludeFields[(int)Field.SHA1]) else if (!ExcludeFields[(int)Field.SHA1])
{ {
state += " SHA1(" + ((Disk)rom).SHA1 + ")"; state += " SHA1(" + ((Disk)rom).SHA1 + ")";
} }
// If we have a baddump, put the second indicator // If we have a baddump, put the second indicator
if (!ExcludeFields[(int)Field.Status] && ((Disk)rom).ItemStatus == ItemStatus.BadDump) if (!ExcludeFields[(int)Field.Status] && ((Disk)rom).ItemStatus == ItemStatus.BadDump)
{ {
state += " BAD_DUMP"; state += " BAD_DUMP";
} }
state += "\n"; state += "\n";
break; break;
case ItemType.Rom: case ItemType.Rom:
// The name is padded out to a particular length // The name is padded out to a particular length
if (rom.Name.Length < 40) if (rom.Name.Length < 40)
{ {
state += rom.Name.PadRight(43 - (((Rom)rom).Size.ToString().Length), ' '); state += rom.Name.PadRight(43 - (((Rom)rom).Size.ToString().Length), ' ');
} }
else else
{ {
state += rom.Name + " "; state += rom.Name + " ";
} }
// If we don't have a nodump, write out the size // If we don't have a nodump, write out the size
if (((Rom)rom).ItemStatus != ItemStatus.Nodump) if (((Rom)rom).ItemStatus != ItemStatus.Nodump)
{ {
state += ((Rom)rom).Size; state += ((Rom)rom).Size;
} }
// If we have a baddump, put the first indicator // If we have a baddump, put the first indicator
if (!ExcludeFields[(int)Field.Status] && ((Rom)rom).ItemStatus == ItemStatus.BadDump) if (!ExcludeFields[(int)Field.Status] && ((Rom)rom).ItemStatus == ItemStatus.BadDump)
{ {
state += " BAD"; state += " BAD";
} }
// If we have a nodump, write out the indicator // If we have a nodump, write out the indicator
if (!ExcludeFields[(int)Field.Status] && ((Rom)rom).ItemStatus == ItemStatus.Nodump) if (!ExcludeFields[(int)Field.Status] && ((Rom)rom).ItemStatus == ItemStatus.Nodump)
{ {
state += " NO GOOD DUMP KNOWN"; state += " NO GOOD DUMP KNOWN";
} }
// Otherwise, write out the CRC and SHA-1 hashes // Otherwise, write out the CRC and SHA-1 hashes
else else
{ {
state += (!ExcludeFields[(int)Field.CRC] ? " CRC(" + ((Rom)rom).CRC + ")" : ""); state += (!ExcludeFields[(int)Field.CRC] ? " CRC(" + ((Rom)rom).CRC + ")" : "");
state += (!ExcludeFields[(int)Field.SHA1] ? " SHA1(" + ((Rom)rom).SHA1 + ")" : ""); state += (!ExcludeFields[(int)Field.SHA1] ? " SHA1(" + ((Rom)rom).SHA1 + ")" : "");
} }
// If we have a baddump, put the second indicator // If we have a baddump, put the second indicator
if (!ExcludeFields[(int)Field.Status] && ((Rom)rom).ItemStatus == ItemStatus.BadDump) if (!ExcludeFields[(int)Field.Status] && ((Rom)rom).ItemStatus == ItemStatus.BadDump)
{ {
state += " BAD_DUMP"; state += " BAD_DUMP";
} }
state += "\n"; state += "\n";
break; break;
} }
sw.Write(state); sw.Write(state);
sw.Flush(); sw.Flush();
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return false; return false;
} }
return true; return true;
} }
} }
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using SabreTools.Library.Data; using SabreTools.Library.Data;
using SabreTools.Library.DatItems; using SabreTools.Library.DatItems;
using SabreTools.Library.Tools; using SabreTools.Library.Tools;
@@ -18,176 +17,176 @@ using NaturalSort;
namespace SabreTools.Library.DatFiles namespace SabreTools.Library.DatFiles
{ {
/// <summary> /// <summary>
/// Represents parsing and writing of a Missfile /// Represents parsing and writing of a Missfile
/// </summary> /// </summary>
internal class Missfile : DatFile internal class Missfile : DatFile
{ {
/// <summary> /// <summary>
/// Constructor designed for casting a base DatFile /// Constructor designed for casting a base DatFile
/// </summary> /// </summary>
/// <param name="datFile">Parent DatFile to copy from</param> /// <param name="datFile">Parent DatFile to copy from</param>
public Missfile(DatFile datFile) public Missfile(DatFile datFile)
: base(datFile, cloneHeader: false) : base(datFile, cloneHeader: false)
{ {
} }
/// <summary> /// <summary>
/// Parse a Missfile and return all found games and roms within /// Parse a Missfile and return all found games and roms within
/// </summary> /// </summary>
/// <param name="filename">Name of the file to be parsed</param> /// <param name="filename">Name of the file to be parsed</param>
/// <param name="sysid">System ID for the DAT</param> /// <param name="sysid">System ID for the DAT</param>
/// <param name="srcid">Source 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="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="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> /// <param name="remUnicode">True if we should remove non-ASCII characters from output, false otherwise (default)</param>
public override void ParseFile( public override void ParseFile(
// Standard Dat parsing // Standard Dat parsing
string filename, string filename,
int sysid, int sysid,
int srcid, int srcid,
// Miscellaneous // Miscellaneous
bool keep, bool keep,
bool clean, bool clean,
bool remUnicode) bool remUnicode)
{ {
// There is no consistent way to parse a missfile... // There is no consistent way to parse a missfile...
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary> /// <summary>
/// Create and open an output file for writing direct from a dictionary /// Create and open an output file for writing direct from a dictionary
/// </summary> /// </summary>
/// <param name="outfile">Name of the file to write to</param> /// <param name="outfile">Name of the file to write to</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param> /// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the DAT was written correctly, false otherwise</returns> /// <returns>True if the DAT was written correctly, false otherwise</returns>
public override bool WriteToFile(string outfile, bool ignoreblanks = false) public override bool WriteToFile(string outfile, bool ignoreblanks = false)
{ {
try try
{ {
Globals.Logger.User("Opening file for writing: {0}", outfile); Globals.Logger.User("Opening file for writing: {0}", outfile);
FileStream fs = Utilities.TryCreate(outfile); FileStream fs = Utilities.TryCreate(outfile);
// If we get back null for some reason, just log and return // If we get back null for some reason, just log and return
if (fs == null) if (fs == null)
{ {
Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile); Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile);
return false; return false;
} }
StreamWriter sw = new StreamWriter(fs, new UTF8Encoding(false)); StreamWriter sw = new StreamWriter(fs, new UTF8Encoding(false));
// Write out each of the machines and roms // Write out each of the machines and roms
string lastgame = null; string lastgame = null;
// Get a properly sorted set of keys // Get a properly sorted set of keys
List<string> keys = Keys; List<string> keys = Keys;
keys.Sort(new NaturalComparer()); keys.Sort(new NaturalComparer());
foreach (string key in keys) foreach (string key in keys)
{ {
List<DatItem> roms = this[key]; List<DatItem> roms = this[key];
// Resolve the names in the block // Resolve the names in the block
roms = DatItem.ResolveNames(roms); roms = DatItem.ResolveNames(roms);
for (int index = 0; index < roms.Count; index++) for (int index = 0; index < roms.Count; index++)
{ {
DatItem rom = roms[index]; DatItem rom = roms[index];
// There are apparently times when a null rom can skip by, skip them // There are apparently times when a null rom can skip by, skip them
if (rom.Name == null || rom.MachineName == null) if (rom.Name == null || rom.MachineName == null)
{ {
Globals.Logger.Warning("Null rom found!"); Globals.Logger.Warning("Null rom found!");
continue; continue;
} }
// If we have a "null" game (created by DATFromDir or something similar), log it to file // If we have a "null" game (created by DATFromDir or something similar), log it to file
if (rom.ItemType == ItemType.Rom if (rom.ItemType == ItemType.Rom
&& ((Rom)rom).Size == -1 && ((Rom)rom).Size == -1
&& ((Rom)rom).CRC == "null") && ((Rom)rom).CRC == "null")
{ {
Globals.Logger.Verbose("Empty folder found: {0}", rom.MachineName); Globals.Logger.Verbose("Empty folder found: {0}", rom.MachineName);
lastgame = rom.MachineName; lastgame = rom.MachineName;
continue; continue;
} }
// Now, output the rom data // Now, output the rom data
WriteDatItem(sw, rom, lastgame, ignoreblanks); WriteDatItem(sw, rom, lastgame, ignoreblanks);
// Set the new data to compare against // Set the new data to compare against
lastgame = rom.MachineName; lastgame = rom.MachineName;
} }
} }
Globals.Logger.Verbose("File written!" + Environment.NewLine); Globals.Logger.Verbose("File written!" + Environment.NewLine);
sw.Dispose(); sw.Dispose();
fs.Dispose(); fs.Dispose();
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return false; return false;
} }
return true; return true;
} }
/// <summary> /// <summary>
/// Write out DatItem using the supplied StreamWriter /// Write out DatItem using the supplied StreamWriter
/// </summary> /// </summary>
/// <param name="sw">StreamWriter to output to</param> /// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param> /// <param name="rom">DatItem object to be output</param>
/// <param name="lastgame">The name of the last game to be output</param> /// <param name="lastgame">The name of the last game to be output</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param> /// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the data was written, false on error</returns> /// <returns>True if the data was written, false on error</returns>
private bool WriteDatItem(StreamWriter sw, DatItem rom, string lastgame, bool ignoreblanks = false) private bool WriteDatItem(StreamWriter sw, DatItem rom, string lastgame, bool ignoreblanks = false)
{ {
// If we are in ignore blanks mode AND we have a blank (0-size) rom, skip // If we are in ignore blanks mode AND we have a blank (0-size) rom, skip
if (ignoreblanks if (ignoreblanks
&& (rom.ItemType == ItemType.Rom && (rom.ItemType == ItemType.Rom
&& (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1))) && (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1)))
{ {
return true; return true;
} }
try try
{ {
string state = ""; string state = "";
// Process the item name // Process the item name
ProcessItemName(rom, false, forceRomName: false); ProcessItemName(rom, false, forceRomName: false);
// If we're in Romba mode, the state is consistent // If we're in Romba mode, the state is consistent
if (Romba) if (Romba)
{ {
state += (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n"; state += (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
} }
// Otherwise, use any flags // Otherwise, use any flags
else else
{ {
if (!UseRomName && rom.MachineName != lastgame) if (!UseRomName && rom.MachineName != lastgame)
{ {
state += (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n"; state += (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
lastgame = rom.MachineName; lastgame = rom.MachineName;
} }
else if (UseRomName) else if (UseRomName)
{ {
state += (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n"; state += (!ExcludeFields[(int)Field.Name] ? rom.Name : "") + "\n";
} }
} }
sw.Write(state); sw.Write(state);
sw.Flush(); sw.Flush();
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return false; return false;
} }
return true; return true;
} }
} }
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using System.Web; using System.Web;
using SabreTools.Library.Data; using SabreTools.Library.Data;
using SabreTools.Library.DatItems; using SabreTools.Library.DatItems;
using SabreTools.Library.Tools; using SabreTools.Library.Tools;
@@ -20,359 +19,359 @@ using NaturalSort;
namespace SabreTools.Library.DatFiles namespace SabreTools.Library.DatFiles
{ {
/// <summary> /// <summary>
/// Represents parsing and writing of a RomCenter DAT /// Represents parsing and writing of a RomCenter DAT
/// </summary> /// </summary>
internal class RomCenter : DatFile internal class RomCenter : DatFile
{ {
/// <summary> /// <summary>
/// Constructor designed for casting a base DatFile /// Constructor designed for casting a base DatFile
/// </summary> /// </summary>
/// <param name="datFile">Parent DatFile to copy from</param> /// <param name="datFile">Parent DatFile to copy from</param>
public RomCenter(DatFile datFile) public RomCenter(DatFile datFile)
: base(datFile, cloneHeader: false) : base(datFile, cloneHeader: false)
{ {
} }
/// <summary> /// <summary>
/// Parse a RomCenter DAT and return all found games and roms within /// Parse a RomCenter DAT and return all found games and roms within
/// </summary> /// </summary>
/// <param name="filename">Name of the file to be parsed</param> /// <param name="filename">Name of the file to be parsed</param>
/// <param name="sysid">System ID for the DAT</param> /// <param name="sysid">System ID for the DAT</param>
/// <param name="srcid">Source 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="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="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> /// <param name="remUnicode">True if we should remove non-ASCII characters from output, false otherwise (default)</param>
public override void ParseFile( public override void ParseFile(
// Standard Dat parsing // Standard Dat parsing
string filename, string filename,
int sysid, int sysid,
int srcid, int srcid,
// Miscellaneous // Miscellaneous
bool keep, bool keep,
bool clean, bool clean,
bool remUnicode) bool remUnicode)
{ {
// Open a file reader // Open a file reader
Encoding enc = Utilities.GetEncoding(filename); Encoding enc = Utilities.GetEncoding(filename);
StreamReader sr = new StreamReader(Utilities.TryOpenRead(filename), enc); StreamReader sr = new StreamReader(Utilities.TryOpenRead(filename), enc);
string blocktype = ""; string blocktype = "";
while (!sr.EndOfStream) while (!sr.EndOfStream)
{ {
string line = sr.ReadLine(); string line = sr.ReadLine();
// If the line is the start of the credits section // If the line is the start of the credits section
if (line.ToLowerInvariant().StartsWith("[credits]")) if (line.ToLowerInvariant().StartsWith("[credits]"))
{ {
blocktype = "credits"; blocktype = "credits";
} }
// If the line is the start of the dat section // If the line is the start of the dat section
else if (line.ToLowerInvariant().StartsWith("[dat]")) else if (line.ToLowerInvariant().StartsWith("[dat]"))
{ {
blocktype = "dat"; blocktype = "dat";
} }
// If the line is the start of the emulator section // If the line is the start of the emulator section
else if (line.ToLowerInvariant().StartsWith("[emulator]")) else if (line.ToLowerInvariant().StartsWith("[emulator]"))
{ {
blocktype = "emulator"; blocktype = "emulator";
} }
// If the line is the start of the game section // If the line is the start of the game section
else if (line.ToLowerInvariant().StartsWith("[games]")) else if (line.ToLowerInvariant().StartsWith("[games]"))
{ {
blocktype = "games"; blocktype = "games";
} }
// Otherwise, it's not a section and it's data, so get out all data // Otherwise, it's not a section and it's data, so get out all data
else else
{ {
// If we have an author // If we have an author
if (line.ToLowerInvariant().StartsWith("author=")) if (line.ToLowerInvariant().StartsWith("author="))
{ {
Author = (String.IsNullOrWhiteSpace(Author) ? line.Split('=')[1] : Author); Author = (String.IsNullOrWhiteSpace(Author) ? line.Split('=')[1] : Author);
} }
// If we have one of the three version tags // If we have one of the three version tags
else if (line.ToLowerInvariant().StartsWith("version=")) else if (line.ToLowerInvariant().StartsWith("version="))
{ {
switch (blocktype) switch (blocktype)
{ {
case "credits": case "credits":
Version = (String.IsNullOrWhiteSpace(Version) ? line.Split('=')[1] : Version); Version = (String.IsNullOrWhiteSpace(Version) ? line.Split('=')[1] : Version);
break; break;
case "emulator": case "emulator":
Description = (String.IsNullOrWhiteSpace(Description) ? line.Split('=')[1] : Description); Description = (String.IsNullOrWhiteSpace(Description) ? line.Split('=')[1] : Description);
break; break;
} }
} }
// If we have a URL // If we have a URL
else if (line.ToLowerInvariant().StartsWith("url=")) else if (line.ToLowerInvariant().StartsWith("url="))
{ {
Url = (String.IsNullOrWhiteSpace(Url) ? line.Split('=')[1] : Url); Url = (String.IsNullOrWhiteSpace(Url) ? line.Split('=')[1] : Url);
} }
// If we have a comment // If we have a comment
else if (line.ToLowerInvariant().StartsWith("comment=")) else if (line.ToLowerInvariant().StartsWith("comment="))
{ {
Comment = (String.IsNullOrWhiteSpace(Comment) ? line.Split('=')[1] : Comment); Comment = (String.IsNullOrWhiteSpace(Comment) ? line.Split('=')[1] : Comment);
} }
// If we have the split flag // If we have the split flag
else if (line.ToLowerInvariant().StartsWith("split=")) else if (line.ToLowerInvariant().StartsWith("split="))
{ {
if (Int32.TryParse(line.Split('=')[1], out int split)) if (Int32.TryParse(line.Split('=')[1], out int split))
{ {
if (split == 1 && ForceMerging == ForceMerging.None) if (split == 1 && ForceMerging == ForceMerging.None)
{ {
ForceMerging = ForceMerging.Split; ForceMerging = ForceMerging.Split;
} }
} }
} }
// If we have the merge tag // If we have the merge tag
else if (line.ToLowerInvariant().StartsWith("merge=")) else if (line.ToLowerInvariant().StartsWith("merge="))
{ {
if (Int32.TryParse(line.Split('=')[1], out int merge)) if (Int32.TryParse(line.Split('=')[1], out int merge))
{ {
if (merge == 1 && ForceMerging == ForceMerging.None) if (merge == 1 && ForceMerging == ForceMerging.None)
{ {
ForceMerging = ForceMerging.Full; ForceMerging = ForceMerging.Full;
} }
} }
} }
// If we have the refname tag // If we have the refname tag
else if (line.ToLowerInvariant().StartsWith("refname=")) else if (line.ToLowerInvariant().StartsWith("refname="))
{ {
Name = (String.IsNullOrWhiteSpace(Name) ? line.Split('=')[1] : Name); Name = (String.IsNullOrWhiteSpace(Name) ? line.Split('=')[1] : Name);
} }
// If we have a rom // If we have a rom
else if (line.StartsWith("¬")) else if (line.StartsWith("¬"))
{ {
// Some old RC DATs have this behavior // Some old RC DATs have this behavior
if (line.Contains("¬N¬O")) if (line.Contains("¬N¬O"))
{ {
line = line.Replace("¬N¬O", "") + "¬¬"; line = line.Replace("¬N¬O", "") + "¬¬";
} }
/* /*
The rominfo order is as follows: The rominfo order is as follows:
1 - parent name 1 - parent name
2 - parent description 2 - parent description
3 - game name 3 - game name
4 - game description 4 - game description
5 - rom name 5 - rom name
6 - rom crc 6 - rom crc
7 - rom size 7 - rom size
8 - romof name 8 - romof name
9 - merge name 9 - merge name
*/ */
string[] rominfo = line.Split('¬'); string[] rominfo = line.Split('¬');
// Try getting the size separately // Try getting the size separately
if (!Int64.TryParse(rominfo[7], out long size)) if (!Int64.TryParse(rominfo[7], out long size))
{ {
size = 0; size = 0;
} }
Rom rom = new Rom Rom rom = new Rom
{ {
Name = rominfo[5], Name = rominfo[5],
Size = size, Size = size,
CRC = Utilities.CleanHashData(rominfo[6], Constants.CRCLength), CRC = Utilities.CleanHashData(rominfo[6], Constants.CRCLength),
ItemStatus = ItemStatus.None, ItemStatus = ItemStatus.None,
MachineName = rominfo[3], MachineName = rominfo[3],
MachineDescription = rominfo[4], MachineDescription = rominfo[4],
CloneOf = rominfo[1], CloneOf = rominfo[1],
RomOf = rominfo[8], RomOf = rominfo[8],
SystemID = sysid, SystemID = sysid,
SourceID = srcid, SourceID = srcid,
}; };
// Now process and add the rom // Now process and add the rom
ParseAddHelper(rom, clean, remUnicode); ParseAddHelper(rom, clean, remUnicode);
} }
} }
} }
sr.Dispose(); sr.Dispose();
} }
/// <summary> /// <summary>
/// Create and open an output file for writing direct from a dictionary /// Create and open an output file for writing direct from a dictionary
/// </summary> /// </summary>
/// <param name="outfile">Name of the file to write to</param> /// <param name="outfile">Name of the file to write to</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param> /// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the DAT was written correctly, false otherwise</returns> /// <returns>True if the DAT was written correctly, false otherwise</returns>
public override bool WriteToFile(string outfile, bool ignoreblanks = false) public override bool WriteToFile(string outfile, bool ignoreblanks = false)
{ {
try try
{ {
Globals.Logger.User("Opening file for writing: {0}", outfile); Globals.Logger.User("Opening file for writing: {0}", outfile);
FileStream fs = Utilities.TryCreate(outfile); FileStream fs = Utilities.TryCreate(outfile);
// If we get back null for some reason, just log and return // If we get back null for some reason, just log and return
if (fs == null) if (fs == null)
{ {
Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile); Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile);
return false; return false;
} }
StreamWriter sw = new StreamWriter(fs, new UTF8Encoding(false)); StreamWriter sw = new StreamWriter(fs, new UTF8Encoding(false));
// Write out the header // Write out the header
WriteHeader(sw); WriteHeader(sw);
// Write out each of the machines and roms // Write out each of the machines and roms
string lastgame = null; string lastgame = null;
List<string> splitpath = new List<string>(); List<string> splitpath = new List<string>();
// Get a properly sorted set of keys // Get a properly sorted set of keys
List<string> keys = Keys; List<string> keys = Keys;
keys.Sort(new NaturalComparer()); keys.Sort(new NaturalComparer());
foreach (string key in keys) foreach (string key in keys)
{ {
List<DatItem> roms = this[key]; List<DatItem> roms = this[key];
// Resolve the names in the block // Resolve the names in the block
roms = DatItem.ResolveNames(roms); roms = DatItem.ResolveNames(roms);
for (int index = 0; index < roms.Count; index++) for (int index = 0; index < roms.Count; index++)
{ {
DatItem rom = roms[index]; DatItem rom = roms[index];
// There are apparently times when a null rom can skip by, skip them // There are apparently times when a null rom can skip by, skip them
if (rom.Name == null || rom.MachineName == null) if (rom.Name == null || rom.MachineName == null)
{ {
Globals.Logger.Warning("Null rom found!"); Globals.Logger.Warning("Null rom found!");
continue; continue;
} }
// If we have a "null" game (created by DATFromDir or something similar), log it to file // If we have a "null" game (created by DATFromDir or something similar), log it to file
if (rom.ItemType == ItemType.Rom if (rom.ItemType == ItemType.Rom
&& ((Rom)rom).Size == -1 && ((Rom)rom).Size == -1
&& ((Rom)rom).CRC == "null") && ((Rom)rom).CRC == "null")
{ {
Globals.Logger.Verbose("Empty folder found: {0}", rom.MachineName); Globals.Logger.Verbose("Empty folder found: {0}", rom.MachineName);
rom.Name = (rom.Name == "null" ? "-" : rom.Name); rom.Name = (rom.Name == "null" ? "-" : rom.Name);
((Rom)rom).Size = Constants.SizeZero; ((Rom)rom).Size = Constants.SizeZero;
((Rom)rom).CRC = ((Rom)rom).CRC == "null" ? Constants.CRCZero : null; ((Rom)rom).CRC = ((Rom)rom).CRC == "null" ? Constants.CRCZero : null;
((Rom)rom).MD5 = ((Rom)rom).MD5 == "null" ? Constants.MD5Zero : null; ((Rom)rom).MD5 = ((Rom)rom).MD5 == "null" ? Constants.MD5Zero : null;
((Rom)rom).SHA1 = ((Rom)rom).SHA1 == "null" ? Constants.SHA1Zero : null; ((Rom)rom).SHA1 = ((Rom)rom).SHA1 == "null" ? Constants.SHA1Zero : null;
((Rom)rom).SHA256 = ((Rom)rom).SHA256 == "null" ? Constants.SHA256Zero : null; ((Rom)rom).SHA256 = ((Rom)rom).SHA256 == "null" ? Constants.SHA256Zero : null;
((Rom)rom).SHA384 = ((Rom)rom).SHA384 == "null" ? Constants.SHA384Zero : null; ((Rom)rom).SHA384 = ((Rom)rom).SHA384 == "null" ? Constants.SHA384Zero : null;
((Rom)rom).SHA512 = ((Rom)rom).SHA512 == "null" ? Constants.SHA512Zero : null; ((Rom)rom).SHA512 = ((Rom)rom).SHA512 == "null" ? Constants.SHA512Zero : null;
} }
// Now, output the rom data // Now, output the rom data
WriteDatItem(sw, rom, ignoreblanks); WriteDatItem(sw, rom, ignoreblanks);
// Set the new data to compare against // Set the new data to compare against
lastgame = rom.MachineName; lastgame = rom.MachineName;
} }
} }
Globals.Logger.Verbose("File written!" + Environment.NewLine); Globals.Logger.Verbose("File written!" + Environment.NewLine);
sw.Dispose(); sw.Dispose();
fs.Dispose(); fs.Dispose();
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return false; return false;
} }
return true; return true;
} }
/// <summary> /// <summary>
/// Write out DAT header using the supplied StreamWriter /// Write out DAT header using the supplied StreamWriter
/// </summary> /// </summary>
/// <param name="sw">StreamWriter to output to</param> /// <param name="sw">StreamWriter to output to</param>
/// <returns>True if the data was written, false on error</returns> /// <returns>True if the data was written, false on error</returns>
private bool WriteHeader(StreamWriter sw) private bool WriteHeader(StreamWriter sw)
{ {
try try
{ {
string header = header = "[CREDITS]\n" + string header = header = "[CREDITS]\n" +
"author=" + Author + "\n" + "author=" + Author + "\n" +
"version=" + Version + "\n" + "version=" + Version + "\n" +
"comment=" + Comment + "\n" + "comment=" + Comment + "\n" +
"[DAT]\n" + "[DAT]\n" +
"version=2.50\n" + "version=2.50\n" +
"split=" + (ForceMerging == ForceMerging.Split ? "1" : "0") + "\n" + "split=" + (ForceMerging == ForceMerging.Split ? "1" : "0") + "\n" +
"merge=" + (ForceMerging == ForceMerging.Full || ForceMerging == ForceMerging.Merged ? "1" : "0") + "\n" + "merge=" + (ForceMerging == ForceMerging.Full || ForceMerging == ForceMerging.Merged ? "1" : "0") + "\n" +
"[EMULATOR]\n" + "[EMULATOR]\n" +
"refname=" + Name + "\n" + "refname=" + Name + "\n" +
"version=" + Description + "\n" + "version=" + Description + "\n" +
"[GAMES]\n"; "[GAMES]\n";
// Write the header out // Write the header out
sw.Write(header); sw.Write(header);
sw.Flush(); sw.Flush();
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return false; return false;
} }
return true; return true;
} }
/// <summary> /// <summary>
/// Write out DatItem using the supplied StreamWriter /// Write out DatItem using the supplied StreamWriter
/// </summary> /// </summary>
/// <param name="sw">StreamWriter to output to</param> /// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param> /// <param name="rom">DatItem object to be output</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param> /// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the data was written, false on error</returns> /// <returns>True if the data was written, false on error</returns>
private bool WriteDatItem(StreamWriter sw, DatItem rom, bool ignoreblanks = false) private bool WriteDatItem(StreamWriter sw, DatItem rom, bool ignoreblanks = false)
{ {
// If we are in ignore blanks mode AND we have a blank (0-size) rom, skip // If we are in ignore blanks mode AND we have a blank (0-size) rom, skip
if (ignoreblanks if (ignoreblanks
&& (rom.ItemType == ItemType.Rom && (rom.ItemType == ItemType.Rom
&& (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1))) && (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1)))
{ {
return true; return true;
} }
try try
{ {
string state = ""; string state = "";
// Pre-process the item name // Pre-process the item name
ProcessItemName(rom, true); ProcessItemName(rom, true);
if (rom.ItemType == ItemType.Rom) if (rom.ItemType == ItemType.Rom)
{ {
state += "¬" + (!ExcludeFields[(int)Field.CloneOf] && String.IsNullOrWhiteSpace(rom.CloneOf) ? HttpUtility.HtmlEncode(rom.CloneOf) : "") + state += "¬" + (!ExcludeFields[(int)Field.CloneOf] && String.IsNullOrWhiteSpace(rom.CloneOf) ? HttpUtility.HtmlEncode(rom.CloneOf) : "") +
"¬" + (!ExcludeFields[(int)Field.CloneOf] && String.IsNullOrWhiteSpace(rom.CloneOf) ? HttpUtility.HtmlEncode(rom.CloneOf) : "") + "¬" + (!ExcludeFields[(int)Field.CloneOf] && String.IsNullOrWhiteSpace(rom.CloneOf) ? HttpUtility.HtmlEncode(rom.CloneOf) : "") +
"¬" + (!ExcludeFields[(int)Field.MachineName] ? HttpUtility.HtmlEncode(rom.MachineName) : "") + "¬" + (!ExcludeFields[(int)Field.MachineName] ? HttpUtility.HtmlEncode(rom.MachineName) : "") +
"¬" + (!ExcludeFields[(int)Field.Description] ? HttpUtility.HtmlEncode((String.IsNullOrWhiteSpace(rom.MachineDescription) ? rom.MachineName : rom.MachineDescription)) : "") + "¬" + (!ExcludeFields[(int)Field.Description] ? HttpUtility.HtmlEncode((String.IsNullOrWhiteSpace(rom.MachineDescription) ? rom.MachineName : rom.MachineDescription)) : "") +
"¬" + (!ExcludeFields[(int)Field.Name] ? HttpUtility.HtmlEncode(rom.Name) : "") + "¬" + (!ExcludeFields[(int)Field.Name] ? HttpUtility.HtmlEncode(rom.Name) : "") +
"¬" + (!ExcludeFields[(int)Field.CRC] ? ((Rom)rom).CRC.ToLowerInvariant() : "") + "¬" + (!ExcludeFields[(int)Field.CRC] ? ((Rom)rom).CRC.ToLowerInvariant() : "") +
"¬" + (!ExcludeFields[(int)Field.Size] && ((Rom)rom).Size != -1 ? ((Rom)rom).Size.ToString() : "") + "¬¬¬\n"; "¬" + (!ExcludeFields[(int)Field.Size] && ((Rom)rom).Size != -1 ? ((Rom)rom).Size.ToString() : "") + "¬¬¬\n";
} }
else if (rom.ItemType == ItemType.Disk) else if (rom.ItemType == ItemType.Disk)
{ {
state += "¬" + (!ExcludeFields[(int)Field.CloneOf] && String.IsNullOrWhiteSpace(rom.CloneOf) ? HttpUtility.HtmlEncode(rom.CloneOf) : "") + state += "¬" + (!ExcludeFields[(int)Field.CloneOf] && String.IsNullOrWhiteSpace(rom.CloneOf) ? HttpUtility.HtmlEncode(rom.CloneOf) : "") +
"¬" + (!ExcludeFields[(int)Field.CloneOf] && String.IsNullOrWhiteSpace(rom.CloneOf) ? HttpUtility.HtmlEncode(rom.CloneOf) : "") + "¬" + (!ExcludeFields[(int)Field.CloneOf] && String.IsNullOrWhiteSpace(rom.CloneOf) ? HttpUtility.HtmlEncode(rom.CloneOf) : "") +
"¬" + (!ExcludeFields[(int)Field.MachineName] ? HttpUtility.HtmlEncode(rom.MachineName) : "") + "¬" + (!ExcludeFields[(int)Field.MachineName] ? HttpUtility.HtmlEncode(rom.MachineName) : "") +
"¬" + (!ExcludeFields[(int)Field.Description] ? HttpUtility.HtmlEncode((String.IsNullOrWhiteSpace(rom.MachineDescription) ? rom.MachineName : rom.MachineDescription)) : "") + "¬" + (!ExcludeFields[(int)Field.Description] ? HttpUtility.HtmlEncode((String.IsNullOrWhiteSpace(rom.MachineDescription) ? rom.MachineName : rom.MachineDescription)) : "") +
"¬" + (!ExcludeFields[(int)Field.Name] ? HttpUtility.HtmlEncode(rom.Name) : "") + "¬" + (!ExcludeFields[(int)Field.Name] ? HttpUtility.HtmlEncode(rom.Name) : "") +
"¬¬¬¬¬\n"; "¬¬¬¬¬\n";
} }
sw.Write(state); sw.Write(state);
sw.Flush(); sw.Flush();
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return false; return false;
} }
return true; return true;
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text; using System.Text;
using SabreTools.Library.Data; using SabreTools.Library.Data;
using SabreTools.Library.DatItems; using SabreTools.Library.DatItems;
using SabreTools.Library.Tools; using SabreTools.Library.Tools;
@@ -18,515 +16,515 @@ using NaturalSort;
namespace SabreTools.Library.DatFiles namespace SabreTools.Library.DatFiles
{ {
/// <summary> /// <summary>
/// Represents parsing and writing of a value-separated DAT /// Represents parsing and writing of a value-separated DAT
/// </summary> /// </summary>
internal class SeparatedValue : DatFile internal class SeparatedValue : DatFile
{ {
// Private instance variables specific to Separated Value DATs // Private instance variables specific to Separated Value DATs
char _delim; char _delim;
/// <summary> /// <summary>
/// Constructor designed for casting a base DatFile /// Constructor designed for casting a base DatFile
/// </summary> /// </summary>
/// <param name="datFile">Parent DatFile to copy from</param> /// <param name="datFile">Parent DatFile to copy from</param>
/// <param name="delim">Delimiter for parsing individual lines</param> /// <param name="delim">Delimiter for parsing individual lines</param>
public SeparatedValue(DatFile datFile, char delim) public SeparatedValue(DatFile datFile, char delim)
: base(datFile, cloneHeader: false) : base(datFile, cloneHeader: false)
{ {
_delim = delim; _delim = delim;
} }
/// <summary> /// <summary>
/// Parse a character-separated value DAT and return all found games and roms within /// Parse a character-separated value DAT and return all found games and roms within
/// </summary> /// </summary>
/// <param name="filename">Name of the file to be parsed</param> /// <param name="filename">Name of the file to be parsed</param>
/// <param name="sysid">System ID for the DAT</param> /// <param name="sysid">System ID for the DAT</param>
/// <param name="srcid">Source 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="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="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> /// <param name="remUnicode">True if we should remove non-ASCII characters from output, false otherwise (default)</param>
public override void ParseFile( public override void ParseFile(
// Standard Dat parsing // Standard Dat parsing
string filename, string filename,
int sysid, int sysid,
int srcid, int srcid,
// Miscellaneous // Miscellaneous
bool keep, bool keep,
bool clean, bool clean,
bool remUnicode) bool remUnicode)
{ {
// Open a file reader // Open a file reader
Encoding enc = Utilities.GetEncoding(filename); Encoding enc = Utilities.GetEncoding(filename);
StreamReader sr = new StreamReader(Utilities.TryOpenRead(filename), enc); StreamReader sr = new StreamReader(Utilities.TryOpenRead(filename), enc);
// Create an empty list of columns to parse though // Create an empty list of columns to parse though
List<string> columns = new List<string>(); List<string> columns = new List<string>();
long linenum = -1; long linenum = -1;
while (!sr.EndOfStream) while (!sr.EndOfStream)
{ {
string line = sr.ReadLine(); string line = sr.ReadLine();
linenum++; linenum++;
// Parse the first line, getting types from the column names // Parse the first line, getting types from the column names
if (linenum == 0) if (linenum == 0)
{ {
string[] parsedColumns = line.Split(_delim); string[] parsedColumns = line.Split(_delim);
foreach (string parsed in parsedColumns) foreach (string parsed in parsedColumns)
{ {
switch (parsed.ToLowerInvariant().Trim('"')) switch (parsed.ToLowerInvariant().Trim('"'))
{ {
case "file": case "file":
case "filename": case "filename":
case "file name": case "file name":
columns.Add("DatFile.FileName"); columns.Add("DatFile.FileName");
break; break;
case "internal name": case "internal name":
columns.Add("DatFile.Name"); columns.Add("DatFile.Name");
break; break;
case "description": case "description":
case "dat description": case "dat description":
columns.Add("DatFile.Description"); columns.Add("DatFile.Description");
break; break;
case "game name": case "game name":
case "game": case "game":
case "machine": case "machine":
columns.Add("Machine.Name"); columns.Add("Machine.Name");
break; break;
case "game description": case "game description":
columns.Add("Description"); columns.Add("Description");
break; break;
case "type": case "type":
columns.Add("DatItem.Type"); columns.Add("DatItem.Type");
break; break;
case "rom": case "rom":
case "romname": case "romname":
case "rom name": case "rom name":
case "name": case "name":
columns.Add("Rom.Name"); columns.Add("Rom.Name");
break; break;
case "disk": case "disk":
case "diskname": case "diskname":
case "disk name": case "disk name":
columns.Add("Disk.Name"); columns.Add("Disk.Name");
break; break;
case "size": case "size":
columns.Add("DatItem.Size"); columns.Add("DatItem.Size");
break; break;
case "crc": case "crc":
case "crc hash": case "crc hash":
columns.Add("DatItem.CRC"); columns.Add("DatItem.CRC");
break; break;
case "md5": case "md5":
case "md5 hash": case "md5 hash":
columns.Add("DatItem.MD5"); columns.Add("DatItem.MD5");
break; break;
case "sha1": case "sha1":
case "sha-1": case "sha-1":
case "sha1 hash": case "sha1 hash":
case "sha-1 hash": case "sha-1 hash":
columns.Add("DatItem.SHA1"); columns.Add("DatItem.SHA1");
break; break;
case "sha256": case "sha256":
case "sha-256": case "sha-256":
case "sha256 hash": case "sha256 hash":
case "sha-256 hash": case "sha-256 hash":
columns.Add("DatItem.SHA256"); columns.Add("DatItem.SHA256");
break; break;
case "sha384": case "sha384":
case "sha-384": case "sha-384":
case "sha384 hash": case "sha384 hash":
case "sha-384 hash": case "sha-384 hash":
columns.Add("DatItem.SHA384"); columns.Add("DatItem.SHA384");
break; break;
case "sha512": case "sha512":
case "sha-512": case "sha-512":
case "sha512 hash": case "sha512 hash":
case "sha-512 hash": case "sha-512 hash":
columns.Add("DatItem.SHA512"); columns.Add("DatItem.SHA512");
break; break;
case "nodump": case "nodump":
case "no dump": case "no dump":
case "status": case "status":
case "item status": case "item status":
columns.Add("DatItem.Nodump"); columns.Add("DatItem.Nodump");
break; break;
case "date": case "date":
columns.Add("DatItem.Date"); columns.Add("DatItem.Date");
break; break;
default: default:
columns.Add("INVALID"); columns.Add("INVALID");
break; break;
} }
} }
continue; continue;
} }
// Otherwise, we want to split the line and parse // Otherwise, we want to split the line and parse
string[] parsedLine = line.Split(_delim); string[] parsedLine = line.Split(_delim);
// If the line doesn't have the correct number of columns, we log and skip // If the line doesn't have the correct number of columns, we log and skip
if (parsedLine.Length != columns.Count) if (parsedLine.Length != columns.Count)
{ {
Globals.Logger.Warning("Malformed line found in '{0}' at line {1}", filename, linenum); Globals.Logger.Warning("Malformed line found in '{0}' at line {1}", filename, linenum);
continue; continue;
} }
// Set the output item information // Set the output item information
string machineName = null, machineDesc = null, name = null, crc = null, md5 = null, sha1 = null, string machineName = null, machineDesc = null, name = null, crc = null, md5 = null, sha1 = null,
sha256 = null, sha384 = null, sha512 = null, date = null; sha256 = null, sha384 = null, sha512 = null, date = null;
long size = -1; long size = -1;
ItemType itemType = ItemType.Rom; ItemType itemType = ItemType.Rom;
ItemStatus status = ItemStatus.None; ItemStatus status = ItemStatus.None;
// Now we loop through and get values for everything // Now we loop through and get values for everything
for (int i = 0; i < columns.Count; i++) for (int i = 0; i < columns.Count; i++)
{ {
string value = parsedLine[i].Trim('"'); string value = parsedLine[i].Trim('"');
switch (columns[i]) switch (columns[i])
{ {
case "DatFile.FileName": case "DatFile.FileName":
FileName = (String.IsNullOrWhiteSpace(FileName) ? value : FileName); FileName = (String.IsNullOrWhiteSpace(FileName) ? value : FileName);
break; break;
case "DatFile.Name": case "DatFile.Name":
Name = (String.IsNullOrWhiteSpace(Name) ? value : Name); Name = (String.IsNullOrWhiteSpace(Name) ? value : Name);
break; break;
case "DatFile.Description": case "DatFile.Description":
Description = (String.IsNullOrWhiteSpace(Description) ? value : Description); Description = (String.IsNullOrWhiteSpace(Description) ? value : Description);
break; break;
case "Machine.Name": case "Machine.Name":
machineName = value; machineName = value;
break; break;
case "Description": case "Description":
machineDesc = value; machineDesc = value;
break; break;
case "DatItem.Type": case "DatItem.Type":
itemType = Utilities.GetItemType(value) ?? ItemType.Rom; itemType = Utilities.GetItemType(value) ?? ItemType.Rom;
break; break;
case "Rom.Name": case "Rom.Name":
case "Disk.Name": case "Disk.Name":
name = String.IsNullOrWhiteSpace(value) ? name : value; name = String.IsNullOrWhiteSpace(value) ? name : value;
break; break;
case "DatItem.Size": case "DatItem.Size":
if (!Int64.TryParse(value, out size)) if (!Int64.TryParse(value, out size))
{ {
size = -1; size = -1;
} }
break; break;
case "DatItem.CRC": case "DatItem.CRC":
crc = Utilities.CleanHashData(value, Constants.CRCLength); crc = Utilities.CleanHashData(value, Constants.CRCLength);
break; break;
case "DatItem.MD5": case "DatItem.MD5":
md5 = Utilities.CleanHashData(value, Constants.MD5Length); md5 = Utilities.CleanHashData(value, Constants.MD5Length);
break; break;
case "DatItem.SHA1": case "DatItem.SHA1":
sha1 = Utilities.CleanHashData(value, Constants.SHA1Length); sha1 = Utilities.CleanHashData(value, Constants.SHA1Length);
break; break;
case "DatItem.SHA256": case "DatItem.SHA256":
sha256 = Utilities.CleanHashData(value, Constants.SHA256Length); sha256 = Utilities.CleanHashData(value, Constants.SHA256Length);
break; break;
case "DatItem.SHA384": case "DatItem.SHA384":
sha384 = Utilities.CleanHashData(value, Constants.SHA384Length); sha384 = Utilities.CleanHashData(value, Constants.SHA384Length);
break; break;
case "DatItem.SHA512": case "DatItem.SHA512":
sha512 = Utilities.CleanHashData(value, Constants.SHA512Length); sha512 = Utilities.CleanHashData(value, Constants.SHA512Length);
break; break;
case "DatItem.Nodump": case "DatItem.Nodump":
status = Utilities.GetItemStatus(value); status = Utilities.GetItemStatus(value);
break; break;
case "DatItem.Date": case "DatItem.Date":
date = value; date = value;
break; break;
} }
} }
// And now we populate and add the new item // And now we populate and add the new item
switch (itemType) switch (itemType)
{ {
case ItemType.Archive: case ItemType.Archive:
Archive archive = new Archive() Archive archive = new Archive()
{ {
Name = name, Name = name,
MachineName = machineName, MachineName = machineName,
MachineDescription = machineDesc, MachineDescription = machineDesc,
}; };
ParseAddHelper(archive, clean, remUnicode); ParseAddHelper(archive, clean, remUnicode);
break; break;
case ItemType.BiosSet: case ItemType.BiosSet:
BiosSet biosset = new BiosSet() BiosSet biosset = new BiosSet()
{ {
Name = name, Name = name,
MachineName = machineName, MachineName = machineName,
Description = machineDesc, Description = machineDesc,
}; };
ParseAddHelper(biosset, clean, remUnicode); ParseAddHelper(biosset, clean, remUnicode);
break; break;
case ItemType.Disk: case ItemType.Disk:
Disk disk = new Disk() Disk disk = new Disk()
{ {
Name = name, Name = name,
MD5 = md5, MD5 = md5,
SHA1 = sha1, SHA1 = sha1,
SHA256 = sha256, SHA256 = sha256,
SHA384 = sha384, SHA384 = sha384,
SHA512 = sha512, SHA512 = sha512,
MachineName = machineName, MachineName = machineName,
MachineDescription = machineDesc, MachineDescription = machineDesc,
ItemStatus = status, ItemStatus = status,
}; };
ParseAddHelper(disk, clean, remUnicode); ParseAddHelper(disk, clean, remUnicode);
break; break;
case ItemType.Release: case ItemType.Release:
Release release = new Release() Release release = new Release()
{ {
Name = name, Name = name,
MachineName = machineName, MachineName = machineName,
MachineDescription = machineDesc, MachineDescription = machineDesc,
}; };
ParseAddHelper(release, clean, remUnicode); ParseAddHelper(release, clean, remUnicode);
break; break;
case ItemType.Rom: case ItemType.Rom:
Rom rom = new Rom() Rom rom = new Rom()
{ {
Name = name, Name = name,
Size = size, Size = size,
CRC = crc, CRC = crc,
MD5 = md5, MD5 = md5,
SHA1 = sha1, SHA1 = sha1,
SHA256 = sha256, SHA256 = sha256,
SHA384 = sha384, SHA384 = sha384,
SHA512 = sha512, SHA512 = sha512,
Date = date, Date = date,
MachineName = machineName, MachineName = machineName,
MachineDescription = machineDesc, MachineDescription = machineDesc,
ItemStatus = status, ItemStatus = status,
}; };
ParseAddHelper(rom, clean, remUnicode); ParseAddHelper(rom, clean, remUnicode);
break; break;
case ItemType.Sample: case ItemType.Sample:
Sample sample = new Sample() Sample sample = new Sample()
{ {
Name = name, Name = name,
MachineName = machineName, MachineName = machineName,
MachineDescription = machineDesc, MachineDescription = machineDesc,
}; };
ParseAddHelper(sample, clean, remUnicode); ParseAddHelper(sample, clean, remUnicode);
break; break;
} }
} }
} }
/// <summary> /// <summary>
/// Create and open an output file for writing direct from a dictionary /// Create and open an output file for writing direct from a dictionary
/// </summary> /// </summary>
/// <param name="outfile">Name of the file to write to</param> /// <param name="outfile">Name of the file to write to</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param> /// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the DAT was written correctly, false otherwise</returns> /// <returns>True if the DAT was written correctly, false otherwise</returns>
public override bool WriteToFile(string outfile, bool ignoreblanks = false) public override bool WriteToFile(string outfile, bool ignoreblanks = false)
{ {
try try
{ {
Globals.Logger.User("Opening file for writing: {0}", outfile); Globals.Logger.User("Opening file for writing: {0}", outfile);
FileStream fs = Utilities.TryCreate(outfile); FileStream fs = Utilities.TryCreate(outfile);
// If we get back null for some reason, just log and return // If we get back null for some reason, just log and return
if (fs == null) if (fs == null)
{ {
Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile); Globals.Logger.Warning("File '{0}' could not be created for writing! Please check to see if the file is writable", outfile);
return false; return false;
} }
StreamWriter sw = new StreamWriter(fs, new UTF8Encoding(false)); StreamWriter sw = new StreamWriter(fs, new UTF8Encoding(false));
// Write out the header // Write out the header
WriteHeader(sw); WriteHeader(sw);
// Get a properly sorted set of keys // Get a properly sorted set of keys
List<string> keys = Keys; List<string> keys = Keys;
keys.Sort(new NaturalComparer()); keys.Sort(new NaturalComparer());
foreach (string key in keys) foreach (string key in keys)
{ {
List<DatItem> roms = this[key]; List<DatItem> roms = this[key];
// Resolve the names in the block // Resolve the names in the block
roms = DatItem.ResolveNames(roms); roms = DatItem.ResolveNames(roms);
for (int index = 0; index < roms.Count; index++) for (int index = 0; index < roms.Count; index++)
{ {
DatItem rom = roms[index]; DatItem rom = roms[index];
// There are apparently times when a null rom can skip by, skip them // There are apparently times when a null rom can skip by, skip them
if (rom.Name == null || rom.MachineName == null) if (rom.Name == null || rom.MachineName == null)
{ {
Globals.Logger.Warning("Null rom found!"); Globals.Logger.Warning("Null rom found!");
continue; continue;
} }
// If we have a "null" game (created by DATFromDir or something similar), log it to file // If we have a "null" game (created by DATFromDir or something similar), log it to file
if (rom.ItemType == ItemType.Rom if (rom.ItemType == ItemType.Rom
&& ((Rom)rom).Size == -1 && ((Rom)rom).Size == -1
&& ((Rom)rom).CRC == "null") && ((Rom)rom).CRC == "null")
{ {
Globals.Logger.Verbose("Empty folder found: {0}", rom.MachineName); Globals.Logger.Verbose("Empty folder found: {0}", rom.MachineName);
} }
// Now, output the rom data // Now, output the rom data
WriteDatItem(sw, rom, ignoreblanks); WriteDatItem(sw, rom, ignoreblanks);
} }
} }
Globals.Logger.Verbose("File written!" + Environment.NewLine); Globals.Logger.Verbose("File written!" + Environment.NewLine);
sw.Dispose(); sw.Dispose();
fs.Dispose(); fs.Dispose();
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return false; return false;
} }
return true; return true;
} }
/// <summary> /// <summary>
/// Write out DAT header using the supplied StreamWriter /// Write out DAT header using the supplied StreamWriter
/// </summary> /// </summary>
/// <param name="sw">StreamWriter to output to</param> /// <param name="sw">StreamWriter to output to</param>
/// <returns>True if the data was written, false on error</returns> /// <returns>True if the data was written, false on error</returns>
private bool WriteHeader(StreamWriter sw) private bool WriteHeader(StreamWriter sw)
{ {
try try
{ {
string header = string.Format("\"File Name\"{0}\"Internal Name\"{0}\"Description\"{0}\"Game Name\"{0}\"Game Description\"{0}\"Type\"{0}\"" + string header = string.Format("\"File Name\"{0}\"Internal Name\"{0}\"Description\"{0}\"Game Name\"{0}\"Game Description\"{0}\"Type\"{0}\"" +
"Rom Name\"{0}\"Disk Name\"{0}\"Size\"{0}\"CRC\"{0}\"MD5\"{0}\"SHA1\"{0}\"SHA256\"{0}\"Nodump\"\n", _delim); "Rom Name\"{0}\"Disk Name\"{0}\"Size\"{0}\"CRC\"{0}\"MD5\"{0}\"SHA1\"{0}\"SHA256\"{0}\"Nodump\"\n", _delim);
// Write the header out // Write the header out
sw.Write(header); sw.Write(header);
sw.Flush(); sw.Flush();
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return false; return false;
} }
return true; return true;
} }
/// <summary> /// <summary>
/// Write out DatItem using the supplied StreamWriter /// Write out DatItem using the supplied StreamWriter
/// </summary> /// </summary>
/// <param name="sw">StreamWriter to output to</param> /// <param name="sw">StreamWriter to output to</param>
/// <param name="rom">DatItem object to be output</param> /// <param name="rom">DatItem object to be output</param>
/// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param> /// <param name="ignoreblanks">True if blank roms should be skipped on output, false otherwise (default)</param>
/// <returns>True if the data was written, false on error</returns> /// <returns>True if the data was written, false on error</returns>
private bool WriteDatItem(StreamWriter sw, DatItem rom, bool ignoreblanks = false) private bool WriteDatItem(StreamWriter sw, DatItem rom, bool ignoreblanks = false)
{ {
// If we are in ignore blanks mode AND we have a blank (0-size) rom, skip // If we are in ignore blanks mode AND we have a blank (0-size) rom, skip
if (ignoreblanks if (ignoreblanks
&& (rom.ItemType == ItemType.Rom && (rom.ItemType == ItemType.Rom
&& (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1))) && (((Rom)rom).Size == 0 || ((Rom)rom).Size == -1)))
{ {
return true; return true;
} }
try try
{ {
// Initialize all strings // Initialize all strings
string state = "", string state = "",
pre = "", pre = "",
post = "", post = "",
type = "", type = "",
romname = "", romname = "",
diskname = "", diskname = "",
size = "", size = "",
crc = "", crc = "",
md5 = "", md5 = "",
sha1 = "", sha1 = "",
sha256 = "", sha256 = "",
sha384 = "", sha384 = "",
sha512 = "", sha512 = "",
status = ""; status = "";
// Separated values should only output Rom and Disk // Separated values should only output Rom and Disk
if (rom.ItemType != ItemType.Disk && rom.ItemType != ItemType.Rom) if (rom.ItemType != ItemType.Disk && rom.ItemType != ItemType.Rom)
{ {
return true; return true;
} }
if (rom.ItemType == ItemType.Rom) if (rom.ItemType == ItemType.Rom)
{ {
type = "rom"; type = "rom";
romname = rom.Name; romname = rom.Name;
size = ((Rom)rom).Size.ToString(); size = ((Rom)rom).Size.ToString();
crc = ((Rom)rom).CRC; crc = ((Rom)rom).CRC;
md5 = ((Rom)rom).MD5; md5 = ((Rom)rom).MD5;
sha1 = ((Rom)rom).SHA1; sha1 = ((Rom)rom).SHA1;
sha256 = ((Rom)rom).SHA256; sha256 = ((Rom)rom).SHA256;
sha384 = ((Rom)rom).SHA384; sha384 = ((Rom)rom).SHA384;
sha512 = ((Rom)rom).SHA512; sha512 = ((Rom)rom).SHA512;
status = (((Rom)rom).ItemStatus != ItemStatus.None ? "\"" + ((Rom)rom).ItemStatus.ToString() + "\"" : "\"\""); status = (((Rom)rom).ItemStatus != ItemStatus.None ? "\"" + ((Rom)rom).ItemStatus.ToString() + "\"" : "\"\"");
} }
else if (rom.ItemType == ItemType.Disk) else if (rom.ItemType == ItemType.Disk)
{ {
type = "disk"; type = "disk";
diskname = rom.Name; diskname = rom.Name;
md5 = ((Disk)rom).MD5; md5 = ((Disk)rom).MD5;
sha1 = ((Disk)rom).SHA1; sha1 = ((Disk)rom).SHA1;
sha256 = ((Disk)rom).SHA256; sha256 = ((Disk)rom).SHA256;
sha384 = ((Disk)rom).SHA384; sha384 = ((Disk)rom).SHA384;
sha512 = ((Disk)rom).SHA512; sha512 = ((Disk)rom).SHA512;
status = (((Disk)rom).ItemStatus != ItemStatus.None ? "\"" + ((Disk)rom).ItemStatus.ToString() + "\"" : "\"\""); status = (((Disk)rom).ItemStatus != ItemStatus.None ? "\"" + ((Disk)rom).ItemStatus.ToString() + "\"" : "\"\"");
} }
pre = CreatePrefixPostfix(rom, true); pre = CreatePrefixPostfix(rom, true);
post = CreatePrefixPostfix(rom, false); post = CreatePrefixPostfix(rom, false);
string inline = string.Format("\"" + FileName + "\"" string inline = string.Format("\"" + FileName + "\""
+ "{0}\"" + Name + "\"" + "{0}\"" + Name + "\""
+ "{0}\"" + Description + "\"" + "{0}\"" + Description + "\""
+ "{0}\"" + (!ExcludeFields[(int)Field.MachineName] ? rom.MachineName : "") + "\"" + "{0}\"" + (!ExcludeFields[(int)Field.MachineName] ? rom.MachineName : "") + "\""
+ "{0}\"" + (!ExcludeFields[(int)Field.Description] ? rom.MachineDescription : "") + "\"" + "{0}\"" + (!ExcludeFields[(int)Field.Description] ? rom.MachineDescription : "") + "\""
+ "{0}\"" + type + "\"" + "{0}\"" + type + "\""
+ "{0}\"" + (!ExcludeFields[(int)Field.Name] ? romname : "") + "\"" + "{0}\"" + (!ExcludeFields[(int)Field.Name] ? romname : "") + "\""
+ "{0}\"" + (!ExcludeFields[(int)Field.Name] ? diskname : "") + "\"" + "{0}\"" + (!ExcludeFields[(int)Field.Name] ? diskname : "") + "\""
+ "{0}\"" + (!ExcludeFields[(int)Field.Size] ? size : "") + "\"" + "{0}\"" + (!ExcludeFields[(int)Field.Size] ? size : "") + "\""
+ "{0}\"" + (!ExcludeFields[(int)Field.CRC] ? crc : "") + "\"" + "{0}\"" + (!ExcludeFields[(int)Field.CRC] ? crc : "") + "\""
+ "{0}\"" + (!ExcludeFields[(int)Field.MD5] ? md5 : "") + "\"" + "{0}\"" + (!ExcludeFields[(int)Field.MD5] ? md5 : "") + "\""
+ "{0}\"" + (!ExcludeFields[(int)Field.SHA1] ? sha1 : "") + "\"" + "{0}\"" + (!ExcludeFields[(int)Field.SHA1] ? sha1 : "") + "\""
+ "{0}\"" + (!ExcludeFields[(int)Field.SHA256] ? sha256 : "") + "\"" + "{0}\"" + (!ExcludeFields[(int)Field.SHA256] ? sha256 : "") + "\""
// + "{0}\"" + (!ExcludeFields[(int)Field.SHA384] ? sha384 : "") + "\"" // + "{0}\"" + (!ExcludeFields[(int)Field.SHA384] ? sha384 : "") + "\""
// + "{0}\"" + (!ExcludeFields[(int)Field.SHA512] ? sha512 : "") + "\"" // + "{0}\"" + (!ExcludeFields[(int)Field.SHA512] ? sha512 : "") + "\""
+ "{0}" + status, _delim); + "{0}" + status, _delim);
state += pre + inline + post + "\n"; state += pre + inline + post + "\n";
sw.Write(state); sw.Write(state);
sw.Flush(); sw.Flush();
} }
catch (Exception ex) catch (Exception ex)
{ {
Globals.Logger.Error(ex.ToString()); Globals.Logger.Error(ex.ToString());
return false; return false;
} }
return true; return true;
} }
} }
} }

File diff suppressed because it is too large Load Diff