diff --git a/SabreTools.Helper/Data/Enums.cs b/SabreTools.Helper/Data/Enums.cs index 8249b2dd..9a4dfc40 100644 --- a/SabreTools.Helper/Data/Enums.cs +++ b/SabreTools.Helper/Data/Enums.cs @@ -21,7 +21,7 @@ #endregion - #region DAT related + #region DatFile related /// /// Determines forcemerging tag for DAT output @@ -56,7 +56,7 @@ #endregion - #region Rom related + #region DatItem related /// /// Determines which type of duplicate a file is @@ -101,23 +101,6 @@ #region Skippers and Mappers - /// - /// Possible detected header type - /// - public enum HeaderType - { - None = 0, - a7800, - fds, - lynx, - //n64, - nes, - pce, - psid, - snes, - spc, - } - /// /// Determines the header skip operation /// diff --git a/SabreTools.Helper/Data/Structs.cs b/SabreTools.Helper/Data/Structs.cs index 60eb1c3c..6184b37f 100644 --- a/SabreTools.Helper/Data/Structs.cs +++ b/SabreTools.Helper/Data/Structs.cs @@ -14,6 +14,7 @@ namespace SabreTools.Helper public string Author; public string Version; public List Rules; + public string SourceFile; } /// @@ -25,6 +26,7 @@ namespace SabreTools.Helper public long? EndOffset; // null if EOF public HeaderSkipOperation Operation; public List Tests; + public string SourceFile; } /// diff --git a/SabreTools.Helper/Skippers/Skippers.cs b/SabreTools.Helper/Skippers/Skippers.cs index e463674b..345fef26 100644 --- a/SabreTools.Helper/Skippers/Skippers.cs +++ b/SabreTools.Helper/Skippers/Skippers.cs @@ -26,22 +26,6 @@ namespace SabreTools.Helper } } - // Header skippers classes represented by a dictionary of dictionaries (name, (header, size)) - private static Dictionary> _headerMaps = new Dictionary>(); - public static Dictionary> HeaderMaps - { - get - { - if (_headerMaps.Count == 0) - { - CreateHeaderSkips(); - } - return _headerMaps; - } - } - - #region Header Skips (new) - /// /// Populate the entire list of header Skippers /// @@ -72,6 +56,7 @@ namespace SabreTools.Helper Skipper skipper = new Skipper { Rules = new List(), + SourceFile = filename, }; if (!File.Exists(filename)) @@ -119,6 +104,7 @@ namespace SabreTools.Helper EndOffset = 0, Operation = HeaderSkipOperation.None, Tests = new List(), + SourceFile = filename, }; if (xtr.GetAttribute("start_offset") != null) @@ -686,150 +672,5 @@ namespace SabreTools.Helper return success; } - - #endregion - - #region Header Skips (old) - - /// - /// Create all header mappings to be used by the program - /// - private static void CreateHeaderSkips() - { - // Create array of dictionary names - string[] skippers = - { - "a7800", "fds", "lynx", /* "n64", */ "nes", "pce", "psid", "snes", "spc", - }; - - // Loop through and add all remappings - foreach (string skipper in skippers) - { - _headerMaps.Add(skipper, new Dictionary()); - SkipperHelper(skipper); - } - } - - /// - /// Create a remapping from XML - /// - /// Name of the header skipper to be populated - private static void SkipperHelper(string skipper) - { - // Read in remapping from file - XmlDocument doc = new XmlDocument(); - try - { - doc.LoadXml(File.ReadAllText(Path.Combine(LocalPath, skipper + ".xml"))); - } - catch (XmlException ex) - { - Console.WriteLine(skipper + " header skippers could not be loaded! " + ex.ToString()); - return; - } - - // Get the detector parent node - XmlNode node = doc.FirstChild; - while (node.Name != "detector") - { - node = node.NextSibling; - } - - // Get the first rule node - node = node.SelectSingleNode("rule"); - - // Now read in the rules - while (node != null && node.Name == "rule") - { - // Size is the offset for the actual game data - int size = (node.Attributes["start_offset"] != null ? Convert.ToInt32(node.Attributes["start_offset"].Value, 16) : 0); - - // Each rule set can have more than one data rule. We can't really use multiples right now - if (node.SelectNodes("data") != null) - { - foreach (XmlNode child in node.SelectNodes("data")) - { - // Add an offset to the match if one exists - string header = (child.Attributes["offset"] != null && child.Attributes["offset"].Value != "0" ? "^.{" + (Convert.ToInt32(child.Attributes["offset"].Value, 16) * 2) + "}" : "^"); - header += child.Attributes["value"].Value; - - // Now add the header and value to the appropriate skipper dictionary - _headerMaps[skipper].Add(header, size); - } - } - - // Get the next node and skip over anything that's not an element - node = node.NextSibling; - - if (node == null) - { - break; - } - - while (node.NodeType != XmlNodeType.Element && node.Name != "rule") - { - node = node.NextSibling; - } - } - } - - /// - /// Get the header type for the input file - /// - /// Input file to parse for header - /// Passed back size of the header - /// Logger object for file and console output - /// The detected HeaderType - public static HeaderType GetFileHeaderType(string input, out int hs, Logger logger) - { - // Open the file in read mode - BinaryReader br = new BinaryReader(File.OpenRead(input)); - - // Extract the first 1024 bytes of the file - byte[] hbin = br.ReadBytes(1024); - string header = BitConverter.ToString(hbin).Replace("-", string.Empty); - br.Dispose(); - - // Determine the type of the file from the header, if possible - HeaderType type = HeaderType.None; - - // Loop over the header types and see if there's a match - hs = -1; - foreach (HeaderType test in Enum.GetValues(typeof(HeaderType))) - { - Dictionary tempDict = new Dictionary(); - - // Try populating the dictionary from the master list - try - { - tempDict = Skippers.HeaderMaps[test.ToString()]; - } - catch - { - continue; - } - - // Loop over the dictionary and see if there are matches - foreach (KeyValuePair entry in tempDict) - { - if (Regex.IsMatch(header, entry.Key)) - { - type = test; - hs = entry.Value; - break; - } - } - - // If we found something, break out - if (type != HeaderType.None) - { - break; - } - } - - return type; - } - - #endregion } } diff --git a/SabreTools.Helper/Tools/DatabaseTools.cs b/SabreTools.Helper/Tools/DatabaseTools.cs index 754cd93a..a3083ac9 100644 --- a/SabreTools.Helper/Tools/DatabaseTools.cs +++ b/SabreTools.Helper/Tools/DatabaseTools.cs @@ -14,9 +14,9 @@ namespace SabreTools.Helper /// /// String representing the header bytes /// SHA-1 of the deheadered file - /// HeaderType representing the detected header + /// Name of the source skipper file /// Logger object for console and file output - public static void AddHeaderToDatabase(string header, string SHA1, HeaderType type, Logger logger) + public static void AddHeaderToDatabase(string header, string SHA1, string source, Logger logger) { bool exists = false; @@ -34,7 +34,7 @@ namespace SabreTools.Helper query = @"INSERT INTO data (sha1, header, type) VALUES ('" + SHA1 + "', " + "'" + header + "', " + - "'" + type.ToString() + "')"; + "'" + source + "')"; slc = new SqliteCommand(query, dbc); logger.Log("Result of inserting header: " + slc.ExecuteNonQuery()); } diff --git a/SabreTools.Helper/Tools/FileTools.cs b/SabreTools.Helper/Tools/FileTools.cs index aee7f2b0..1296a52e 100644 --- a/SabreTools.Helper/Tools/FileTools.cs +++ b/SabreTools.Helper/Tools/FileTools.cs @@ -207,53 +207,43 @@ namespace SabreTools.Helper logger.User("\nGetting skipper information for '" + file + "'"); - // Then, if the file was headered, store it to the database - int headerSize = -1; - HeaderType type = Skippers.GetFileHeaderType(file, out headerSize, logger); + // Get the skipper rule that matches the file, if any + SkipperRule rule = Skippers.MatchesSkipper(file, "", logger); - // If we have a valid HeaderType, remove the correct byte count - logger.User("File has header: " + (type != HeaderType.None)); - if (type != HeaderType.None) + // If we have an empty rule, return false + if (rule.Tests == null || rule.Tests.Count == 0 || rule.Operation != HeaderSkipOperation.None) { - logger.Log("Deteched header type: " + type); - - // Now take care of the header and new output file - string hstr = string.Empty; - BinaryReader br = new BinaryReader(File.OpenRead(file)); - - // Extract the header as a string for the database - byte[] hbin = br.ReadBytes(headerSize); - for (int i = 0; i < headerSize; i++) - { - hstr += BitConverter.ToString(new byte[] { hbin[i] }); - } - - br.Dispose(); - - // Then find an apply the exact rule to the file - SkipperRule rule = Skippers.MatchesSkipper(file, "", logger); - - // If we have an empty rule, return false - if (rule.Tests == null || rule.Tests.Count == 0) - { - return false; - } - - // Otherwise, apply the rule to the file - string newfile = (outDir == "" ? Path.GetFullPath(file) + ".new" : Path.Combine(outDir, Path.GetFileName(file))); - Skippers.TransformFile(file, newfile, rule, logger); - - // If the output file doesn't exist, return false - if (!File.Exists(newfile)) - { - return false; - } - - // Now add the information to the database if it's not already there - Rom rom = GetSingleFileInfo(newfile); - DatabaseTools.AddHeaderToDatabase(hstr, rom.SHA1, type, logger); + return false; } + logger.User("File has a valid copier header"); + + // Get the header bytes from the file first + string hstr = string.Empty; + BinaryReader br = new BinaryReader(File.OpenRead(file)); + + // Extract the header as a string for the database + byte[] hbin = br.ReadBytes((int)rule.StartOffset); + for (int i = 0; i < (int)rule.StartOffset; i++) + { + hstr += BitConverter.ToString(new byte[] { hbin[i] }); + } + br.Dispose(); + + // Apply the rule to the file + string newfile = (outDir == "" ? Path.GetFullPath(file) + ".new" : Path.Combine(outDir, Path.GetFileName(file))); + Skippers.TransformFile(file, newfile, rule, logger); + + // If the output file doesn't exist, return false + if (!File.Exists(newfile)) + { + return false; + } + + // Now add the information to the database if it's not already there + Rom rom = GetSingleFileInfo(newfile); + DatabaseTools.AddHeaderToDatabase(hstr, rom.SHA1, rule.SourceFile, logger); + return true; }