// Constructors /// <summary> /// DiskReader (multi tracks) /// </summary> /// <param name="fileUrl">Path to the CUE file to read</param> /// <param name="system">File system used for data track</param> private DiskReader(string fileUrl, DiskFileSystem system) : base(system) { try { var cueFile = new FileInfo(fileUrl); using (var cueFileStream = new FileStream(cueFile.FullName, FileMode.Open, FileAccess.Read, FileShare.Read)) using (var cueStream = new StreamReader(cueFileStream)) { var tracksDic = new Dictionary <int, Track>(); var indexOffsets = new List <long>(); Match match = null; Track track = null; int trackNumber = 0; int m, s, b; string line; string keyWord; while ((line = cueStream.ReadLine()) != null) { keyWord = _regCueKeyWord.Match(line).Groups[1].Value.ToUpper(); switch (keyWord) { case "FILE": if (_fileOpen) { throw new FrameworkException("Error while parsing cue sheet : framework does not support multi files per cue but only one file with multi tracks"); } fileUrl = _regCueFile.Match(line).Groups[1].Value; if (!(fileUrl.StartsWith("/") || fileUrl.StartsWith("\\") || fileUrl.Contains(":/") || fileUrl.Contains(":\\"))) { fileUrl = cueFile.DirectoryName + "/" + fileUrl; } _file = new FileInfo(fileUrl); if (!_file.Exists) { throw new FrameworkException("Error while parsing cue sheet : targeted file \"{0}\" not found", fileUrl); } string extension = _file.Extension.ToUpper(); if (!(extension == ".BIN" || extension == ".IMG" || extension == ".ISO")) { throw new FrameworkException("Error while parsing cue sheet : targeted file \"{0}\" is not a BIN/IMG/ISO file", fileUrl); } _fileStream = new FileStream(_file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read); _stream = new CBinaryReader(_fileStream); _fileOpen = true; break; case "TRACK": if (!_fileOpen) { throw new FrameworkException("Error while parsing cue sheet : TRACK defined before FILE"); } match = _regCueTrack.Match(line); if (!int.TryParse(match.Groups[1].Value, out trackNumber)) { throw new FrameworkException("Error while parsing cue sheet : track number invalid"); } string mode = match.Groups[2].Value.ToUpper(); if ((!mode.StartsWith("MODE") && !_hasDataTrack)) { throw new FrameworkException("Error while parsing cue sheet : only Mixed Mode multi tracks disks are supported, the first track must be a DATA track"); } else if ((mode.StartsWith("MODE") && _hasDataTrack)) { throw new FrameworkException("Error while parsing cue sheet : only Mixed Mode multi tracks disks are supported, it must contains only one DATA track"); } switch (mode) { case "RAW": case "RAW/2048": case "MODE1/2048": track = new DataTrackReader(_stream, trackNumber, _system, DataTrackMode.RAW, false, false); _hasDataTrack = true; break; case "MODE1/2352": track = new DataTrackReader(_stream, trackNumber, _system, DataTrackMode.MODE1, false, false); _hasDataTrack = true; break; case "MODE2/2336": track = new DataTrackReader(_stream, trackNumber, _system, DataTrackMode.MODE2, false, false); _hasDataTrack = true; break; case "MODE2/2352": track = new DataTrackReader(_stream, trackNumber, _system, DataTrackMode.MODE2_XA, false, false); _hasDataTrack = true; break; case "AUDIO": track = new AudioTrackReader(_stream, trackNumber); break; default: throw new FrameworkException("Error while parsing cue sheet : unknown/not supported track type \"{0}\"", mode); } tracksDic.Add(trackNumber, track); _tracks.Add(track); break; case "INDEX": track = tracksDic[trackNumber]; match = _regCueIndex.Match(line); int indexNumber; if (!int.TryParse(match.Groups[1].Value, out indexNumber) || indexNumber > 2) { throw new FrameworkException("Error while parsing cue sheet : index number invalid"); } if (!int.TryParse(match.Groups[2].Value, out m) || !int.TryParse(match.Groups[3].Value, out s) || s > 59 || !int.TryParse(match.Groups[4].Value, out b) || s > 74) { throw new FrameworkException("Error while parsing cue sheet : index time code invalid"); } uint offset = (uint)(((((m * 60) + s) * 75) + b) * track.SectorSize); indexOffsets.Add(offset); if (indexNumber == 0) { track.HasPause = true; } break; case "PREGAP": case "POSTGAP": track = tracksDic[trackNumber]; match = _regCueGap.Match(line); if (!int.TryParse(match.Groups[1].Value, out m) || !int.TryParse(match.Groups[2].Value, out s) || s > 59 || !int.TryParse(match.Groups[3].Value, out b) || s > 74) { throw new FrameworkException("Error while parsing cue sheet : gap size invalid"); } uint gapSize = (uint)((((m * 60) + s) * 75) + b); if (keyWord == "PREGAP") { track.PregapSize = gapSize; } else { track.PostgapSize = gapSize; } break; } } indexOffsets.Add(_fileStream.Length); for (int i = 0, u = 0, max = _tracks.Count; i < max; i++) { track = _tracks[i]; if (track.HasPause) { track.PauseOffset = indexOffsets[u]; track.PauseSize = (uint)((indexOffsets[u + 1] - indexOffsets[u]) / track.SectorSize); u++; } track.Offset = indexOffsets[u]; track.Size = (uint)((indexOffsets[u + 1] - indexOffsets[u]) / track.SectorSize); u++; } } _stream.Position = 0; } catch (FrameworkException ex) { throw ex; } catch (Exception) { throw new FrameworkException("Error while reading ISO : Unable to open the ISO File"); } }
/// <summary> /// Récupère un index présent dans le SLUS /// </summary> /// <param name="dtr_track">Track 1 de l'iso</param> /// <param name="i_position">Adresse de l'index dans le fichier SLUS</param> /// <param name="nb">Nombre de pointeurs de l'index</param> /// <returns></returns> private static List<cGlobal.st_index> readSlusIndex(DataTrackReader dtr_track, int i_position, int nb) { List<cGlobal.st_index> index = new List<cGlobal.st_index>(); Stream st_file = dtr_track.ReadFile("/SLUS_006.26"); using (BinaryReader br_file = new BinaryReader(st_file)) { br_file.BaseStream.Seek(i_position, SeekOrigin.Begin); cGlobal.st_index elem; for (int i = 0; i < nb; i++) { elem.id = i; elem.pos = br_file.ReadUInt32(); elem.size = br_file.ReadUInt32(); index.Add(elem); } } return index; }