using System; using System.Collections.Generic; using System.Text; using System.IO; namespace BizHawk.Emulation.DiscSystem { /// /// Class to represent the file/directory information read from the disk. /// public class ISONodeRecord { #region Constants /// /// String representing the current directory entry /// public const string CURRENT_DIRECTORY = "."; /// /// String representing the parent directory entry /// public const string PARENT_DIRECTORY = ".."; #endregion #region Public Properties /// /// The length of the record in bytes. /// public byte Length; /// /// The file offset of the data for this file/directory (in sectors). /// public long OffsetOfData; /// /// The length of the data for this file/directory (in bytes). /// public long LengthOfData; /// /// The file/directory creation year since 1900. /// public byte Year; /// /// The file/directory creation month. /// public byte Month; /// /// The file/directory creation day. /// public byte Day; /// /// The file/directory creation hour. /// public byte Hour; /// /// The file/directory creation minute. /// public byte Minute; /// /// The file/directory creation second. /// public byte Second; /// /// The file time offset from GMT. /// public byte TimeZoneOffset; /// /// Flags representing the attributes of this file/directory. /// public byte Flags; /// /// The length of the file/directory name. /// public byte NameLength; /// /// The file/directory name. /// public string Name; #endregion #region Construction /// /// Constructor /// public ISONodeRecord() { // Set initial values this.Length = 0; this.OffsetOfData = 0; this.LengthOfData = 0; this.Year = 0; this.Month = 0; this.Day = 0; this.Hour = 0; this.Minute = 0; this.Second = 0; this.TimeZoneOffset = 0; this.Flags = 0; this.NameLength = 0; this.Name = null; } #endregion #region File/Directory Methods /// /// Return true if the record represents a file. /// /// True if a file. public bool IsFile() { return ((this.Flags >> 1) & 0x01) == 0; } /// /// Return true if the record represents a directory. /// /// True if a directory. public bool IsDirectory() { return ((this.Flags >> 1) & 0x01) == 1; } #endregion #region Parsing /// /// Parse the record from an array and offset. /// /// The array to parse from. /// The offset to start parsing at. public void Parse(byte[] data, int cursor) { // Put the array into a memory stream and pass to the main parsing function MemoryStream s = new MemoryStream(data); s.Seek(cursor, SeekOrigin.Begin); this.Parse(s); } /// /// Parse the node record from the given stream. /// /// The stream to parse from. public void Parse(Stream s) { EndianBitConverter bc = EndianBitConverter.CreateForLittleEndian(); long startPosition = s.Position; byte[] buffer = new byte[ISOFile.SECTOR_SIZE]; // Get the length s.Read(buffer, 0, 1); this.Length = buffer[0]; //the number of sectors in the attribute record s.Read(buffer, 0, 1); // Read Data Offset s.Read(buffer, 0, 8); this.OffsetOfData = (long)bc.ToInt32(buffer); // Read Data Length s.Read(buffer, 0, 8); this.LengthOfData = (long)bc.ToInt32(buffer); // Read the time and flags s.Read(buffer, 0, 8); this.Year = buffer[0]; this.Month = buffer[1]; this.Day = buffer[2]; this.Hour = buffer[3]; this.Minute = buffer[4]; this.Second = buffer[5]; this.TimeZoneOffset = buffer[6]; this.Flags = buffer[7]; s.Read(buffer, 0, 6); // Read the name length s.Read(buffer, 0, 1); this.NameLength = buffer[0]; // Read the directory name s.Read(buffer, 0, this.NameLength); if (this.NameLength == 1 && (buffer[0] == 0 || buffer[0] == 1)) { if (buffer[0] == 0) this.Name = ISONodeRecord.CURRENT_DIRECTORY; else this.Name = ISONodeRecord.PARENT_DIRECTORY; } else { this.Name = ASCIIEncoding.ASCII.GetString(buffer, 0, this.NameLength); } // Seek to end s.Seek(startPosition + this.Length, SeekOrigin.Begin); } #endregion } }