diff --git a/SabreTools.Library/DatFiles/DatFile.cs b/SabreTools.Library/DatFiles/DatFile.cs
index 3e9f4b6a..c57ab37d 100644
--- a/SabreTools.Library/DatFiles/DatFile.cs
+++ b/SabreTools.Library/DatFiles/DatFile.cs
@@ -3705,7 +3705,7 @@ namespace SabreTools.Library.DatFiles
bool addDate, string headerToCheckAgainst)
{
Globals.Logger.Verbose("'{0}' treated like a file", Path.GetFileName(item));
- Rom rom = FileTools.GetFileInfo(item, omitFromScan: omitFromScan, date: addDate, header: headerToCheckAgainst);
+ DatItem rom = FileTools.GetFileInfo(item, omitFromScan: omitFromScan, date: addDate, header: headerToCheckAgainst);
ProcessFileHelper(item, rom, basePath, parent);
}
@@ -4211,7 +4211,7 @@ namespace SabreTools.Library.DatFiles
if (shouldExternalProcess)
{
// TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually
- Rom fileinfo = FileTools.GetFileInfo(file, omitFromScan: (quickScan ? Hash.SecureHashes : Hash.DeepHashes), header: headerToCheckAgainst);
+ DatItem fileinfo = FileTools.GetFileInfo(file, omitFromScan: (quickScan ? Hash.SecureHashes : Hash.DeepHashes), header: headerToCheckAgainst);
usedExternally = RebuildIndividualFile(fileinfo, file, outDir, tempSubDir, date, inverse, outputFormat,
romba, updateDat, null /* isZip */, headerToCheckAgainst);
}
@@ -4242,7 +4242,7 @@ namespace SabreTools.Library.DatFiles
if (entries == null && File.Exists(file))
{
// TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually
- Rom fileinfo = FileTools.GetFileInfo(file, omitFromScan: (quickScan ? Hash.SecureHashes : Hash.DeepHashes));
+ DatItem fileinfo = FileTools.GetFileInfo(file, omitFromScan: (quickScan ? Hash.SecureHashes : Hash.DeepHashes));
usedExternally = RebuildIndividualFile(fileinfo, file, outDir, tempSubDir, date, inverse, outputFormat,
romba, updateDat, null /* isZip */, headerToCheckAgainst);
}
@@ -4454,7 +4454,7 @@ namespace SabreTools.Library.DatFiles
}
// Get the item from the current file
- Rom item = FileTools.GetStreamInfo(fileStream, fileStream.Length, keepReadOpen: true);
+ Rom item = (Rom)FileTools.GetStreamInfo(fileStream, fileStream.Length, keepReadOpen: true);
item.MachineName = Style.GetFileNameWithoutExtension(item.Name);
item.MachineDescription = Style.GetFileNameWithoutExtension(item.Name);
@@ -4565,7 +4565,7 @@ namespace SabreTools.Library.DatFiles
if (rule.TransformStream(fileStream, transformStream, keepReadOpen: true, keepWriteOpen: true))
{
// Get the file informations that we will be using
- Rom headerless = FileTools.GetStreamInfo(transformStream, transformStream.Length, keepReadOpen: true);
+ Rom headerless = (Rom)FileTools.GetStreamInfo(transformStream, transformStream.Length, keepReadOpen: true);
// Find if the file has duplicates in the DAT
hasDuplicates = headerless.HasDuplicates(this);
diff --git a/SabreTools.Library/Data/Constants.cs b/SabreTools.Library/Data/Constants.cs
index a01effcb..dc6e7171 100644
--- a/SabreTools.Library/Data/Constants.cs
+++ b/SabreTools.Library/Data/Constants.cs
@@ -13,7 +13,7 @@ namespace SabreTools.Library.Data
///
/// The current toolset version to be used by all child applications
///
- public static string Version = "v0.9.8.1-" + Assembly.GetExecutingAssembly().GetLinkerTime().ToString("yyyy-MM-dd HH:mm:ss");
+ public readonly static string Version = "v0.9.8.1-" + Assembly.GetExecutingAssembly().GetLinkerTime().ToString("yyyy-MM-dd HH:mm:ss");
public const int HeaderHeight = 3;
#region 0-byte file constants
@@ -31,26 +31,36 @@ namespace SabreTools.Library.Data
#region Byte (1000-based) size comparisons
public const long KiloByte = 1000;
- public static long MegaByte = (long)Math.Pow(KiloByte, 2);
- public static long GigaByte = (long)Math.Pow(KiloByte, 3);
- public static long TeraByte = (long)Math.Pow(KiloByte, 4);
- public static long PetaByte = (long)Math.Pow(KiloByte, 5);
- public static long ExaByte = (long)Math.Pow(KiloByte, 6);
- public static long ZettaByte = (long)Math.Pow(KiloByte, 7);
- public static long YottaByte = (long)Math.Pow(KiloByte, 8);
+ public readonly static long MegaByte = (long)Math.Pow(KiloByte, 2);
+ public readonly static long GigaByte = (long)Math.Pow(KiloByte, 3);
+ public readonly static long TeraByte = (long)Math.Pow(KiloByte, 4);
+ public readonly static long PetaByte = (long)Math.Pow(KiloByte, 5);
+ public readonly static long ExaByte = (long)Math.Pow(KiloByte, 6);
+ public readonly static long ZettaByte = (long)Math.Pow(KiloByte, 7);
+ public readonly static long YottaByte = (long)Math.Pow(KiloByte, 8);
#endregion
#region Byte (1024-based) size comparisons
public const long KibiByte = 1024;
- public static long MibiByte = (long)Math.Pow(KibiByte, 2);
- public static long GibiByte = (long)Math.Pow(KibiByte, 3);
- public static long TibiByte = (long)Math.Pow(KibiByte, 4);
- public static long PibiByte = (long)Math.Pow(KibiByte, 5);
- public static long ExiByte = (long)Math.Pow(KibiByte, 6);
- public static long ZittiByte = (long)Math.Pow(KibiByte, 7);
- public static long YittiByte = (long)Math.Pow(KibiByte, 8);
+ public readonly static long MibiByte = (long)Math.Pow(KibiByte, 2);
+ public readonly static long GibiByte = (long)Math.Pow(KibiByte, 3);
+ public readonly static long TibiByte = (long)Math.Pow(KibiByte, 4);
+ public readonly static long PibiByte = (long)Math.Pow(KibiByte, 5);
+ public readonly static long ExiByte = (long)Math.Pow(KibiByte, 6);
+ public readonly static long ZittiByte = (long)Math.Pow(KibiByte, 7);
+ public readonly static long YittiByte = (long)Math.Pow(KibiByte, 8);
+
+ #endregion
+
+ #region CHD header values
+
+ public readonly static byte[] CHDSignature = { 0x4d, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x48, 0x44 }; // "MComprHD"
+ public const int CHD_HEADER_VERSION = 5;
+ public const int CHD_V3_HEADER_SIZE = 120;
+ public const int CHD_V4_HEADER_SIZE = 108;
+ public const int CHD_V5_HEADER_SIZE = 124;
#endregion
@@ -109,7 +119,7 @@ namespace SabreTools.Library.Data
0A-0B Last mod file time (0x00, 0xBC)
0C-0D Last mod file date (0x98, 0x21)
*/
- public static byte[] TorrentZipHeader = new byte[] { 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0xbc, 0x98, 0x21 };
+ public readonly static byte[] TorrentZipHeader = new byte[] { 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0xbc, 0x98, 0x21 };
/* Torrent7z Header Format
http://cpansearch.perl.org/src/BJOERN/Compress-Deflate7-1.0/7zip/DOC/7zFormat.txt
@@ -118,8 +128,8 @@ namespace SabreTools.Library.Data
06-07 ArchiveVersion (0x00, 0x03)
The rest is unknown
*/
- public static byte[] Torrent7ZipHeader = new byte[] { 0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c, 0x00, 0x03 };
- public static byte[] Torrent7ZipSignature = new byte[] { 0xa9, 0xa9, 0x9f, 0xd1, 0x57, 0x08, 0xa9, 0xd7, 0xea, 0x29, 0x64, 0xb2,
+ public readonly static byte[] Torrent7ZipHeader = new byte[] { 0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c, 0x00, 0x03 };
+ public readonly static byte[] Torrent7ZipSignature = new byte[] { 0xa9, 0xa9, 0x9f, 0xd1, 0x57, 0x08, 0xa9, 0xd7, 0xea, 0x29, 0x64, 0xb2,
0x36, 0x1b, 0x83, 0x52, 0x33, 0x00, 0x74, 0x6f, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x37, 0x7a, 0x5f, 0x30, 0x2e, 0x39, 0x62, 0x65, 0x74, 0x61 };
/* (Torrent)GZ Header Format
@@ -138,7 +148,7 @@ namespace SabreTools.Library.Data
1C-1F CRC hash
20-27 Int64 size (mirrored)
*/
- public static byte[] TorrentGZHeader = new byte[] { 0x1f, 0x8b, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00 };
+ public readonly static byte[] TorrentGZHeader = new byte[] { 0x1f, 0x8b, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00 };
#endregion
diff --git a/SabreTools.Library/Data/Enums.cs b/SabreTools.Library/Data/Enums.cs
index 32f8147a..22d6db62 100644
--- a/SabreTools.Library/Data/Enums.cs
+++ b/SabreTools.Library/Data/Enums.cs
@@ -31,6 +31,33 @@
TorrentZip64 = 45,
}
+ ///
+ /// Availible CHD codec formats
+ ///
+ public enum CHDCodecType : uint
+ {
+ CHD_CODEC_NONE = 0,
+
+ // general codecs
+ CHD_CODEC_ZLIB = 0x7a6c6962, // zlib
+ CHD_CODEC_LZMA = 0x6c7a6d61, // lzma
+ CHD_CODEC_HUFFMAN = 0x68756666, // huff
+ CHD_CODEC_FLAC = 0x666c6163, // flac
+
+ // general codecs with CD frontend
+ CHD_CODEC_CD_ZLIB = 0x63647a6c, // cdzl
+ CHD_CODEC_CD_LZMA = 0x63646c7a, // cdlz
+ CHD_CODEC_CD_FLAC = 0x6364666c, // cdfl
+
+ // A/V codecs
+ CHD_CODEC_AVHUFF = 0x61766875, // avhu
+
+ // pseudo-codecs returned by hunk_info
+ CHD_CODEC_SELF = 1, // copy of another hunk
+ CHD_CODEC_PARENT = 2, // copy of a parent's hunk
+ CHD_CODEC_MINI = 3, // legacy "mini" 8-byte repeat
+ }
+
///
/// Compression method based on flag
///
diff --git a/SabreTools.Library/External/CHDFile.cs b/SabreTools.Library/External/CHDFile.cs
new file mode 100644
index 00000000..efaf4dfe
--- /dev/null
+++ b/SabreTools.Library/External/CHDFile.cs
@@ -0,0 +1,350 @@
+using System;
+
+using SabreTools.Library.Data;
+using SabreTools.Library.Items;
+using SabreTools.Library.Tools;
+
+#if MONO
+using System.IO;
+#else
+using BinaryReader = System.IO.BinaryReader;
+using FileStream = System.IO.FileStream;
+using SeekOrigin = System.IO.SeekOrigin;
+#endif
+
+namespace SabreTools.Library.External
+{
+ ///
+ /// This is code adapted from chd.h and chd.cpp in MAME
+ ///
+ public class CHDFile
+ {
+ // core parameters from the header
+ private uint m_version; // version of the header
+ private ulong m_logicalbytes; // logical size of the raw CHD data in bytes
+ private ulong m_mapoffset; // offset of map
+ private ulong m_metaoffset; // offset to first metadata bit
+ private uint m_hunkbytes; // size of each raw hunk in bytes
+ private ulong m_hunkcount; // number of hunks represented
+ private uint m_unitbytes; // size of each unit in bytes
+ private ulong m_unitcount; // number of units represented
+ private CHDCodecType[] m_compression = new CHDCodecType[4]; // array of compression types used
+
+ // key offsets within the header
+ private long m_mapoffset_offset; // offset of map offset field
+ private long m_metaoffset_offset;// offset of metaoffset field
+ private long m_sha1_offset; // offset of SHA1 field
+ private long m_rawsha1_offset; // offset of raw SHA1 field
+ private long m_parentsha1_offset;// offset of paren SHA1 field
+
+ // map information
+ uint m_mapentrybytes; // length of each entry in a map
+
+ ///
+ /// Get internal metadata from a CHD
+ ///
+ /// Filename of possible CHD
+ /// A Disk object with internal SHA-1 on success, null on error, empty Disk otherwise
+ ///
+ /// Original code had a "writable" param. This is not required for metadata checking
+ ///
+ public DatItem GetCHDInfo(string filename)
+ {
+ FileStream fs = FileTools.TryOpenRead(filename);
+ DatItem datItem = GetCHDInfo(fs);
+ fs.Dispose();
+ return datItem;
+ }
+
+ ///
+ /// Get internal metadata from a CHD
+ ///
+ /// FileStreams of possible CHD
+ /// A Disk object with internal SHA-1 on success, null on error, empty Disk otherwise
+ ///
+ /// Original code had a "writable" param. This is not required for metadata checking
+ ///
+ public DatItem GetCHDInfo(FileStream fs)
+ {
+ // Create a blank Disk to populate and return
+ Disk datItem = new Disk();
+
+ // Get a binary reader to make life easier
+ BinaryReader br = new BinaryReader(fs);
+
+ // Read and verify the CHD signature
+ // read the raw header
+ byte[] signature = br.ReadBytes(8);
+
+ // verify the signature
+ bool correct = true;
+ for (int i = 0; i < signature.Length; i++)
+ {
+ correct &= (signature[i] == Constants.CHDSignature[i]);
+ }
+ if (!correct)
+ {
+ // throw CHDERR_INVALID_FILE;
+ return null;
+ }
+
+ // only allow writes to the most recent version
+ br.BaseStream.Seek(12, SeekOrigin.Begin);
+ m_version = br.ReadUInt32();
+
+ // read the header if we support it
+ byte[] sha1 = new byte[20];
+ switch (m_version)
+ {
+ case 3:
+ ParseV3Header(br, out sha1);
+ break;
+ case 4:
+ ParseV4Header(br, out sha1);
+ break;
+ case 5:
+ ParseV5Header(br, out sha1);
+ break;
+ default:
+ // throw CHDERR_UNSUPPORTED_VERSION;
+ return null;
+ }
+
+ datItem.SHA1 = BitConverter.ToString(sha1).Replace("-", string.Empty).ToLowerInvariant();
+
+ return datItem;
+ }
+
+ ///
+ /// Parse a CHD v3 header, populate the fields, and return the SHA-1
+ ///
+ /// BinaryReader representing the file to read
+ /// Out parameter representing the SHA-1
+ /// True if the header was parsed properly, false otherwise
+ ///
+ /// CHD v3 header layout:
+ /// 0x00-0x07 - CHD signature
+ /// 0x08-0x0B - Header size
+ /// 0x0C-0x0F - [UNUSED]
+ /// 0x10-0x13 - Flags (1: Has parent SHA-1, 2: Disallow writes)
+ /// 0x14-0x17 - Compression
+ /// 0x18-0x1B - Hunk count
+ /// 0x1C-0x23 - Logical Bytes
+ /// 0x24-0x2C - Metadata Offset
+ /// ...
+ /// 0x4C-0x4F - Hunk Bytes
+ /// 0x50-0x63 - SHA-1
+ /// 0x64-0x77 - Parent SHA-1
+ /// 0x78-0x87 - Map
+ ///
+ private bool ParseV3Header(BinaryReader br, out byte[] sha1)
+ {
+ // Set the blank SHA-1 hash
+ sha1 = null;
+
+ // Set offsets and defaults
+ m_mapoffset_offset = 0;
+ m_rawsha1_offset = 0;
+ m_mapoffset = 120;
+ m_metaoffset_offset = 36;
+ m_sha1_offset = 80;
+ m_parentsha1_offset = 100;
+ m_mapentrybytes = 16;
+
+ // Ensure the proper starting position
+ br.BaseStream.Seek(8, SeekOrigin.Begin);
+
+ // Verify header length
+ if (br.ReadInt32() != Constants.CHD_V3_HEADER_SIZE)
+ {
+ // throw CHDERR_INVALID_FILE;
+ return false;
+ }
+
+ // Skip over the 0x0C-0x0F block
+ br.ReadUInt32();
+
+ // Read the CHD flags
+ uint flags = br.ReadUInt32();
+
+ // Determine compression
+ switch (br.ReadUInt32())
+ {
+ case 0: m_compression[0] = CHDCodecType.CHD_CODEC_NONE; break;
+ case 1: m_compression[0] = CHDCodecType.CHD_CODEC_ZLIB; break;
+ case 2: m_compression[0] = CHDCodecType.CHD_CODEC_ZLIB; break;
+ case 3: m_compression[0] = CHDCodecType.CHD_CODEC_AVHUFF; break;
+ default: /* throw CHDERR_UNKNOWN_COMPRESSION; */ return false;
+ }
+
+ m_compression[1] = m_compression[2] = m_compression[3] = CHDCodecType.CHD_CODEC_NONE;
+
+ m_hunkcount = br.ReadUInt32();
+ m_logicalbytes = br.ReadUInt64();
+ m_metaoffset = br.ReadUInt64();
+
+ br.BaseStream.Seek(76, SeekOrigin.Begin);
+ m_hunkbytes = br.ReadUInt32();
+
+ br.BaseStream.Seek(m_sha1_offset, SeekOrigin.Begin);
+ sha1 = br.ReadBytes(20);
+
+ // guess at the units based on snooping the metadata
+ // m_unitbytes = guess_unitbytes();
+ m_unitcount = (m_logicalbytes + m_unitbytes - 1) / m_unitbytes;
+
+ return true;
+ }
+
+ ///
+ /// Parse a CHD v4 header, populate the fields, and return the SHA-1
+ ///
+ /// BinaryReader representing the file to read
+ /// Out parameter representing the SHA-1
+ /// True if the header was parsed properly, false otherwise
+ ///
+ /// CHD v4 header layout:
+ /// 0x00-0x07 - CHD signature
+ /// 0x08-0x0B - Header size
+ /// 0x0C-0x0F - [UNUSED]
+ /// 0x10-0x13 - Flags (1: Has parent SHA-1, 2: Disallow writes)
+ /// 0x14-0x17 - Compression
+ /// 0x18-0x1B - Hunk count
+ /// 0x1C-0x23 - Logical Bytes
+ /// 0x24-0x2C - Metadata Offset
+ /// ...
+ /// 0x2C-0x2F - Hunk Bytes
+ /// 0x30-0x43 - SHA-1
+ /// 0x44-0x57 - Parent SHA-1
+ /// 0x58-0x6b - Raw SHA-1
+ /// 0x6c-0x7b - Map
+ ///
+ private bool ParseV4Header(BinaryReader br, out byte[] sha1)
+ {
+ // Set the blank SHA-1 hash
+ sha1 = null;
+
+ // Set offsets and defaults
+ m_mapoffset_offset = 0;
+ m_metaoffset_offset = 36;
+ m_sha1_offset = 48;
+ m_parentsha1_offset = 68;
+ m_rawsha1_offset = 88;
+ m_mapoffset = 108;
+ m_mapentrybytes = 16;
+
+ // Ensure the proper starting position
+ br.BaseStream.Seek(8, SeekOrigin.Begin);
+
+ // Verify header length
+ if (br.ReadUInt32() != Constants.CHD_V4_HEADER_SIZE)
+ {
+ // throw CHDERR_INVALID_FILE;
+ return false;
+ }
+
+ // Read the CHD flags
+ uint flags = br.ReadUInt32();
+
+ // Determine compression
+ switch (br.ReadUInt32())
+ {
+ case 0: m_compression[0] = CHDCodecType.CHD_CODEC_NONE; break;
+ case 1: m_compression[0] = CHDCodecType.CHD_CODEC_ZLIB; break;
+ case 2: m_compression[0] = CHDCodecType.CHD_CODEC_ZLIB; break;
+ case 3: m_compression[0] = CHDCodecType.CHD_CODEC_AVHUFF; break;
+ default: /* throw CHDERR_UNKNOWN_COMPRESSION; */ return false;
+ }
+
+ m_compression[1] = m_compression[2] = m_compression[3] = CHDCodecType.CHD_CODEC_NONE;
+
+ m_hunkcount = br.ReadUInt32();
+ m_logicalbytes = br.ReadUInt64();
+ m_metaoffset = br.ReadUInt64();
+
+ br.BaseStream.Seek(44, SeekOrigin.Begin);
+ m_hunkbytes = br.ReadUInt32();
+
+ br.BaseStream.Seek(m_sha1_offset, SeekOrigin.Begin);
+ sha1 = br.ReadBytes(20);
+
+ // guess at the units based on snooping the metadata
+ // m_unitbytes = guess_unitbytes();
+ m_unitcount = (m_logicalbytes + m_unitbytes - 1) / m_unitbytes;
+
+ return true;
+ }
+
+ ///
+ /// Parse a CHD v5 header, populate the fields, and return the SHA-1
+ ///
+ /// BinaryReader representing the file to read
+ /// Out parameter representing the SHA-1
+ /// True if the header was parsed properly, false otherwise
+ ///
+ /// CHD v5 header layout:
+ /// 0x00-0x07 - CHD signature
+ /// 0x08-0x0B - Header size
+ /// 0x0C-0x0F - [UNUSED]
+ /// 0x10-0x13 - Compression format 1
+ /// 0x14-0x17 - Compression format 2
+ /// 0x18-0x1B - Compression format 3
+ /// 0x1C-0x1F - Compression format 4
+ /// 0x18-0x1B - Hunk count
+ /// 0x20-0x27 - Logical Bytes
+ /// 0x28-0x2F - Map Offset
+ /// 0x30-0x37 - Metadata Offset
+ /// 0x38-0x3B - Hunk Bytes
+ /// 0x3C-0x3F - Unit Bytes
+ /// 0x40-0x53 - Raw SHA-1
+ /// 0x54-0x67 - SHA-1
+ /// 0x68-0x7b - Parent SHA-1
+ ///
+ private bool ParseV5Header(BinaryReader br, out byte[] sha1)
+ {
+ // Set the blank SHA-1 hash
+ sha1 = null;
+
+ // Set offsets and defaults
+ m_mapoffset_offset = 40;
+ m_metaoffset_offset = 48;
+ m_rawsha1_offset = 64;
+ m_sha1_offset = 84;
+ m_parentsha1_offset = 104;
+
+ // Ensure the proper starting position
+ br.BaseStream.Seek(8, SeekOrigin.Begin);
+
+ // Verify header length
+ if (br.ReadUInt32() != Constants.CHD_V5_HEADER_SIZE)
+ {
+ // throw CHDERR_INVALID_FILE
+ return false;
+ }
+
+ // Determine compression
+ m_compression[0] = (CHDCodecType)br.ReadUInt32();
+ m_compression[1] = (CHDCodecType)br.ReadUInt32();
+ m_compression[2] = (CHDCodecType)br.ReadUInt32();
+ m_compression[3] = (CHDCodecType)br.ReadUInt32();
+
+ m_logicalbytes = br.ReadUInt64();
+ m_mapoffset = br.ReadUInt64();
+ m_metaoffset = br.ReadUInt64();
+ m_hunkbytes = br.ReadUInt32();
+ m_hunkcount = (m_logicalbytes + m_hunkbytes - 1) / m_hunkbytes;
+ m_unitbytes = br.ReadUInt32();
+ m_unitcount = (m_logicalbytes + m_unitbytes - 1) / m_unitbytes;
+
+ // m_allow_writes = !compressed();
+
+ // determine properties of map entries
+ // m_mapentrybytes = compressed() ? 12 : 4;
+
+ br.BaseStream.Seek(m_sha1_offset, SeekOrigin.Begin);
+ sha1 = br.ReadBytes(20);
+
+ return true;
+ }
+ }
+}
diff --git a/SabreTools.Library/SabreTools.Library.csproj b/SabreTools.Library/SabreTools.Library.csproj
index 1cc1a3f3..54fff118 100644
--- a/SabreTools.Library/SabreTools.Library.csproj
+++ b/SabreTools.Library/SabreTools.Library.csproj
@@ -130,6 +130,7 @@
+
diff --git a/SabreTools.Library/Tools/ArchiveTools.cs b/SabreTools.Library/Tools/ArchiveTools.cs
index 15022e15..c267ee48 100644
--- a/SabreTools.Library/Tools/ArchiveTools.cs
+++ b/SabreTools.Library/Tools/ArchiveTools.cs
@@ -644,7 +644,7 @@ namespace SabreTools.Library.Tools
else
{
Stream entryStream = entry.OpenEntryStream();
- Rom sevenZipEntryRom = FileTools.GetStreamInfo(entryStream, entry.Size, omitFromScan: omitFromScan);
+ Rom sevenZipEntryRom = (Rom)FileTools.GetStreamInfo(entryStream, entry.Size, omitFromScan: omitFromScan);
sevenZipEntryRom.Name = entry.Key;
sevenZipEntryRom.MachineName = gamename;
sevenZipEntryRom.Date = (date && entry.LastModifiedTime != null ? entry.LastModifiedTime?.ToString("yyyy/MM/dd hh:mm:ss") : null);
@@ -677,7 +677,7 @@ namespace SabreTools.Library.Tools
else
{
GZipStream gzstream = new GZipStream(FileTools.TryOpenRead(input), Ionic.Zlib.CompressionMode.Decompress);
- Rom gzipEntryRom = FileTools.GetStreamInfo(gzstream, gzstream.Length, omitFromScan: omitFromScan);
+ Rom gzipEntryRom = (Rom)FileTools.GetStreamInfo(gzstream, gzstream.Length, omitFromScan: omitFromScan);
gzipEntryRom.Name = gzstream.FileName;
gzipEntryRom.MachineName = gamename;
gzipEntryRom.Date = (date && gzstream.LastModified != null ? gzstream.LastModified?.ToString("yyyy/MM/dd hh:mm:ss") : null);
@@ -709,7 +709,7 @@ namespace SabreTools.Library.Tools
else
{
Stream entryStream = entry.OpenEntryStream();
- Rom rarEntryRom = FileTools.GetStreamInfo(entryStream, entry.Size, omitFromScan: omitFromScan);
+ Rom rarEntryRom = (Rom)FileTools.GetStreamInfo(entryStream, entry.Size, omitFromScan: omitFromScan);
rarEntryRom.Name = entry.Key;
rarEntryRom.MachineName = gamename;
rarEntryRom.Date = entry.LastModifiedTime?.ToString("yyyy/MM/dd hh:mm:ss");
@@ -745,7 +745,7 @@ namespace SabreTools.Library.Tools
else
{
Stream entryStream = entry.OpenEntryStream();
- Rom tarEntryRom = FileTools.GetStreamInfo(entryStream, entry.Size, omitFromScan: omitFromScan);
+ Rom tarEntryRom = (Rom)FileTools.GetStreamInfo(entryStream, entry.Size, omitFromScan: omitFromScan);
tarEntryRom.Name = entry.Key;
tarEntryRom.MachineName = gamename;
tarEntryRom.Date = entry.LastModifiedTime?.ToString("yyyy/MM/dd hh:mm:ss");
@@ -802,7 +802,7 @@ namespace SabreTools.Library.Tools
// Otherwise, use the stream directly
else
{
- Rom zipEntryRom = FileTools.GetStreamInfo(readStream, (long)zf.Entries[i].UncompressedSize, omitFromScan: omitFromScan);
+ Rom zipEntryRom = (Rom)FileTools.GetStreamInfo(readStream, (long)zf.Entries[i].UncompressedSize, omitFromScan: omitFromScan);
zipEntryRom.Name = zf.Entries[i].FileName;
zipEntryRom.MachineName = gamename;
string convertedDate = Style.ConvertMsDosTimeFormatToDateTime(zf.Entries[i].LastMod).ToString("yyyy/MM/dd hh:mm:ss");
@@ -2216,7 +2216,7 @@ namespace SabreTools.Library.Tools
outDir = Path.GetFullPath(outDir);
// Now get the Rom info for the file so we have hashes and size
- Rom rom = FileTools.GetStreamInfo(inputStream, inputStream.Length, keepReadOpen: true);
+ Rom rom = (Rom)FileTools.GetStreamInfo(inputStream, inputStream.Length, keepReadOpen: true);
// Get the output file name
string outfile = null;
diff --git a/SabreTools.Library/Tools/FileTools.cs b/SabreTools.Library/Tools/FileTools.cs
index 55d1cff5..29ba850e 100644
--- a/SabreTools.Library/Tools/FileTools.cs
+++ b/SabreTools.Library/Tools/FileTools.cs
@@ -216,7 +216,7 @@ namespace SabreTools.Library.Tools
///
/// TODO: Add CHD parsing logic here to get internal hash data
///
- public static Rom GetFileInfo(string input, Hash omitFromScan = 0x0,
+ public static DatItem GetFileInfo(string input, Hash omitFromScan = 0x0,
long offset = 0, bool date = false, string header = null)
{
// Add safeguard if file doesn't exist
@@ -240,7 +240,7 @@ namespace SabreTools.Library.Tools
// Transform the stream and get the information from it
rule.TransformStream(inputStream, outputStream, keepReadOpen: false, keepWriteOpen: true);
- rom = GetStreamInfo(outputStream, outputStream.Length, omitFromScan: omitFromScan, keepReadOpen: false);
+ rom = (Rom)GetStreamInfo(outputStream, outputStream.Length, omitFromScan: omitFromScan, keepReadOpen: false);
// Dispose of the streams
outputStream.Dispose();
@@ -250,13 +250,13 @@ namespace SabreTools.Library.Tools
else
{
long length = new FileInfo(input).Length;
- rom = GetStreamInfo(TryOpenRead(input), length, omitFromScan, offset, false);
+ rom = (Rom)GetStreamInfo(TryOpenRead(input), length, omitFromScan, offset, false);
}
}
else
{
long length = new FileInfo(input).Length;
- rom = GetStreamInfo(TryOpenRead(input), length, omitFromScan, offset, false);
+ rom = (Rom)GetStreamInfo(TryOpenRead(input), length, omitFromScan, offset, false);
}
// Add unique data from the file
@@ -409,7 +409,7 @@ namespace SabreTools.Library.Tools
}
// Now add the information to the database if it's not already there
- Rom rom = GetFileInfo(newfile);
+ Rom rom = (Rom)GetFileInfo(newfile);
DatabaseTools.AddHeaderToDatabase(hstr, rom.SHA1, rule.SourceFile);
return true;
@@ -508,7 +508,7 @@ namespace SabreTools.Library.Tools
}
// First, get the SHA-1 hash of the file
- Rom rom = GetFileInfo(file);
+ Rom rom = (Rom)GetFileInfo(file);
// Retrieve a list of all related headers from the database
List headers = DatabaseTools.RetrieveHeadersFromDatabase(rom.SHA1);
@@ -733,7 +733,7 @@ namespace SabreTools.Library.Tools
/// Set a >0 number for getting hash for part of the file, 0 otherwise (default)
/// True if the underlying read stream should be kept open, false otherwise
/// Populated DatItem object if success, empty one on error
- public static Rom GetStreamInfo(Stream input, long size, Hash omitFromScan = 0x0,
+ public static DatItem GetStreamInfo(Stream input, long size, Hash omitFromScan = 0x0,
long offset = 0, bool keepReadOpen = false)
{
Rom rom = new Rom