diff --git a/Deheader/Headerer.cs b/Deheader/Headerer.cs
index 4045f417..5cf66ec0 100644
--- a/Deheader/Headerer.cs
+++ b/Deheader/Headerer.cs
@@ -22,7 +22,7 @@ namespace SabreTools
/// Start deheader operation with supplied parameters
///
/// String array representing command line parameters
- static void Main(string[] args)
+ public static void Main(string[] args)
{
// If output is being redirected, don't allow clear screens
if (!Console.IsOutputRedirected)
@@ -132,111 +132,77 @@ namespace SabreTools
/// Name of the file to be parsed
private static void DetectRemoveHeader(string file)
{
- // Open the file in read mode
- BinaryReader br = new BinaryReader(File.OpenRead(file));
-
- // Extract the first 1024 bytes of the file
- byte[] hbin = br.ReadBytes(1024);
- string header = BitConverter.ToString(hbin).Replace("-", string.Empty);
-
- // Determine the type of the file from the header, if possible
- HeaderType type = HeaderType.None;
- int headerSize = 0;
-
- // Loop over the header types and see if there's a match
- foreach (HeaderType test in Enum.GetValues(typeof(HeaderType)))
- {
- Dictionary tempDict = new Dictionary();
-
- // Try populating the dictionary from the master list
- try
- {
- tempDict = Remapping.HeaderMaps[test.ToString()];
- }
- catch
- {
- logger.Warning("The mapping for '" + test.ToString() + "' cannot be found!");
- }
-
- // Loop over the dictionary and see if there are matches
- foreach (KeyValuePair entry in tempDict)
- {
- if (Regex.IsMatch(header, entry.Key))
- {
- type = test;
- headerSize = entry.Value;
- break;
- }
- }
-
- // If we found something, break out
- if (type != HeaderType.None)
- {
- break;
- }
- }
+ // First get the HeaderType, if any
+ int headerSize = -1;
+ HeaderType type = RomTools.GetFileHeaderType(file, out headerSize, logger);
+ // If we have a valid HeaderType, remove the correct byte count
logger.User("File has header: " + (type != HeaderType.None));
-
if (type != HeaderType.None)
{
logger.Log("Deteched header type: " + type);
- int hs = headerSize;
- // Save header as string in the database
- string realhead = "";
- for (int i = 0; i < hs; i++)
+ // Now take care of the header and new output file
+ string hstr = string.Empty;
+ using (BinaryReader br = new BinaryReader(File.OpenRead(file)))
{
- realhead += BitConverter.ToString(new byte[] { hbin[i] });
+ // 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] });
+ }
}
- // Get the bytes that aren't from the header from the extracted bit so they can be written before the rest of the file
- hbin = hbin.Skip(hs).ToArray();
-
- // Write out the new file
+ // Write out the remaining bytes to new file
logger.User("Creating unheadered file: " + file + ".new");
- BinaryWriter bw = new BinaryWriter(File.OpenWrite(file + ".new"));
- FileInfo fi = new FileInfo(file);
- bw.Write(hbin);
- bw.Write(br.ReadBytes((int)fi.Length - hs));
- bw.Close();
+ Output.RemoveBytesFromFile(file, file + ".new", headerSize, 0);
logger.User("Unheadered file created!");
// Now add the information to the database if it's not already there
- SHA1 sha1 = SHA1.Create();
- sha1.ComputeHash(File.ReadAllBytes(file + ".new"));
- bool exists = false;
+ RomData rom = RomTools.GetSingleFileInfo(file + ".new");
+ AddHeaderToDatabase(hstr, rom.SHA1, type);
+ }
+ }
- string query = @"SELECT * FROM data WHERE sha1='" + BitConverter.ToString(sha1.Hash) + "' AND header='" + realhead + "'";
+ ///
+ /// Add a header to the database
+ ///
+ /// String representing the header bytes
+ /// SHA-1 of the deheadered file
+ /// HeaderType representing the detected header
+ private static void AddHeaderToDatabase(string header, string SHA1, HeaderType type)
+ {
+ bool exists = false;
+
+ string query = @"SELECT * FROM data WHERE sha1='" + SHA1 + "' AND header='" + header + "'";
+ using (SqliteConnection dbc = new SqliteConnection(_connectionString))
+ {
+ dbc.Open();
+ using (SqliteCommand slc = new SqliteCommand(query, dbc))
+ {
+ using (SqliteDataReader sldr = slc.ExecuteReader())
+ {
+ exists = sldr.HasRows;
+ }
+ }
+ }
+
+ if (!exists)
+ {
+ query = @"INSERT INTO data (sha1, header, type) VALUES ('" +
+ SHA1 + "', " +
+ "'" + header + "', " +
+ "'" + type.ToString() + "')";
using (SqliteConnection dbc = new SqliteConnection(_connectionString))
{
dbc.Open();
using (SqliteCommand slc = new SqliteCommand(query, dbc))
{
- using (SqliteDataReader sldr = slc.ExecuteReader())
- {
- exists = sldr.HasRows;
- }
- }
- }
-
- if (!exists)
- {
- query = @"INSERT INTO data (sha1, header, type) VALUES ('" +
- BitConverter.ToString(sha1.Hash) + "', " +
- "'" + realhead + "', " +
- "'" + type.ToString() + "')";
- using (SqliteConnection dbc = new SqliteConnection(_connectionString))
- {
- dbc.Open();
- using (SqliteCommand slc = new SqliteCommand(query, dbc))
- {
- logger.Log("Result of inserting header: " + slc.ExecuteNonQuery());
- }
+ logger.Log("Result of inserting header: " + slc.ExecuteNonQuery());
}
}
}
- br.Close();
}
///
@@ -246,14 +212,12 @@ namespace SabreTools
private static void ReplaceHeader(string file)
{
// First, get the SHA-1 hash of the file
- SHA1 sha1 = SHA1.Create();
- sha1.ComputeHash(File.ReadAllBytes(file));
- string hash = BitConverter.ToString(sha1.Hash);
+ RomData rom = RomTools.GetSingleFileInfo(file);
// Then try to pull the corresponding headers from the database
string header = "";
- string query = @"SELECT header, type FROM data WHERE sha1='" + hash + "'";
+ string query = @"SELECT header, type FROM data WHERE sha1='" + rom.SHA1 + "'";
using (SqliteConnection dbc = new SqliteConnection(_connectionString))
{
dbc.Open();
@@ -270,15 +234,7 @@ namespace SabreTools
header = sldr.GetString(0);
logger.User("Creating reheadered file: " + file + ".new" + sub);
- BinaryWriter bw = new BinaryWriter(File.OpenWrite(file + ".new" + sub));
-
- // Source: http://stackoverflow.com/questions/311165/how-do-you-convert-byte-array-to-hexadecimal-string-and-vice-versa
- for (int i = 0; i < header.Length; i += 2)
- {
- bw.Write(Convert.ToByte(header.Substring(i, 2), 16));
- }
- bw.Write(File.ReadAllBytes(file));
- bw.Close();
+ Output.AppendBytesToFile(file, file + ".new" + sub, header, string.Empty);
logger.User("Reheadered file created!");
}
}
diff --git a/SabreTools.Helper/Tools/Output.cs b/SabreTools.Helper/Tools/Output.cs
index e311a3f6..b0b75899 100644
--- a/SabreTools.Helper/Tools/Output.cs
+++ b/SabreTools.Helper/Tools/Output.cs
@@ -584,5 +584,116 @@ namespace SabreTools.Helper
catch { }
}
}
+
+ ///
+ /// Remove an arbitrary number of bytes from the inputted file
+ ///
+ /// File to be cropped
+ /// Outputted file
+ /// Bytes to be removed from head of file
+ /// Bytes to be removed from tail of file
+ public static void RemoveBytesFromFile(string input, string output, long bytesToRemoveFromHead, long bytesToRemoveFromTail)
+ {
+ // If any of the inputs are invalid, skip
+ if (!File.Exists(input) || new FileInfo(input).Length <= (bytesToRemoveFromHead + bytesToRemoveFromTail))
+ {
+ return;
+ }
+
+ // Read the input file and write to the fail
+ using (BinaryReader br = new BinaryReader(File.OpenRead(input)))
+ using (BinaryWriter bw = new BinaryWriter(File.OpenWrite(output)))
+ {
+ int bufferSize = 1024;
+ long adjustedLength = br.BaseStream.Length - bytesToRemoveFromTail;
+
+ // Seek to the correct position
+ br.BaseStream.Seek(bytesToRemoveFromHead, SeekOrigin.Begin);
+
+ // Now read the file in chunks and write out
+ byte[] buffer = new byte[bufferSize];
+ while (br.BaseStream.Position <= (adjustedLength - bufferSize))
+ {
+ buffer = br.ReadBytes(bufferSize);
+ bw.Write(buffer);
+ }
+
+ // For the final chunk, if any, write out only that number of bytes
+ int length = (int)(adjustedLength - br.BaseStream.Position);
+ buffer = new byte[length];
+ buffer = br.ReadBytes(length);
+ bw.Write(buffer);
+ }
+ }
+
+ ///
+ /// Add an aribtrary number of bytes to the inputted file
+ ///
+ /// File to be appended to
+ /// Outputted file
+ /// String representing bytes to be added to head of file
+ /// String representing bytes to be added to tail of file
+ public static void AppendBytesToFile(string input, string output, string bytesToAddToHead, string bytesToAddToTail)
+ {
+ // Source: http://stackoverflow.com/questions/311165/how-do-you-convert-byte-array-to-hexadecimal-string-and-vice-versa
+ byte[] bytesToAddToHeadArray = new byte[bytesToAddToHead.Length / 2];
+ for (int i = 0; i < bytesToAddToHead.Length; i += 2)
+ {
+ bytesToAddToHeadArray[i/2] = Convert.ToByte(bytesToAddToHead.Substring(i, 2), 16);
+ }
+ byte[] bytesToAddToTailArray = new byte[bytesToAddToTail.Length / 2];
+ for (int i = 0; i < bytesToAddToTail.Length; i += 2)
+ {
+ bytesToAddToTailArray[i / 2] = Convert.ToByte(bytesToAddToTail.Substring(i, 2), 16);
+ }
+
+ AppendBytesToFile(input, output, bytesToAddToHeadArray, bytesToAddToTailArray);
+ }
+
+ ///
+ /// Add an aribtrary number of bytes to the inputted file
+ ///
+ /// File to be appended to
+ /// Outputted file
+ /// Bytes to be added to head of file
+ /// Bytes to be added to tail of file
+ public static void AppendBytesToFile(string input, string output, byte[] bytesToAddToHead, byte[] bytesToAddToTail)
+ {
+ // If any of the inputs are invalid, skip
+ if (!File.Exists(input))
+ {
+ return;
+ }
+
+ using (BinaryReader br = new BinaryReader(File.OpenRead(input)))
+ using (BinaryWriter bw = new BinaryWriter(File.OpenWrite(output)))
+ {
+ if (bytesToAddToHead.Count() > 0)
+ {
+ bw.Write(bytesToAddToHead);
+ }
+
+ int bufferSize = 1024;
+
+ // Now read the file in chunks and write out
+ byte[] buffer = new byte[bufferSize];
+ while (br.BaseStream.Position <= (br.BaseStream.Length - bufferSize))
+ {
+ buffer = br.ReadBytes(bufferSize);
+ bw.Write(buffer);
+ }
+
+ // For the final chunk, if any, write out only that number of bytes
+ int length = (int)(br.BaseStream.Length - br.BaseStream.Position);
+ buffer = new byte[length];
+ buffer = br.ReadBytes(length);
+ bw.Write(buffer);
+
+ if (bytesToAddToTail.Count() > 0)
+ {
+ bw.Write(bytesToAddToTail);
+ }
+ }
+ }
}
}
diff --git a/SabreTools.Helper/Tools/RomTools.cs b/SabreTools.Helper/Tools/RomTools.cs
index 3c20cc96..d59ac89b 100644
--- a/SabreTools.Helper/Tools/RomTools.cs
+++ b/SabreTools.Helper/Tools/RomTools.cs
@@ -3,6 +3,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
+using System.Text.RegularExpressions;
namespace SabreTools.Helper
{
@@ -72,6 +73,64 @@ namespace SabreTools.Helper
return rom;
}
+ ///
+ /// 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 = Remapping.HeaderMaps[test.ToString()];
+ }
+ catch
+ {
+ logger.Warning("The mapping for '" + test.ToString() + "' cannot be found!");
+ 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;
+ }
+
///
/// Merge an arbitrary set of ROMs based on the supplied information
///