mirror of
https://github.com/claunia/SabreTools.git
synced 2025-12-16 19:14:27 +00:00
[FileTools] Remove legacy skipper information from Headerer and replace with new system
This commit is contained in:
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region DAT related
|
#region DatFile related
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines forcemerging tag for DAT output
|
/// Determines forcemerging tag for DAT output
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Rom related
|
#region DatItem related
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines which type of duplicate a file is
|
/// Determines which type of duplicate a file is
|
||||||
@@ -101,23 +101,6 @@
|
|||||||
|
|
||||||
#region Skippers and Mappers
|
#region Skippers and Mappers
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Possible detected header type
|
|
||||||
/// </summary>
|
|
||||||
public enum HeaderType
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
a7800,
|
|
||||||
fds,
|
|
||||||
lynx,
|
|
||||||
//n64,
|
|
||||||
nes,
|
|
||||||
pce,
|
|
||||||
psid,
|
|
||||||
snes,
|
|
||||||
spc,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines the header skip operation
|
/// Determines the header skip operation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ namespace SabreTools.Helper
|
|||||||
public string Author;
|
public string Author;
|
||||||
public string Version;
|
public string Version;
|
||||||
public List<SkipperRule> Rules;
|
public List<SkipperRule> Rules;
|
||||||
|
public string SourceFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -25,6 +26,7 @@ namespace SabreTools.Helper
|
|||||||
public long? EndOffset; // null if EOF
|
public long? EndOffset; // null if EOF
|
||||||
public HeaderSkipOperation Operation;
|
public HeaderSkipOperation Operation;
|
||||||
public List<SkipperTest> Tests;
|
public List<SkipperTest> Tests;
|
||||||
|
public string SourceFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -26,22 +26,6 @@ namespace SabreTools.Helper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header skippers classes represented by a dictionary of dictionaries (name, (header, size))
|
|
||||||
private static Dictionary<string, Dictionary<string, int>> _headerMaps = new Dictionary<string, Dictionary<string, int>>();
|
|
||||||
public static Dictionary<string, Dictionary<string, int>> HeaderMaps
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_headerMaps.Count == 0)
|
|
||||||
{
|
|
||||||
CreateHeaderSkips();
|
|
||||||
}
|
|
||||||
return _headerMaps;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Header Skips (new)
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Populate the entire list of header Skippers
|
/// Populate the entire list of header Skippers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -72,6 +56,7 @@ namespace SabreTools.Helper
|
|||||||
Skipper skipper = new Skipper
|
Skipper skipper = new Skipper
|
||||||
{
|
{
|
||||||
Rules = new List<SkipperRule>(),
|
Rules = new List<SkipperRule>(),
|
||||||
|
SourceFile = filename,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!File.Exists(filename))
|
if (!File.Exists(filename))
|
||||||
@@ -119,6 +104,7 @@ namespace SabreTools.Helper
|
|||||||
EndOffset = 0,
|
EndOffset = 0,
|
||||||
Operation = HeaderSkipOperation.None,
|
Operation = HeaderSkipOperation.None,
|
||||||
Tests = new List<SkipperTest>(),
|
Tests = new List<SkipperTest>(),
|
||||||
|
SourceFile = filename,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (xtr.GetAttribute("start_offset") != null)
|
if (xtr.GetAttribute("start_offset") != null)
|
||||||
@@ -686,150 +672,5 @@ namespace SabreTools.Helper
|
|||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Header Skips (old)
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create all header mappings to be used by the program
|
|
||||||
/// </summary>
|
|
||||||
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<string, int>());
|
|
||||||
SkipperHelper(skipper);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create a remapping from XML
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="skipper">Name of the header skipper to be populated</param>
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get the header type for the input file
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="input">Input file to parse for header</param>
|
|
||||||
/// <param name="hs">Passed back size of the header</param>
|
|
||||||
/// <param name="logger">Logger object for file and console output</param>
|
|
||||||
/// <returns>The detected HeaderType</returns>
|
|
||||||
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<string, int> tempDict = new Dictionary<string, int>();
|
|
||||||
|
|
||||||
// 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<string, int> 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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ namespace SabreTools.Helper
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="header">String representing the header bytes</param>
|
/// <param name="header">String representing the header bytes</param>
|
||||||
/// <param name="SHA1">SHA-1 of the deheadered file</param>
|
/// <param name="SHA1">SHA-1 of the deheadered file</param>
|
||||||
/// <param name="type">HeaderType representing the detected header</param>
|
/// <param name="type">Name of the source skipper file</param>
|
||||||
/// <param name="logger">Logger object for console and file output</param>
|
/// <param name="logger">Logger object for console and file output</param>
|
||||||
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;
|
bool exists = false;
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ namespace SabreTools.Helper
|
|||||||
query = @"INSERT INTO data (sha1, header, type) VALUES ('" +
|
query = @"INSERT INTO data (sha1, header, type) VALUES ('" +
|
||||||
SHA1 + "', " +
|
SHA1 + "', " +
|
||||||
"'" + header + "', " +
|
"'" + header + "', " +
|
||||||
"'" + type.ToString() + "')";
|
"'" + source + "')";
|
||||||
slc = new SqliteCommand(query, dbc);
|
slc = new SqliteCommand(query, dbc);
|
||||||
logger.Log("Result of inserting header: " + slc.ExecuteNonQuery());
|
logger.Log("Result of inserting header: " + slc.ExecuteNonQuery());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -207,53 +207,43 @@ namespace SabreTools.Helper
|
|||||||
|
|
||||||
logger.User("\nGetting skipper information for '" + file + "'");
|
logger.User("\nGetting skipper information for '" + file + "'");
|
||||||
|
|
||||||
// Then, if the file was headered, store it to the database
|
// Get the skipper rule that matches the file, if any
|
||||||
int headerSize = -1;
|
SkipperRule rule = Skippers.MatchesSkipper(file, "", logger);
|
||||||
HeaderType type = Skippers.GetFileHeaderType(file, out headerSize, logger);
|
|
||||||
|
|
||||||
// If we have a valid HeaderType, remove the correct byte count
|
// If we have an empty rule, return false
|
||||||
logger.User("File has header: " + (type != HeaderType.None));
|
if (rule.Tests == null || rule.Tests.Count == 0 || rule.Operation != HeaderSkipOperation.None)
|
||||||
if (type != HeaderType.None)
|
|
||||||
{
|
{
|
||||||
logger.Log("Deteched header type: " + type);
|
return false;
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user