diff --git a/SabreTools.Library/FileTypes/CHDFile.cs b/SabreTools.Library/FileTypes/CHDFile.cs
index d95cb821..8c543c9f 100644
--- a/SabreTools.Library/FileTypes/CHDFile.cs
+++ b/SabreTools.Library/FileTypes/CHDFile.cs
@@ -1,7 +1,4 @@
-using System;
-using System.Linq;
-
-using SabreTools.Library.Data;
+using SabreTools.Library.Data;
using SabreTools.Library.Tools;
#if MONO
@@ -88,7 +85,7 @@ namespace SabreTools.Library.FileTypes
/// 0x68-0x7b - Parent SHA-1
/// ----------------------------------------------
///
- public class CHDFile : BaseFile, IDisposable
+ public class CHDFile : BaseFile
{
#region Private instance variables
@@ -110,12 +107,61 @@ namespace SabreTools.Library.FileTypes
private uint m_mapentrybytes; // length of each entry in a map
// additional required vars
+ private uint? _headerVersion;
private BinaryReader m_br; // Binary reader representing the CHD stream
#endregion
+ #region Pubically facing variables
+
+ public uint? Version
+ {
+ get
+ {
+ if (_headerVersion == null)
+ {
+ _headerVersion = ValidateHeaderVersion();
+ }
+
+ return _headerVersion;
+ }
+ }
+
+ #endregion
+
#region Constructors
+ ///
+ /// Create a new, blank CHDFile
+ ///
+ public CHDFile()
+ {
+ this._fileType = FileType.CHD;
+ }
+
+ ///
+ /// Create a new CHDFile from an input file
+ ///
+ ///
+ public CHDFile(string filename)
+ : base(filename)
+ {
+ _fileType = FileType.CHD;
+ m_br = new BinaryReader(Utilities.TryOpenRead(filename));
+
+ _headerVersion = ValidateHeaderVersion();
+
+ byte[] hash = GetHashFromHeader();
+ if (hash.Length == Constants.MD5Length)
+ {
+ _md5 = hash;
+ }
+ else if (hash.Length == Constants.SHA1Length)
+ {
+ _sha1 = hash;
+ }
+ }
+
///
/// Create a new CHDFile from an input stream
///
@@ -124,14 +170,18 @@ namespace SabreTools.Library.FileTypes
{
_fileType = FileType.CHD;
m_br = new BinaryReader(chdstream);
- }
- ///
- /// Dispose of the CHDFile
- ///
- public void Dispose()
- {
- m_br.Dispose();
+ _headerVersion = ValidateHeaderVersion();
+
+ byte[] hash = GetHashFromHeader();
+ if (hash.Length == Constants.MD5Length)
+ {
+ _md5 = hash;
+ }
+ else if (hash.Length == Constants.SHA1Length)
+ {
+ _sha1 = hash;
+ }
}
#endregion
@@ -142,50 +192,57 @@ namespace SabreTools.Library.FileTypes
/// Validate the initial signature, version, and header size
///
/// Unsigned int containing the version number, null if invalid
- public uint? ValidateHeaderVersion()
+ private uint? ValidateHeaderVersion()
{
- // Seek to the beginning to make sure we're reading the correct bytes
- m_br.BaseStream.Seek(0, SeekOrigin.Begin);
+ try
+ {
+ // Seek to the beginning to make sure we're reading the correct bytes
+ m_br.BaseStream.Seek(0, SeekOrigin.Begin);
- // Read and verify the CHD signature
- m_signature = m_br.ReadBytes(8);
+ // Read and verify the CHD signature
+ m_signature = m_br.ReadBytes(8);
- // If no signature could be read, return null
- if (m_signature == null || m_signature.Length == 0)
+ // If no signature could be read, return null
+ if (m_signature == null || m_signature.Length == 0)
+ {
+ return null;
+ }
+
+ if (!m_signature.StartsWith(Constants.CHDSignature, exact: true))
+ {
+ // throw CHDERR_INVALID_FILE;
+ return null;
+ }
+
+ // Get the header size and version
+ m_headersize = m_br.ReadUInt32Reverse();
+ m_version = m_br.ReadUInt32Reverse();
+
+ // If we have an invalid combination of size and version
+ if ((m_version == 1 && m_headersize != Constants.CHD_V1_HEADER_SIZE)
+ || (m_version == 2 && m_headersize != Constants.CHD_V2_HEADER_SIZE)
+ || (m_version == 3 && m_headersize != Constants.CHD_V3_HEADER_SIZE)
+ || (m_version == 4 && m_headersize != Constants.CHD_V4_HEADER_SIZE)
+ || (m_version == 5 && m_headersize != Constants.CHD_V5_HEADER_SIZE)
+ || (m_version < 1 || m_version > 5))
+ {
+ // throw CHDERR_UNSUPPORTED_VERSION;
+ return null;
+ }
+
+ return m_version;
+ }
+ catch
{
return null;
}
-
- if (!m_signature.StartsWith(Constants.CHDSignature, exact: true))
- {
- // throw CHDERR_INVALID_FILE;
- return null;
- }
-
- // Get the header size and version
- m_headersize = m_br.ReadUInt32Reverse();
- m_version = m_br.ReadUInt32Reverse();
-
- // If we have an invalid combination of size and version
- if ((m_version == 1 && m_headersize != Constants.CHD_V1_HEADER_SIZE)
- || (m_version == 2 && m_headersize != Constants.CHD_V2_HEADER_SIZE)
- || (m_version == 3 && m_headersize != Constants.CHD_V3_HEADER_SIZE)
- || (m_version == 4 && m_headersize != Constants.CHD_V4_HEADER_SIZE)
- || (m_version == 5 && m_headersize != Constants.CHD_V5_HEADER_SIZE)
- || (m_version < 1 || m_version > 5))
- {
- // throw CHDERR_UNSUPPORTED_VERSION;
- return null;
- }
-
- return m_version;
}
///
/// Get the internal MD5 (v1, v2) or SHA-1 (v3, v4, v5) from the CHD
///
/// MD5 as a byte array, null on error
- public byte[] GetHashFromHeader()
+ private byte[] GetHashFromHeader()
{
// Validate the header by default just in case
uint? version = ValidateHeaderVersion();
@@ -194,27 +251,35 @@ namespace SabreTools.Library.FileTypes
byte[] hash;
// Now parse the rest of the header according to the version
- switch (version)
+ try
{
- case 1:
- hash = ParseCHDv1Header();
- break;
- case 2:
- hash = ParseCHDv2Header();
- break;
- case 3:
- hash = ParseCHDv3Header();
- break;
- case 4:
- hash = ParseCHDv4Header();
- break;
- case 5:
- hash = ParseCHDv5Header();
- break;
- case null:
- default:
- // throw CHDERR_INVALID_FILE;
- return null;
+ switch (version)
+ {
+ case 1:
+ hash = ParseCHDv1Header();
+ break;
+ case 2:
+ hash = ParseCHDv2Header();
+ break;
+ case 3:
+ hash = ParseCHDv3Header();
+ break;
+ case 4:
+ hash = ParseCHDv4Header();
+ break;
+ case 5:
+ hash = ParseCHDv5Header();
+ break;
+ case null:
+ default:
+ // throw CHDERR_INVALID_FILE;
+ return null;
+ }
+ }
+ catch
+ {
+ // throw CHDERR_INVALID_FILE;
+ return null;
}
return hash;
diff --git a/SabreTools.Library/Tools/Utilities.cs b/SabreTools.Library/Tools/Utilities.cs
index 7578e2dc..70e4fe7c 100644
--- a/SabreTools.Library/Tools/Utilities.cs
+++ b/SabreTools.Library/Tools/Utilities.cs
@@ -1040,9 +1040,9 @@ namespace SabreTools.Library.Tools
public static BaseFile GetCHDInfo(string input)
{
FileStream fs = TryOpenRead(input);
- BaseFile datItem = GetCHDInfo(fs);
+ BaseFile chd = GetCHDInfo(fs);
fs.Dispose();
- return datItem;
+ return chd;
}
///
@@ -1371,32 +1371,6 @@ namespace SabreTools.Library.Tools
}
}
- ///
- /// Get if file has a known CHD header
- ///
- /// Filename of possible CHD
- /// True if the file has a valid CHD header, false otherwise
- public static bool HasCHDHeader(string input)
- {
- FileStream fs = TryOpenRead(input);
- bool output = HasCHDHeader(fs);
- fs.Dispose();
- return output;
- }
-
- ///
- /// Get if file is a valid CHD
- ///
- /// Filename of possible CHD
- /// True if the file is a valid CHD, false otherwise
- public static bool IsValidCHD(string input)
- {
- BaseFile baseFile = GetCHDInfo(input);
- return baseFile != null
- && (((CHDFile)baseFile).MD5 != null
- || ((CHDFile)baseFile).SHA1 != null);
- }
-
///
/// Retrieve a list of files from a directory recursively in proper order
///
@@ -1925,7 +1899,7 @@ namespace SabreTools.Library.Tools
long offset = 0, bool keepReadOpen = false, bool chdsAsFiles = true)
{
// We first check to see if it's a CHD
- if (chdsAsFiles == false && HasCHDHeader(input))
+ if (chdsAsFiles == false && GetCHDInfo(input) != null)
{
// Seek to the starting position, if one is set
try
@@ -1952,8 +1926,8 @@ namespace SabreTools.Library.Tools
Globals.Logger.Warning("Stream does not support seeking. Stream position not changed");
}
- // Get the Disk from the information
- BaseFile disk = GetCHDInfo(input);
+ // Get the BaseFile from the information
+ BaseFile chd = GetCHDInfo(input);
// Seek to the beginning of the stream if possible
try
@@ -1974,7 +1948,7 @@ namespace SabreTools.Library.Tools
input.Dispose();
}
- return disk;
+ return chd;
}
BaseFile rom = new BaseFile()
@@ -2130,54 +2104,8 @@ namespace SabreTools.Library.Tools
///
public static BaseFile GetCHDInfo(Stream input)
{
- // Get a CHD object to store the data
CHDFile chd = new CHDFile(input);
-
- // Ensure that the header is valid
- byte[] hash = chd.GetHashFromHeader();
-
- // Set the proper hash of the Disk to return
- if (hash.Length == Constants.MD5Length)
- {
- chd.MD5 = hash;
- return chd;
- }
- else if (hash.Length == Constants.SHA1Length)
- {
- chd.SHA1 = hash;
- return chd;
- }
-
- return null;
- }
-
- ///
- /// Get if stream has a known CHD header
- ///
- /// Stream of possible CHD
- /// True if the stream has a valid CHD header, false otherwise
- public static bool HasCHDHeader(Stream input)
- {
- // Get a CHD object to store the data
- CHDFile chd = new CHDFile(input);
-
- // Now try to get the header version
- uint? version = chd.ValidateHeaderVersion();
-
- return version != null;
- }
-
- ///
- /// Get if stream is a valid CHD
- ///
- /// Stream of possible CHD
- /// True if the stream is a valid CHD, false otherwise
- public static bool IsValidCHD(Stream input)
- {
- BaseFile baseFile = GetCHDInfo(input);
- return baseFile != null
- && (((CHDFile)baseFile).MD5 != null
- || ((CHDFile)baseFile).SHA1 != null);
+ return (chd.Version != null && (chd.MD5 != null || chd.SHA1 != null) ? chd : null);
}
#endregion