diff --git a/DATFromDir/DATFromDir.cs b/DATFromDir/DATFromDir.cs index e72bad88..a849d139 100644 --- a/DATFromDir/DATFromDir.cs +++ b/DATFromDir/DATFromDir.cs @@ -248,11 +248,68 @@ namespace SabreTools _basePath = (File.Exists(item) ? item : item + Path.DirectorySeparatorChar); _basePath = Path.GetFullPath(_basePath); } - + + bool items = false; foreach (string subitem in Directory.EnumerateFiles(item, "*", SearchOption.AllDirectories)) { + items = true; ProcessFile(subitem); } + + // If there were no subitems, add a "blank" game to to the set + if (!items) + { + RomData rom = new RomData + { + Name = "null", + Game = item.Remove(0, basePathBackup.Length), + Size = -1, + CRC = "null", + MD5 = "null", + SHA1 = "null", + }; + + string key = rom.Size + "-" + rom.CRC; + if (_dict.ContainsKey(key)) + { + _dict[key].Add(rom); + } + else + { + List temp = new List(); + temp.Add(rom); + _dict.Add(key, temp); + } + } + + // Now scour subdirectories for empties and add those as well + foreach (string subdir in Directory.EnumerateDirectories(item, "*", SearchOption.AllDirectories)) + { + if (Directory.EnumerateFiles(subdir, "*", SearchOption.AllDirectories).Count() == 0) + { + RomData rom = new RomData + { + Name = "null", + Game = subdir.Remove(0, basePathBackup.Length), + Size = -1, + CRC = "null", + MD5 = "null", + SHA1 = "null", + }; + + string key = rom.Size + "-" + rom.CRC; + if (_dict.ContainsKey(key)) + { + _dict[key].Add(rom); + } + else + { + List temp = new List(); + temp.Add(rom); + _dict.Add(key, temp); + } + } + } } _basePath = basePathBackup; } diff --git a/SabreHelper/Converters.cs b/SabreHelper/Converters.cs index f8bcd97d..046efd65 100644 --- a/SabreHelper/Converters.cs +++ b/SabreHelper/Converters.cs @@ -28,7 +28,7 @@ namespace SabreTools.Helper { XElement elem = new XElement("datafile"); - bool block = false; + bool block = false, romfound = false; for (int k = 0; k < filecontents.Length; k++) { string line = filecontents[k]; @@ -61,6 +61,7 @@ namespace SabreTools.Helper // If the line is a rom or disk and we're in a block else if ((line.Trim().StartsWith("rom (") || line.Trim().StartsWith("disk (")) && block) { + romfound = true; string[] gc = line.Trim().Split(' '); XElement temp = new XElement(gc[0]); @@ -151,6 +152,7 @@ namespace SabreTools.Helper // If we find an end bracket that's not associated with anything else, the block is done else if (Regex.IsMatch(line, _endPatternCMP) && block) { + romfound = false; block = false; elem = elem.Parent; } diff --git a/SabreHelper/Output.cs b/SabreHelper/Output.cs index 22dcad16..6471a055 100644 --- a/SabreHelper/Output.cs +++ b/SabreHelper/Output.cs @@ -233,93 +233,101 @@ namespace SabreTools.Helper } } - // Now output the rom data - switch (datdata.OutputFormat) + // If we have a "null" game (created by DATFromDir or something similar), skip trying to add a rom + if (rom.Name == "null" && rom.Size == -1 && rom.CRC == "null" && rom.MD5 == "null" && rom.SHA1 == "null") { - case OutputFormat.ClrMamePro: - state += "\t" + rom.Type + " ( name \"" + rom.Name + "\"" + - (rom.Size != 0 ? " size " + rom.Size : "") + - (rom.CRC != "" ? " crc " + rom.CRC.ToLowerInvariant() : "") + - (rom.MD5 != "" ? " md5 " + rom.MD5.ToLowerInvariant() : "") + - (rom.SHA1 != "" ? " sha1 " + rom.SHA1.ToLowerInvariant() : "") + - (rom.Nodump ? " flags nodump" : "") + - " )\n"; - break; - case OutputFormat.MissFile: - string pre = datdata.Prefix + (datdata.Quotes ? "\"" : ""); - string post = (datdata.Quotes ? "\"" : "") + datdata.Postfix; + logger.Log("Empty folder found: " + rom.Game); + } + // Otherwise, output the rom data + else + { + switch (datdata.OutputFormat) + { + case OutputFormat.ClrMamePro: + state += "\t" + rom.Type + " ( name \"" + rom.Name + "\"" + + (rom.Size != 0 ? " size " + rom.Size : "") + + (rom.CRC != "" ? " crc " + rom.CRC.ToLowerInvariant() : "") + + (rom.MD5 != "" ? " md5 " + rom.MD5.ToLowerInvariant() : "") + + (rom.SHA1 != "" ? " sha1 " + rom.SHA1.ToLowerInvariant() : "") + + (rom.Nodump ? " flags nodump" : "") + + " )\n"; + break; + case OutputFormat.MissFile: + string pre = datdata.Prefix + (datdata.Quotes ? "\"" : ""); + string post = (datdata.Quotes ? "\"" : "") + datdata.Postfix; - // If we're in Romba mode, the state is consistent - if (datdata.Romba) - { - // We can only write out if there's a SHA-1 - if (rom.SHA1 != "") + // If we're in Romba mode, the state is consistent + if (datdata.Romba) { - string name = "/" + rom.SHA1.Substring(0, 2) + "/" + rom.SHA1.Substring(2, 2) + "/" + rom.SHA1.Substring(4, 2) + "/" + - rom.SHA1.Substring(6, 2) + "/" + rom.SHA1 + ".gz\n"; - state += pre + name + post; + // We can only write out if there's a SHA-1 + if (rom.SHA1 != "") + { + string name = "/" + rom.SHA1.Substring(0, 2) + "/" + rom.SHA1.Substring(2, 2) + "/" + rom.SHA1.Substring(4, 2) + "/" + + rom.SHA1.Substring(6, 2) + "/" + rom.SHA1 + ".gz\n"; + state += pre + name + post; + } } - } - // Otherwise, use any flags - else - { - string name = (datdata.UseGame ? rom.Game : rom.Name); - if (datdata.RepExt != "") + // Otherwise, use any flags + else { - string dir = Path.GetDirectoryName(name); - dir = (dir.EndsWith(Path.DirectorySeparatorChar.ToString()) ? dir : dir + Path.DirectorySeparatorChar); - dir = (dir.StartsWith(Path.DirectorySeparatorChar.ToString()) ? dir.Remove(0, 1) : dir); - name = dir + Path.GetFileNameWithoutExtension(name) + datdata.RepExt; - } - if (datdata.AddExt != "") - { - name += datdata.AddExt; - } - if (!datdata.UseGame && datdata.GameName) - { - name = (rom.Game.EndsWith(Path.DirectorySeparatorChar.ToString()) ? rom.Game : rom.Game + Path.DirectorySeparatorChar) + name; - } + string name = (datdata.UseGame ? rom.Game : rom.Name); + if (datdata.RepExt != "") + { + string dir = Path.GetDirectoryName(name); + dir = (dir.EndsWith(Path.DirectorySeparatorChar.ToString()) ? dir : dir + Path.DirectorySeparatorChar); + dir = (dir.StartsWith(Path.DirectorySeparatorChar.ToString()) ? dir.Remove(0, 1) : dir); + name = dir + Path.GetFileNameWithoutExtension(name) + datdata.RepExt; + } + if (datdata.AddExt != "") + { + name += datdata.AddExt; + } + if (!datdata.UseGame && datdata.GameName) + { + name = (rom.Game.EndsWith(Path.DirectorySeparatorChar.ToString()) ? rom.Game : rom.Game + Path.DirectorySeparatorChar) + name; + } - if (datdata.UseGame && rom.Game != lastgame) - { - state += pre + name + post + "\n"; - lastgame = rom.Game; + if (datdata.UseGame && rom.Game != lastgame) + { + state += pre + name + post + "\n"; + lastgame = rom.Game; + } + else if (!datdata.UseGame) + { + state += pre + name + post + "\n"; + } } - else if (!datdata.UseGame) + break; + case OutputFormat.RomCenter: + state += "¬¬¬" + HttpUtility.HtmlEncode(rom.Game) + + "¬" + HttpUtility.HtmlEncode(rom.Game) + + "¬" + HttpUtility.HtmlEncode(rom.Name) + + "¬" + rom.CRC.ToLowerInvariant() + + "¬" + (rom.Size != -1 ? rom.Size.ToString() : "") + "¬¬¬\n"; + break; + case OutputFormat.SabreDat: + for (int i = 0; i < depth; i++) { - state += pre + name + post + "\n"; + state += "\t"; } - } - break; - case OutputFormat.RomCenter: - state += "¬¬¬" + HttpUtility.HtmlEncode(rom.Game) + - "¬" + HttpUtility.HtmlEncode(rom.Game) + - "¬" + HttpUtility.HtmlEncode(rom.Name) + - "¬" + rom.CRC.ToLowerInvariant() + - "¬" + (rom.Size != -1 ? rom.Size.ToString() : "") + "¬¬¬\n"; - break; - case OutputFormat.SabreDat: - for (int i = 0; i < depth; i++) - { - state += "\t"; - } - state += "\n"; - break; - case OutputFormat.Xml: - state += "\t\t<" + rom.Type + " name=\"" + HttpUtility.HtmlEncode(rom.Name) + "\"" + - (rom.Size != -1 ? " size=\"" + rom.Size + "\"" : "") + - (rom.CRC != "" ? " crc=\"" + rom.CRC.ToLowerInvariant() + "\"" : "") + - (rom.MD5 != "" ? " md5=\"" + rom.MD5.ToLowerInvariant() + "\"" : "") + - (rom.SHA1 != "" ? " sha1=\"" + rom.SHA1.ToLowerInvariant() + "\"" : "") + - (rom.Nodump ? " status=\"nodump\"" : "") + - "/>\n"; - break; + state += "\n"; + break; + case OutputFormat.Xml: + state += "\t\t<" + rom.Type + " name=\"" + HttpUtility.HtmlEncode(rom.Name) + "\"" + + (rom.Size != -1 ? " size=\"" + rom.Size + "\"" : "") + + (rom.CRC != "" ? " crc=\"" + rom.CRC.ToLowerInvariant() + "\"" : "") + + (rom.MD5 != "" ? " md5=\"" + rom.MD5.ToLowerInvariant() + "\"" : "") + + (rom.SHA1 != "" ? " sha1=\"" + rom.SHA1.ToLowerInvariant() + "\"" : "") + + (rom.Nodump ? " status=\"nodump\"" : "") + + "/>\n"; + break; + } } splitpath = newsplit; diff --git a/SabreHelper/RomManipulation.cs b/SabreHelper/RomManipulation.cs index 2991126f..876f1131 100644 --- a/SabreHelper/RomManipulation.cs +++ b/SabreHelper/RomManipulation.cs @@ -102,7 +102,7 @@ namespace SabreTools.Helper { // Prepare all internal variables XmlReader subreader, headreader, flagreader; - bool superdat = false, shouldbreak = false, nodump = false; + bool superdat = false, shouldbreak = false, nodump = false, empty = true; string key = "", crc = "", md5 = "", sha1 = ""; long size = -1; List parent = new List(); @@ -113,16 +113,50 @@ namespace SabreTools.Helper xtr.MoveToContent(); while (xtr.NodeType != XmlNodeType.None) { - // If we have an end folder element, remove one item from the parent, if possible - if (xtr.NodeType == XmlNodeType.EndElement && (xtr.Name == "directory" || xtr.Name == "dir") && parent.Count > 0) + // If we're ending a folder or game, take care of possibly empty games and removing from the parent + if (xtr.NodeType == XmlNodeType.EndElement && (xtr.Name == "directory" || xtr.Name == "dir")) { - parent.RemoveAt(parent.Count - 1); - if (keep) + // If we didn't find any items in the folder, make sure to add the blank rom + if (empty) { - datdata.Type = (String.IsNullOrEmpty(datdata.Type) ? "SuperDAT" : datdata.Type); + RomData rom = new RomData + { + Name = "null", + Game = String.Join("\\", parent), + Size = -1, + CRC = "null", + MD5 = "null", + SHA1 = "null", + }; + + key = rom.Size + "-" + rom.CRC; + if (datdata.Roms.ContainsKey(key)) + { + datdata.Roms[key].Add(rom); + } + else + { + List temp = new List(); + temp.Add(rom); + datdata.Roms.Add(key, temp); + } + } + + // Regardless, end the current folder + empty = true; + + // If we have an end folder element, remove one item from the parent, if possible + if (parent.Count > 0) + { + parent.RemoveAt(parent.Count - 1); + if (keep) + { + datdata.Type = (String.IsNullOrEmpty(datdata.Type) ? "SuperDAT" : datdata.Type); + } } } + // We only want elements if (xtr.NodeType != XmlNodeType.Element) { @@ -395,6 +429,8 @@ namespace SabreTools.Helper { case "rom": case "disk": + empty = false; + // If the rom is nodump, flag it nodump = false; if (xtr.GetAttribute("flags") == "nodump" || xtr.GetAttribute("status") == "nodump") @@ -498,6 +534,37 @@ namespace SabreTools.Helper } } + // If we didn't find any items in the folder, make sure to add the blank rom + if (empty) + { + tempname = (parent.Count > 0 ? String.Join("\\", parent) + Path.DirectorySeparatorChar : "") + tempname; + + RomData rom = new RomData + { + Name = "null", + Game = tempname, + Size = -1, + CRC = "null", + MD5 = "null", + SHA1 = "null", + }; + + key = rom.Size + "-" + rom.CRC; + if (datdata.Roms.ContainsKey(key)) + { + datdata.Roms[key].Add(rom); + } + else + { + List temp = new List(); + temp.Add(rom); + datdata.Roms.Add(key, temp); + } + } + + // Regardless, end the current folder + empty = true; + // Read to next game if (!xtr.ReadToNextSibling(temptype)) { @@ -521,6 +588,8 @@ namespace SabreTools.Helper xtr.Read(); break; case "file": + empty = false; + // If the rom is nodump, flag it nodump = false; flagreader = xtr.ReadSubtree();