mirror of
https://github.com/claunia/SabreTools.git
synced 2025-12-16 19:14:27 +00:00
[Headerer] Modularize Headerer and port some core features to the DLL
This commit is contained in:
@@ -22,7 +22,7 @@ namespace SabreTools
|
|||||||
/// Start deheader operation with supplied parameters
|
/// Start deheader operation with supplied parameters
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="args">String array representing command line parameters</param>
|
/// <param name="args">String array representing command line parameters</param>
|
||||||
static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
// If output is being redirected, don't allow clear screens
|
// If output is being redirected, don't allow clear screens
|
||||||
if (!Console.IsOutputRedirected)
|
if (!Console.IsOutputRedirected)
|
||||||
@@ -132,82 +132,50 @@ namespace SabreTools
|
|||||||
/// <param name="file">Name of the file to be parsed</param>
|
/// <param name="file">Name of the file to be parsed</param>
|
||||||
private static void DetectRemoveHeader(string file)
|
private static void DetectRemoveHeader(string file)
|
||||||
{
|
{
|
||||||
// Open the file in read mode
|
// First get the HeaderType, if any
|
||||||
BinaryReader br = new BinaryReader(File.OpenRead(file));
|
int headerSize = -1;
|
||||||
|
HeaderType type = RomTools.GetFileHeaderType(file, out headerSize, logger);
|
||||||
// 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<string, int> tempDict = new Dictionary<string, int>();
|
|
||||||
|
|
||||||
// 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<string, int> 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// If we have a valid HeaderType, remove the correct byte count
|
||||||
logger.User("File has header: " + (type != HeaderType.None));
|
logger.User("File has header: " + (type != HeaderType.None));
|
||||||
|
|
||||||
if (type != HeaderType.None)
|
if (type != HeaderType.None)
|
||||||
{
|
{
|
||||||
logger.Log("Deteched header type: " + type);
|
logger.Log("Deteched header type: " + type);
|
||||||
int hs = headerSize;
|
|
||||||
|
|
||||||
// Save header as string in the database
|
// Now take care of the header and new output file
|
||||||
string realhead = "";
|
string hstr = string.Empty;
|
||||||
for (int i = 0; i < hs; i++)
|
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
|
// Write out the remaining bytes to new file
|
||||||
hbin = hbin.Skip(hs).ToArray();
|
|
||||||
|
|
||||||
// Write out the new file
|
|
||||||
logger.User("Creating unheadered file: " + file + ".new");
|
logger.User("Creating unheadered file: " + file + ".new");
|
||||||
BinaryWriter bw = new BinaryWriter(File.OpenWrite(file + ".new"));
|
Output.RemoveBytesFromFile(file, file + ".new", headerSize, 0);
|
||||||
FileInfo fi = new FileInfo(file);
|
|
||||||
bw.Write(hbin);
|
|
||||||
bw.Write(br.ReadBytes((int)fi.Length - hs));
|
|
||||||
bw.Close();
|
|
||||||
logger.User("Unheadered file created!");
|
logger.User("Unheadered file created!");
|
||||||
|
|
||||||
// Now add the information to the database if it's not already there
|
// Now add the information to the database if it's not already there
|
||||||
SHA1 sha1 = SHA1.Create();
|
RomData rom = RomTools.GetSingleFileInfo(file + ".new");
|
||||||
sha1.ComputeHash(File.ReadAllBytes(file + ".new"));
|
AddHeaderToDatabase(hstr, rom.SHA1, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a header to the database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="header">String representing the header bytes</param>
|
||||||
|
/// <param name="SHA1">SHA-1 of the deheadered file</param>
|
||||||
|
/// <param name="type">HeaderType representing the detected header</param>
|
||||||
|
private static void AddHeaderToDatabase(string header, string SHA1, HeaderType type)
|
||||||
|
{
|
||||||
bool exists = false;
|
bool exists = false;
|
||||||
|
|
||||||
string query = @"SELECT * FROM data WHERE sha1='" + BitConverter.ToString(sha1.Hash) + "' AND header='" + realhead + "'";
|
string query = @"SELECT * FROM data WHERE sha1='" + SHA1 + "' AND header='" + header + "'";
|
||||||
using (SqliteConnection dbc = new SqliteConnection(_connectionString))
|
using (SqliteConnection dbc = new SqliteConnection(_connectionString))
|
||||||
{
|
{
|
||||||
dbc.Open();
|
dbc.Open();
|
||||||
@@ -223,8 +191,8 @@ namespace SabreTools
|
|||||||
if (!exists)
|
if (!exists)
|
||||||
{
|
{
|
||||||
query = @"INSERT INTO data (sha1, header, type) VALUES ('" +
|
query = @"INSERT INTO data (sha1, header, type) VALUES ('" +
|
||||||
BitConverter.ToString(sha1.Hash) + "', " +
|
SHA1 + "', " +
|
||||||
"'" + realhead + "', " +
|
"'" + header + "', " +
|
||||||
"'" + type.ToString() + "')";
|
"'" + type.ToString() + "')";
|
||||||
using (SqliteConnection dbc = new SqliteConnection(_connectionString))
|
using (SqliteConnection dbc = new SqliteConnection(_connectionString))
|
||||||
{
|
{
|
||||||
@@ -236,8 +204,6 @@ namespace SabreTools
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
br.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Detect and replace header(s) to the given file
|
/// Detect and replace header(s) to the given file
|
||||||
@@ -246,14 +212,12 @@ namespace SabreTools
|
|||||||
private static void ReplaceHeader(string file)
|
private static void ReplaceHeader(string file)
|
||||||
{
|
{
|
||||||
// First, get the SHA-1 hash of the file
|
// First, get the SHA-1 hash of the file
|
||||||
SHA1 sha1 = SHA1.Create();
|
RomData rom = RomTools.GetSingleFileInfo(file);
|
||||||
sha1.ComputeHash(File.ReadAllBytes(file));
|
|
||||||
string hash = BitConverter.ToString(sha1.Hash);
|
|
||||||
|
|
||||||
// Then try to pull the corresponding headers from the database
|
// Then try to pull the corresponding headers from the database
|
||||||
string header = "";
|
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))
|
using (SqliteConnection dbc = new SqliteConnection(_connectionString))
|
||||||
{
|
{
|
||||||
dbc.Open();
|
dbc.Open();
|
||||||
@@ -270,15 +234,7 @@ namespace SabreTools
|
|||||||
header = sldr.GetString(0);
|
header = sldr.GetString(0);
|
||||||
|
|
||||||
logger.User("Creating reheadered file: " + file + ".new" + sub);
|
logger.User("Creating reheadered file: " + file + ".new" + sub);
|
||||||
BinaryWriter bw = new BinaryWriter(File.OpenWrite(file + ".new" + sub));
|
Output.AppendBytesToFile(file, file + ".new" + sub, header, string.Empty);
|
||||||
|
|
||||||
// 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();
|
|
||||||
logger.User("Reheadered file created!");
|
logger.User("Reheadered file created!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -584,5 +584,116 @@ namespace SabreTools.Helper
|
|||||||
catch { }
|
catch { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove an arbitrary number of bytes from the inputted file
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">File to be cropped</param>
|
||||||
|
/// <param name="output">Outputted file</param>
|
||||||
|
/// <param name="bytesToRemoveFromHead">Bytes to be removed from head of file</param>
|
||||||
|
/// <param name="bytesToRemoveFromTail">Bytes to be removed from tail of file</param>
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add an aribtrary number of bytes to the inputted file
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">File to be appended to</param>
|
||||||
|
/// <param name="output">Outputted file</param>
|
||||||
|
/// <param name="bytesToAddToHead">String representing bytes to be added to head of file</param>
|
||||||
|
/// <param name="bytesToAddToTail">String representing bytes to be added to tail of file</param>
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add an aribtrary number of bytes to the inputted file
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">File to be appended to</param>
|
||||||
|
/// <param name="output">Outputted file</param>
|
||||||
|
/// <param name="bytesToAddToHead">Bytes to be added to head of file</param>
|
||||||
|
/// <param name="bytesToAddToTail">Bytes to be added to tail of file</param>
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace SabreTools.Helper
|
namespace SabreTools.Helper
|
||||||
{
|
{
|
||||||
@@ -72,6 +73,64 @@ namespace SabreTools.Helper
|
|||||||
return rom;
|
return rom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <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 = 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<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;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Merge an arbitrary set of ROMs based on the supplied information
|
/// Merge an arbitrary set of ROMs based on the supplied information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user