4CH)|(?PRE)|(?SCMS))\\s*)+$";
-#endregion
+ bool initialized;
+ string imagePath;
+ StreamReader cueStream;
+ FileStream imageStream;
+ Dictionary offsetmap;
+ // Dictionary, index is track #, value is TrackFile
+ CDRWinDisc discimage;
+ List partitions;
-#region Methods
- public CDRWin (PluginBase Core)
+ #endregion
+
+ #region Parsing regexs
+
+ const string SessionRegEx = "REM\\s+SESSION\\s+(?\\d+).*$";
+ const string DiskTypeRegEx = "REM\\s+ORIGINAL MEDIA-TYPE:\\s+(?.+)$";
+ const string LeadOutRegEx = "REM\\s+LEAD-OUT\\s+(?[\\d]+:[\\d]+:[\\d]+)$";
+ const string LBARegEx = "REM MSF:\\s+(?[\\d]+:[\\d]+:[\\d]+)\\s+=\\s+LBA:\\s+(?[\\d]+)$";
+ // Not checked
+ const string DiskIDRegEx = "DISC_ID\\s+(?[\\da-f]{8})$";
+ const string BarCodeRegEx = "UPC_EAN\\s+(?[\\d]{12,13})$";
+ const string CommentRegEx = "REM\\s+(?.+)$";
+ const string CDTextRegEx = "CDTEXTFILE\\s+(?.+)$";
+ const string MCNRegEx = "CATALOG\\s+(?\\d{13})$";
+ const string TitleRegEx = "TITLE\\s+(?.+)$";
+ const string GenreRegEx = "GENRE\\s+(?.+)$";
+ const string ArrangerRegEx = "ARRANGER\\s+(?.+)$";
+ const string ComposerRegEx = "COMPOSER\\s+(?.+)$";
+ const string PerformerRegEx = "PERFORMER\\s+(?.+)$";
+ const string SongWriterRegEx = "SONGWRITER\\s+(?.+)$";
+ const string FileRegEx = "FILE\\s+(?.+)\\s+(?\\S+)$";
+ const string TrackRegEx = "TRACK\\s+(?\\d+)\\s+(?\\S+)$";
+ const string ISRCRegEx = "ISRC\\s+(?\\w{12})$";
+ const string IndexRegEx = "INDEX\\s+(?\\d+)\\s+(?[\\d]+:[\\d]+:[\\d]+)$";
+ const string PregapRegEx = "PREGAP\\s+(?[\\d]+:[\\d]+:[\\d]+)$";
+ const string PostgapRegex = "POSTGAP\\s+(?[\\d]+:[\\d]+:[\\d]+)$";
+ const string FlagsRegEx = "FLAGS\\s+(((?DCP)|(?4CH)|(?PRE)|(?SCMS))\\s*)+$";
+
+ #endregion
+
+ #region Methods
+
+ public CDRWin(PluginBase Core)
{
- base.Name = "CDRWin cuesheet handler";
- base.PluginUUID = new Guid("664568B2-15D4-4E64-8A7A-20BDA8B8386F");
- this.imagePath = "";
+ Name = "CDRWin cuesheet handler";
+ PluginUUID = new Guid("664568B2-15D4-4E64-8A7A-20BDA8B8386F");
+ imagePath = "";
}
-
// Due to .cue format, this method must parse whole file, ignoring errors (those will be thrown by OpenImage()).
public override bool IdentifyImage(string imagePath)
{
@@ -163,13 +261,13 @@ namespace FileSystemIDandChk.ImagePlugins
try
{
- this.cueStream = new StreamReader(this.imagePath);
+ cueStream = new StreamReader(this.imagePath);
int line = 0;
- while (this.cueStream.Peek() >= 0)
+ while (cueStream.Peek() >= 0)
{
line++;
- string _line = this.cueStream.ReadLine();
+ string _line = cueStream.ReadLine();
Regex Sr = new Regex(SessionRegEx);
Regex Rr = new Regex(CommentRegEx);
@@ -187,15 +285,14 @@ namespace FileSystemIDandChk.ImagePlugins
Cm = Cr.Match(_line);
Fm = Fr.Match(_line);
- if(!Sm.Success && !Rm.Success && !Cm.Success && !Fm.Success)
+ if (!Sm.Success && !Rm.Success && !Cm.Success && !Fm.Success)
return false;
- else
- return true;
+ return true;
}
return false;
}
- catch(Exception ex)
+ catch (Exception ex)
{
Console.WriteLine("Exception trying to identify image file {0}", this.imagePath);
Console.WriteLine("Exception: {0}", ex.Message);
@@ -204,20 +301,20 @@ namespace FileSystemIDandChk.ImagePlugins
}
}
- public override bool OpenImage(string filename)
+ public override bool OpenImage(string imagePath)
{
- if (filename == "")
+ if (imagePath == null)
+ return false;
+ if (imagePath == "")
return false;
this.imagePath = imagePath;
try
{
- this.cueStream = new StreamReader(this.imagePath);
+ cueStream = new StreamReader(imagePath);
int line = 0;
bool intrack = false;
- string currentfile = "";
- string currentfileformat = "";
byte currentsession = 1;
// Initialize all RegExs
@@ -269,16 +366,47 @@ namespace FileSystemIDandChk.ImagePlugins
Match MatchFlags;
// Initialize disc
- this.discimage = new CDRWinDisc();
- this.discimage.sessions = new List();
- this.discimage.tracks = new List();
+ discimage = new CDRWinDisc();
+ discimage.sessions = new List();
+ discimage.tracks = new List();
+ discimage.comment = "";
CDRWinTrack currenttrack = new CDRWinTrack();
+ currenttrack.indexes = new Dictionary();
+ CDRWinTrackFile currentfile = new CDRWinTrackFile();
+ ulong currentfileoffsetsector = 0;
- while (this.cueStream.Peek() >= 0)
+ CDRWinTrack[] cuetracks;
+ int track_count = 0;
+
+ while (cueStream.Peek() >= 0)
{
line++;
- string _line = this.cueStream.ReadLine();
+ string _line = cueStream.ReadLine();
+
+ MatchTrack = RegexTrack.Match(_line);
+ if (MatchTrack.Success)
+ {
+ uint track_seq = uint.Parse(MatchTrack.Groups[1].Value);
+ if (track_count + 1 != track_seq)
+ throw new FeatureUnsupportedImageException(String.Format("Found TRACK {0} out of order in line {1}", track_seq, line));
+
+ track_count++;
+ }
+ }
+
+ if (track_count == 0)
+ throw new FeatureUnsupportedImageException("No tracks found");
+
+ cuetracks = new CDRWinTrack[track_count];
+
+ line = 0;
+ cueStream.BaseStream.Seek(0, SeekOrigin.Begin);
+
+ while (cueStream.Peek() >= 0)
+ {
+ line++;
+ string _line = cueStream.ReadLine();
MatchSession = RegexSession.Match(_line);
MatchDiskType = RegexDiskType.Match(_line);
@@ -286,36 +414,39 @@ namespace FileSystemIDandChk.ImagePlugins
MatchLBA = RegexLBA.Match(_line); // Unhandled, just ignored
MatchLeadOut = RegexLeadOut.Match(_line); // Unhandled, just ignored
- if(MatchDiskType.Success && intrack == false)
+ if (MatchDiskType.Success && !intrack)
{
Console.WriteLine("DEBUG (CDRWin plugin): Found REM ORIGINAL MEDIA TYPE at line {0}", line);
- this.discimage.disktypestr = MatchDiskType.Groups[1].Value;
+ discimage.disktypestr = MatchDiskType.Groups[1].Value;
}
- else if(MatchSession.Success && intrack == false)
+ else if (MatchDiskType.Success && intrack)
+ {
+ throw new FeatureUnsupportedImageException(String.Format("Found REM ORIGINAL MEDIA TYPE field after a track in line {0}", line));
+ }
+ else if (MatchSession.Success)
{
Console.WriteLine("DEBUG (CDRWin plugin): Found REM SESSION at line {0}", line);
currentsession = Byte.Parse(MatchSession.Groups[1].Value);
// What happens between sessions
}
- else if(MatchLBA.Success)
+ else if (MatchLBA.Success)
{
Console.WriteLine("DEBUG (CDRWin plugin): Found REM MSF at line {0}", line);
// Just ignored
}
- else if(MatchLeadOut.Success)
+ else if (MatchLeadOut.Success)
{
Console.WriteLine("DEBUG (CDRWin plugin): Found REM LEAD-OUT at line {0}", line);
// Just ignored
}
- else if(MatchComment.Success && intrack == false)
+ else if (MatchComment.Success)
{
Console.WriteLine("DEBUG (CDRWin plugin): Found REM at line {0}", line);
- this.discimage.comment = MatchComment.Groups[1].Value;
- }
- else if((MatchComment.Success || MatchSession.Success || MatchDiskType.Success) && intrack == true)
- {
- throw new FeatureUnsupportedImageException(String.Format("Found comment/session/disktype field after a track in line {0}", line));
+ if (discimage.comment == "")
+ discimage.comment = MatchComment.Groups[1].Value; // First comment
+ else
+ discimage.comment += Environment.NewLine + MatchComment.Groups[1].Value; // Append new comments as new lines
}
else
{
@@ -337,165 +468,661 @@ namespace FileSystemIDandChk.ImagePlugins
MatchBarCode = RegexBarCode.Match(_line);
MatchArranger = RegexArranger.Match(_line);
- if(MatchArranger.Success)
+ if (MatchArranger.Success)
{
Console.WriteLine("DEBUG (CDRWin plugin): Found ARRANGER at line {0}", line);
- if(intrack == true)
+ if (intrack)
currenttrack.arranger = MatchArranger.Groups[1].Value;
else
- this.discimage.arranger = MatchArranger.Groups[1].Value;
+ discimage.arranger = MatchArranger.Groups[1].Value;
}
- else if(MatchBarCode.Success)
+ else if (MatchBarCode.Success)
{
- Console.WriteLine("DEBUG (CDRWin plugin): Found CATALOG at line {0}", line);
- if(intrack == false)
- this.discimage.barcode = MatchBarCode.Groups[1].Value;
+ Console.WriteLine("DEBUG (CDRWin plugin): Found UPC_EAN at line {0}", line);
+ if (!intrack)
+ discimage.barcode = MatchBarCode.Groups[1].Value;
else
throw new FeatureUnsupportedImageException(String.Format("Found barcode field in incorrect place at line {0}", line));
}
- else if(MatchCDText.Success)
+ else if (MatchCDText.Success)
{
Console.WriteLine("DEBUG (CDRWin plugin): Found CDTEXTFILE at line {0}", line);
- if(intrack == false)
- this.discimage.cdtextfile = MatchCDText.Groups[1].Value;
+ if (!intrack)
+ discimage.cdtextfile = MatchCDText.Groups[1].Value;
else
throw new FeatureUnsupportedImageException(String.Format("Found CD-Text file field in incorrect place at line {0}", line));
}
- else if(MatchComposer.Success)
+ else if (MatchComposer.Success)
{
Console.WriteLine("DEBUG (CDRWin plugin): Found COMPOSER at line {0}", line);
- if(intrack == true)
+ if (intrack)
currenttrack.arranger = MatchComposer.Groups[1].Value;
else
- this.discimage.arranger = MatchComposer.Groups[1].Value;
+ discimage.arranger = MatchComposer.Groups[1].Value;
}
- else if(MatchDiskID.Success)
+ else if (MatchDiskID.Success)
{
Console.WriteLine("DEBUG (CDRWin plugin): Found DISC_ID at line {0}", line);
- if(intrack == false)
- this.discimage.disk_id = MatchDiskID.Groups[1].Value;
+ if (!intrack)
+ discimage.disk_id = MatchDiskID.Groups[1].Value;
else
throw new FeatureUnsupportedImageException(String.Format("Found CDDB ID field in incorrect place at line {0}", line));
}
- else if(MatchFile.Success)
+ else if (MatchFile.Success)
{
Console.WriteLine("DEBUG (CDRWin plugin): Found FILE at line {0}", line);
- currentfile = MatchFile.Groups[1].Value;
- currentfileformat = MatchFile.Groups[2].Value;
+
+ if (currenttrack.sequence != 0)
+ {
+ currentfile.sequence = currenttrack.sequence;
+ currenttrack.trackfile = currentfile;
+ FileInfo finfo = new FileInfo(currentfile.datafile);
+ currenttrack.sectors = ((ulong)finfo.Length - currentfile.offset) / CDRWinTrackTypeToBytesPerSector(currenttrack.tracktype);
+ cuetracks[currenttrack.sequence - 1] = currenttrack;
+ intrack = false;
+ currenttrack = new CDRWinTrack();
+ }
+
+
+ currentfile.datafile = MatchFile.Groups[1].Value;
+ currentfile.filetype = MatchFile.Groups[2].Value;
+
+ // Check if file path is quoted
+ if (currentfile.datafile[0] == '"' && currentfile.datafile[currentfile.datafile.Length - 1] == '"')
+ {
+ currentfile.datafile = currentfile.datafile.Substring(1, currentfile.datafile.Length - 2); // Unquote it
+ }
+
+ // Check if file exists
+ if (!File.Exists(currentfile.datafile))
+ {
+ if (currentfile.datafile[0] == '/' || (currentfile.datafile[0] == '/' && currentfile.datafile[1] == '.')) // UNIX absolute path
+ {
+ Regex unixpath = new Regex("^(.+)/([^/]+)$");
+ Match unixpathmatch = unixpath.Match(currentfile.datafile);
+
+ if (unixpathmatch.Success)
+ {
+ currentfile.datafile = unixpathmatch.Groups[1].Value;
+
+ if (!File.Exists(currentfile.datafile))
+ {
+ string path = Path.GetPathRoot(imagePath);
+ currentfile.datafile = path + Path.PathSeparator + currentfile.datafile;
+
+ if (!File.Exists(currentfile.datafile))
+ throw new FeatureUnsupportedImageException(String.Format("File \"{0}\" not found.", MatchFile.Groups[1].Value));
+ }
+ }
+ else
+ throw new FeatureUnsupportedImageException(String.Format("File \"{0}\" not found.", MatchFile.Groups[1].Value));
+ }
+ else if ((currentfile.datafile[1] == ':' && currentfile.datafile[2] == '\\') ||
+ (currentfile.datafile[0] == '\\' && currentfile.datafile[1] == '\\') ||
+ ((currentfile.datafile[0] == '.' && currentfile.datafile[1] == '\\'))) // Windows absolute path
+ {
+ Regex winpath = new Regex("^(?:[a-zA-Z]\\:(\\\\|\\/)|file\\:\\/\\/|\\\\\\\\|\\.(\\/|\\\\))([^\\\\\\/\\:\\*\\?\\<\\>\\\"\\|]+(\\\\|\\/){0,1})+$");
+ Match winpathmatch = winpath.Match(currentfile.datafile);
+ if (winpathmatch.Success)
+ {
+ currentfile.datafile = winpathmatch.Groups[1].Value;
+
+ if (!File.Exists(currentfile.datafile))
+ {
+ string path = Path.GetPathRoot(imagePath);
+ currentfile.datafile = path + Path.PathSeparator + currentfile.datafile;
+
+ if (!File.Exists(currentfile.datafile))
+ throw new FeatureUnsupportedImageException(String.Format("File \"{0}\" not found.", MatchFile.Groups[1].Value));
+ }
+ }
+ else
+ throw new FeatureUnsupportedImageException(String.Format("File \"{0}\" not found.", MatchFile.Groups[1].Value));
+ }
+ else
+ {
+ string path = Path.GetDirectoryName(imagePath);
+ currentfile.datafile = path + Path.DirectorySeparatorChar + currentfile.datafile;
+
+ if (!File.Exists(currentfile.datafile))
+ throw new FeatureUnsupportedImageException(String.Format("File \"{0}\" not found.", MatchFile.Groups[1].Value));
+ }
+ }
+
+ // File does exist, process it
+ Console.WriteLine("DEBUG (CDRWin plugin): File \"{0}\" found", currentfile.datafile);
+
+ switch (currentfile.filetype)
+ {
+ case CDRWinDiskTypeLittleEndian:
+ break;
+ case CDRWinDiskTypeBigEndian:
+ case CDRWinDiskTypeAIFF:
+ case CDRWinDiskTypeRIFF:
+ case CDRWinDiskTypeMP3:
+ throw new FeatureSupportedButNotImplementedImageException(String.Format("Unsupported file type {0}", currentfile.filetype));
+ default:
+ throw new FeatureUnsupportedImageException(String.Format("Unknown file type {0}", currentfile.filetype));
+ }
+
+ Console.WriteLine("DEBUG (CDRWin plugin): Sets currentfile.offset to 0 at line 514");
+ currentfile.offset = 0;
+ currentfile.sequence = 0;
}
- else if(MatchFlags.Success)
+ else if (MatchFlags.Success)
{
Console.WriteLine("DEBUG (CDRWin plugin): Found FLAGS at line {0}", line);
- if(intrack == false)
+ if (!intrack)
throw new FeatureUnsupportedImageException(String.Format("Found FLAGS field in incorrect place at line {0}", line));
- else
- {
- // Not yet implemented
- }
+ // TODO: Implement FLAGS support.
}
- else if(MatchGenre.Success)
+ else if (MatchGenre.Success)
{
Console.WriteLine("DEBUG (CDRWin plugin): Found GENRE at line {0}", line);
- if(intrack == true)
+ if (intrack)
currenttrack.genre = MatchGenre.Groups[1].Value;
else
- this.discimage.genre = MatchGenre.Groups[1].Value;
+ discimage.genre = MatchGenre.Groups[1].Value;
}
- else if(MatchIndex.Success)
+ else if (MatchIndex.Success)
{
Console.WriteLine("DEBUG (CDRWin plugin): Found INDEX at line {0}", line);
- if(intrack == false)
+ if (!intrack)
throw new FeatureUnsupportedImageException(String.Format("Found INDEX before a track {0}", line));
else
{
- // Not yet implemented
+ int index = int.Parse(MatchIndex.Groups[1].Value);
+ ulong offset = CDRWinMSFToLBA(MatchIndex.Groups[2].Value);
+
+ if ((index != 0 && index != 1) && currenttrack.indexes.Count == 0)
+ throw new FeatureUnsupportedImageException(String.Format("Found INDEX {0} before INDEX 00 or INDEX 01", index));
+
+ if ((index == 0 || (index == 1 && !currenttrack.indexes.ContainsKey(0))))
+ {
+ if ((int)(currenttrack.sequence - 2) >= 0 && offset > 1)
+ {
+ cuetracks[currenttrack.sequence - 2].sectors = offset - currentfileoffsetsector;
+ currentfile.offset += cuetracks[currenttrack.sequence - 2].sectors * cuetracks[currenttrack.sequence - 2].bps;
+ Console.WriteLine("DEBUG (CDRWin plugin): Sets currentfile.offset to {0} at line 553", currentfile.offset);
+ Console.WriteLine("DEBUG (CDRWin plugin): cuetracks[currenttrack.sequence-2].sectors = {0}", cuetracks[currenttrack.sequence - 2].sectors);
+ Console.WriteLine("DEBUG (CDRWin plugin): cuetracks[currenttrack.sequence-2].bps = {0}", cuetracks[currenttrack.sequence - 2].bps);
+ }
+ }
+
+ if ((index == 0 || (index == 1 && !currenttrack.indexes.ContainsKey(0))) && currenttrack.sequence == 1)
+ {
+ Console.WriteLine("DEBUG (CDRWin plugin): Sets currentfile.offset to {0} at line 559", offset * currenttrack.bps);
+ currentfile.offset = offset * currenttrack.bps;
+ }
+
+ currentfileoffsetsector = offset;
+ currenttrack.indexes.Add(index, offset);
}
}
- else if(MatchISRC.Success)
+ else if (MatchISRC.Success)
{
Console.WriteLine("DEBUG (CDRWin plugin): Found ISRC at line {0}", line);
- if(intrack == false)
+ if (!intrack)
throw new FeatureUnsupportedImageException(String.Format("Found ISRC before a track {0}", line));
- else
- currenttrack.isrc = MatchISRC.Groups[1].Value;
+ currenttrack.isrc = MatchISRC.Groups[1].Value;
}
- else if(MatchMCN.Success)
+ else if (MatchMCN.Success)
{
Console.WriteLine("DEBUG (CDRWin plugin): Found CATALOG at line {0}", line);
- if(intrack == false)
- this.discimage.mcn = MatchMCN.Groups[1].Value;
+ if (!intrack)
+ discimage.mcn = MatchMCN.Groups[1].Value;
else
throw new FeatureUnsupportedImageException(String.Format("Found CATALOG field in incorrect place at line {0}", line));
}
- else if(MatchPerformer.Success)
+ else if (MatchPerformer.Success)
{
Console.WriteLine("DEBUG (CDRWin plugin): Found PERFORMER at line {0}", line);
- if(intrack == true)
+ if (intrack)
currenttrack.performer = MatchPerformer.Groups[1].Value;
else
- this.discimage.performer = MatchPerformer.Groups[1].Value;
+ discimage.performer = MatchPerformer.Groups[1].Value;
}
- else if(MatchPostgap.Success)
+ else if (MatchPostgap.Success)
{
Console.WriteLine("DEBUG (CDRWin plugin): Found POSTGAP at line {0}", line);
- if(intrack == true)
+ if (intrack)
{
- // Not yet implemented
+ currenttrack.postgap = CDRWinMSFToLBA(MatchPostgap.Groups[1].Value);
}
else
throw new FeatureUnsupportedImageException(String.Format("Found POSTGAP field before a track at line {0}", line));
}
- else if(MatchPregap.Success)
+ else if (MatchPregap.Success)
{
Console.WriteLine("DEBUG (CDRWin plugin): Found PREGAP at line {0}", line);
- if(intrack == true)
+ if (intrack)
{
- // Not yet implemented
+ currenttrack.pregap = CDRWinMSFToLBA(MatchPregap.Groups[1].Value);
}
else
throw new FeatureUnsupportedImageException(String.Format("Found PREGAP field before a track at line {0}", line));
}
- else if(MatchSongWriter.Success)
+ else if (MatchSongWriter.Success)
{
Console.WriteLine("DEBUG (CDRWin plugin): Found SONGWRITER at line {0}", line);
- if(intrack == true)
+ if (intrack)
currenttrack.songwriter = MatchSongWriter.Groups[1].Value;
else
- this.discimage.songwriter = MatchSongWriter.Groups[1].Value;
+ discimage.songwriter = MatchSongWriter.Groups[1].Value;
}
- else if(MatchTitle.Success)
+ else if (MatchTitle.Success)
{
Console.WriteLine("DEBUG (CDRWin plugin): Found TITLE at line {0}", line);
- if(intrack == true)
+ if (intrack)
currenttrack.title = MatchTitle.Groups[1].Value;
else
- this.discimage.title = MatchTitle.Groups[1].Value;
+ discimage.title = MatchTitle.Groups[1].Value;
}
- else if(MatchTrack.Success)
+ else if (MatchTrack.Success)
{
Console.WriteLine("DEBUG (CDRWin plugin): Found TRACK at line {0}", line);
- if(currentfile == "")
+ if (currentfile.datafile == "")
throw new FeatureUnsupportedImageException(String.Format("Found TRACK field before a file is defined at line {0}", line));
- else
+ if (intrack)
{
- if(intrack == true)
+ if (currenttrack.indexes.ContainsKey(0) && currenttrack.pregap == 0)
{
- this.discimage.tracks.Add(currenttrack);
+ currenttrack.indexes.TryGetValue(0, out currenttrack.pregap);
}
- currenttrack = new CDRWinTrack();
- intrack = true;
-
- // TODO
+ currentfile.sequence = currenttrack.sequence;
+ currenttrack.trackfile = currentfile;
+ cuetracks[currenttrack.sequence - 1] = currenttrack;
}
+ currenttrack = new CDRWinTrack();
+ currenttrack.indexes = new Dictionary();
+ currenttrack.sequence = uint.Parse(MatchTrack.Groups[1].Value);
+ Console.WriteLine("DEBUG (CDRWin plugin): Setting currenttrack.sequence to {0}", currenttrack.sequence);
+ currentfile.sequence = currenttrack.sequence;
+ currenttrack.bps = CDRWinTrackTypeToBytesPerSector(MatchTrack.Groups[2].Value);
+ currenttrack.tracktype = MatchTrack.Groups[2].Value;
+ currenttrack.session = currentsession;
+ intrack = true;
+
+ // TODO
+ }
+ else if (_line == "") // Empty line, ignore it
+ {
+
+ }
+ else // Non-empty unknown field
+ {
+ throw new FeatureUnsupportedImageException(String.Format("Found unknown field defined at line {0}: \"{1}\"", line, _line));
}
}
}
- return false;
+ if (currenttrack.sequence != 0)
+ {
+ currentfile.sequence = currenttrack.sequence;
+ currenttrack.trackfile = currentfile;
+ FileInfo finfo = new FileInfo(currentfile.datafile);
+ currenttrack.sectors = ((ulong)finfo.Length - currentfile.offset) / CDRWinTrackTypeToBytesPerSector(currenttrack.tracktype);
+ cuetracks[currenttrack.sequence - 1] = currenttrack;
+ }
+
+ Session[] _sessions = new Session[currentsession];
+ for (int s = 1; s <= _sessions.Length; s++)
+ {
+ _sessions[s - 1].SessionSequence = 1;
+ ulong _session_offset;
+
+ if (s > 1)
+ _sessions[s - 1].StartSector = _sessions[s - 2].EndSector + 1;
+ else
+ _sessions[s - 1].StartSector = 0;
+
+ ulong session_sectors = 0;
+ bool first_session_track = true;
+ int last_session_track = 0;
+
+ for (int i = 0; i < cuetracks.Length; i++)
+ {
+ if (cuetracks[i].session == s)
+ {
+ session_sectors += cuetracks[i].sectors;
+ if (i > last_session_track)
+ last_session_track = i;
+ }
+ }
+
+ _sessions[s - 1].EndTrack = cuetracks[last_session_track].sequence;
+ _sessions[s - 1].EndSector = session_sectors - 1;
+ }
+
+ for (int s = 1; s <= _sessions.Length; s++)
+ discimage.sessions.Add(_sessions[s - 1]);
+
+ for (int t = 1; t <= cuetracks.Length; t++)
+ discimage.tracks.Add(cuetracks[t - 1]);
+
+ discimage.disktype = CDRWinIsoBusterDiscTypeToDiskType(discimage.disktypestr);
+
+ if (discimage.disktype == DiskType.Unknown || discimage.disktype == DiskType.CD)
+ {
+ bool data = false;
+ bool cdg = false;
+ bool cdi = false;
+ bool mode2 = false;
+ bool firstaudio = false;
+ bool firstdata = false;
+ bool audio = false;
+
+ for (int i = 0; i < discimage.tracks.Count; i++)
+ {
+ // First track is audio
+ firstaudio |= i == 0 && discimage.tracks[i].tracktype == CDRWinTrackTypeAudio;
+
+ // First track is data
+ firstdata |= i == 0 && discimage.tracks[i].tracktype != CDRWinTrackTypeAudio;
+
+ // Any non first track is data
+ data |= i != 0 && discimage.tracks[i].tracktype != CDRWinTrackTypeAudio;
+
+ // Any non first track is audio
+ audio |= i != 0 && discimage.tracks[i].tracktype == CDRWinTrackTypeAudio;
+
+ switch (discimage.tracks[i].tracktype)
+ {
+ case CDRWinTrackTypeCDG:
+ cdg = true;
+ break;
+ case CDRWinTrackTypeCDI:
+ case CDRWinTrackTypeCDIRaw:
+ cdi = true;
+ break;
+ case CDRWinTrackTypeMode2Form1:
+ case CDRWinTrackTypeMode2Form2:
+ case CDRWinTrackTypeMode2Formless:
+ case CDRWinTrackTypeMode2Raw:
+ mode2 = true;
+ break;
+ }
+ }
+
+ if (!data && !firstdata)
+ discimage.disktype = DiskType.CDDA;
+ else if (cdg)
+ discimage.disktype = DiskType.CDG;
+ else if (cdi)
+ discimage.disktype = DiskType.CDI;
+ else if (firstaudio && data && discimage.sessions.Count > 1 && mode2)
+ discimage.disktype = DiskType.CDPLUS;
+ else if ((firstdata && !data) || mode2)
+ discimage.disktype = DiskType.CDROMXA;
+ else if (!audio)
+ discimage.disktype = DiskType.CDROM;
+ else
+ discimage.disktype = DiskType.CD;
+ }
+
+ // DEBUG information
+ Console.WriteLine("DEBUG (CDRWin plugin): Disc image parsing results");
+ Console.WriteLine("DEBUG (CDRWin plugin): Disc CD-TEXT:");
+ if (discimage.arranger == null)
+ Console.WriteLine("DEBUG (CDRWin plugin): \tArranger is not set.");
+ else
+ Console.WriteLine("DEBUG (CDRWin plugin): \tArranger: {0}", discimage.arranger);
+ if (discimage.composer == null)
+ Console.WriteLine("DEBUG (CDRWin plugin): \tComposer is not set.");
+ else
+ Console.WriteLine("DEBUG (CDRWin plugin): \tComposer: {0}", discimage.composer);
+ if (discimage.genre == null)
+ Console.WriteLine("DEBUG (CDRWin plugin): \tGenre is not set.");
+ else
+ Console.WriteLine("DEBUG (CDRWin plugin): \tGenre: {0}", discimage.genre);
+ if (discimage.performer == null)
+ Console.WriteLine("DEBUG (CDRWin plugin): \tPerformer is not set.");
+ else
+ Console.WriteLine("DEBUG (CDRWin plugin): \tPerformer: {0}", discimage.performer);
+ if (discimage.songwriter == null)
+ Console.WriteLine("DEBUG (CDRWin plugin): \tSongwriter is not set.");
+ else
+ Console.WriteLine("DEBUG (CDRWin plugin): \tSongwriter: {0}", discimage.songwriter);
+ if (discimage.title == null)
+ Console.WriteLine("DEBUG (CDRWin plugin): \tTitle is not set.");
+ else
+ Console.WriteLine("DEBUG (CDRWin plugin): \tTitle: {0}", discimage.title);
+ if (discimage.cdtextfile == null)
+ Console.WriteLine("DEBUG (CDRWin plugin): \tCD-TEXT binary file not set.");
+ else
+ Console.WriteLine("DEBUG (CDRWin plugin): \tCD-TEXT binary file: {0}", discimage.cdtextfile);
+ Console.WriteLine("DEBUG (CDRWin plugin): Disc information:");
+ if (discimage.disktypestr == null)
+ Console.WriteLine("DEBUG (CDRWin plugin): \tISOBuster disc type not set.");
+ else
+ Console.WriteLine("DEBUG (CDRWin plugin): \tISOBuster disc type: {0}", discimage.disktypestr);
+ Console.WriteLine("DEBUG (CDRWin plugin): \tGuessed disk type: {0}", discimage.disktype);
+ if (discimage.barcode == null)
+ Console.WriteLine("DEBUG (CDRWin plugin): \tBarcode not set.");
+ else
+ Console.WriteLine("DEBUG (CDRWin plugin): \tBarcode: {0}", discimage.barcode);
+ if (discimage.disk_id == null)
+ Console.WriteLine("DEBUG (CDRWin plugin): \tDisc ID not set.");
+ else
+ Console.WriteLine("DEBUG (CDRWin plugin): \tDisc ID: {0}", discimage.disk_id);
+ if (discimage.mcn == null)
+ Console.WriteLine("DEBUG (CDRWin plugin): \tMCN not set.");
+ else
+ Console.WriteLine("DEBUG (CDRWin plugin): \tMCN: {0}", discimage.mcn);
+ if (discimage.comment == null)
+ Console.WriteLine("DEBUG (CDRWin plugin): \tComment not set.");
+ else
+ Console.WriteLine("DEBUG (CDRWin plugin): \tComment: \"{0}\"", discimage.comment);
+ Console.WriteLine("DEBUG (CDRWin plugin): Session information:");
+ Console.WriteLine("DEBUG (CDRWin plugin): \tDisc contains {0} sessions", discimage.sessions.Count);
+ for (int i = 0; i < discimage.sessions.Count; i++)
+ {
+ Console.WriteLine("DEBUG (CDRWin plugin): \tSession {0} information:", i + 1);
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tStarting track: {0}", discimage.sessions[i].StartTrack);
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tStarting sector: {0}", discimage.sessions[i].StartSector);
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tEnding track: {0}", discimage.sessions[i].EndTrack);
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tEnding sector: {0}", discimage.sessions[i].EndSector);
+ }
+ Console.WriteLine("DEBUG (CDRWin plugin): Track information:");
+ Console.WriteLine("DEBUG (CDRWin plugin): \tDisc contains {0} tracks", discimage.tracks.Count);
+ for (int i = 0; i < discimage.tracks.Count; i++)
+ {
+ Console.WriteLine("DEBUG (CDRWin plugin): \tTrack {0} information:", discimage.tracks[i].sequence);
+
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\t{0} bytes per sector", discimage.tracks[i].bps);
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tPregap: {0} sectors", discimage.tracks[i].pregap);
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tData: {0} sectors", discimage.tracks[i].sectors);
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tPostgap: {0} sectors", discimage.tracks[i].postgap);
+
+ if (discimage.tracks[i].flag_4ch)
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tTrack is flagged as quadraphonic");
+ if (discimage.tracks[i].flag_dcp)
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tTrack allows digital copy");
+ if (discimage.tracks[i].flag_pre)
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tTrack has pre-emphasis applied");
+ if (discimage.tracks[i].flag_scms)
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tTrack has SCMS");
+
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tTrack resides in file {0}, type defined as {1}, starting at byte {2}",
+ discimage.tracks[i].trackfile.datafile, discimage.tracks[i].trackfile.filetype, discimage.tracks[i].trackfile.offset);
+
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tIndexes:");
+ foreach (KeyValuePair kvp in discimage.tracks[i].indexes)
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\t\tIndex {0} starts at sector {1}", kvp.Key, kvp.Value);
+
+ if (discimage.tracks[i].isrc == null)
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tISRC is not set.");
+ else
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tISRC: {0}", discimage.tracks[i].isrc);
+
+ if (discimage.tracks[i].arranger == null)
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tArranger is not set.");
+ else
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tArranger: {0}", discimage.tracks[i].arranger);
+ if (discimage.tracks[i].composer == null)
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tComposer is not set.");
+ else
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tComposer: {0}", discimage.tracks[i].composer);
+ if (discimage.tracks[i].genre == null)
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tGenre is not set.");
+ else
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tGenre: {0}", discimage.tracks[i].genre);
+ if (discimage.tracks[i].performer == null)
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tPerformer is not set.");
+ else
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tPerformer: {0}", discimage.tracks[i].performer);
+ if (discimage.tracks[i].songwriter == null)
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tSongwriter is not set.");
+ else
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tSongwriter: {0}", discimage.tracks[i].songwriter);
+ if (discimage.tracks[i].title == null)
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tTitle is not set.");
+ else
+ Console.WriteLine("DEBUG (CDRWin plugin): \t\tTitle: {0}", discimage.tracks[i].title);
+ }
+
+ Console.WriteLine("DEBUG (CDRWin plugin): Building offset map");
+
+ partitions = new List();
+
+ ulong byte_offset = 0;
+ ulong sector_offset = 0;
+ ulong partitionSequence = 0;
+ ulong index_zero_offset = 0;
+ ulong index_one_offset = 0;
+ bool index_zero = false;
+
+ offsetmap = new Dictionary();
+
+ for (int i = 0; i < discimage.tracks.Count; i++)
+ {
+ if (discimage.tracks[i].sequence == 1 && i != 0)
+ throw new ImageNotSupportedException("Unordered tracks");
+
+ PartPlugins.Partition partition = new FileSystemIDandChk.PartPlugins.Partition();
+
+ if (discimage.tracks[i].pregap > 0)
+ {
+ partition.PartitionDescription = String.Format("Track {0} pregap.", discimage.tracks[i].sequence);
+ partition.PartitionName = discimage.tracks[i].title;
+ partition.PartitionStartSector = sector_offset;
+ partition.PartitionLength = discimage.tracks[i].pregap * discimage.tracks[i].bps;
+ partition.PartitionSectors = discimage.tracks[i].pregap;
+ partition.PartitionSequence = partitionSequence;
+ partition.PartitionStart = byte_offset;
+ partition.PartitionType = discimage.tracks[i].tracktype;
+
+ sector_offset += partition.PartitionSectors;
+ byte_offset += partition.PartitionLength;
+ partitionSequence++;
+
+ if(!offsetmap.ContainsKey(discimage.tracks[i].sequence))
+ offsetmap.Add(discimage.tracks[i].sequence, partition.PartitionStartSector);
+ else
+ {
+ ulong old_start;
+ offsetmap.TryGetValue(discimage.tracks[i].sequence, out old_start);
+
+ if(partition.PartitionStartSector < old_start)
+ {
+ offsetmap.Remove(discimage.tracks[i].sequence);
+ offsetmap.Add(discimage.tracks[i].sequence, partition.PartitionStartSector);
+ }
+ }
+
+ partitions.Add(partition);
+ partition = new FileSystemIDandChk.PartPlugins.Partition();
+ }
+
+ index_zero |= discimage.tracks[i].indexes.TryGetValue(0, out index_zero_offset);
+
+ if (!discimage.tracks[i].indexes.TryGetValue(1, out index_one_offset))
+ throw new ImageNotSupportedException(String.Format("Track {0} lacks index 01", discimage.tracks[i].sequence));
+
+ if (index_zero && index_one_offset > index_zero_offset)
+ {
+ partition.PartitionDescription = String.Format("Track {0} index 00.", discimage.tracks[i].sequence);
+ partition.PartitionName = discimage.tracks[i].title;
+ partition.PartitionStartSector = sector_offset;
+ partition.PartitionLength = (index_one_offset - index_zero_offset) * discimage.tracks[i].bps;
+ partition.PartitionSectors = index_one_offset - index_zero_offset;
+ partition.PartitionSequence = partitionSequence;
+ partition.PartitionStart = byte_offset;
+ partition.PartitionType = discimage.tracks[i].tracktype;
+
+ sector_offset += partition.PartitionSectors;
+ byte_offset += partition.PartitionLength;
+ partitionSequence++;
+
+ if(!offsetmap.ContainsKey(discimage.tracks[i].sequence))
+ offsetmap.Add(discimage.tracks[i].sequence, partition.PartitionStartSector);
+ else
+ {
+ ulong old_start;
+ offsetmap.TryGetValue(discimage.tracks[i].sequence, out old_start);
+
+ if(partition.PartitionStartSector < old_start)
+ {
+ offsetmap.Remove(discimage.tracks[i].sequence);
+ offsetmap.Add(discimage.tracks[i].sequence, partition.PartitionStartSector);
+ }
+ }
+
+ partitions.Add(partition);
+ partition = new FileSystemIDandChk.PartPlugins.Partition();
+ }
+
+ // Index 01
+ partition.PartitionDescription = String.Format("Track {0}.", discimage.tracks[i].sequence);
+ partition.PartitionName = discimage.tracks[i].title;
+ partition.PartitionStartSector = sector_offset;
+ partition.PartitionLength = (discimage.tracks[i].sectors - (index_one_offset - index_zero_offset)) * discimage.tracks[i].bps;
+ partition.PartitionSectors = (discimage.tracks[i].sectors - (index_one_offset - index_zero_offset));
+ partition.PartitionSequence = partitionSequence;
+ partition.PartitionStart = byte_offset;
+ partition.PartitionType = discimage.tracks[i].tracktype;
+
+ sector_offset += partition.PartitionSectors;
+ byte_offset += partition.PartitionLength;
+ partitionSequence++;
+
+ if(!offsetmap.ContainsKey(discimage.tracks[i].sequence))
+ offsetmap.Add(discimage.tracks[i].sequence, partition.PartitionStartSector);
+ else
+ {
+ ulong old_start;
+ offsetmap.TryGetValue(discimage.tracks[i].sequence, out old_start);
+
+ if(partition.PartitionStartSector < old_start)
+ {
+ offsetmap.Remove(discimage.tracks[i].sequence);
+ offsetmap.Add(discimage.tracks[i].sequence, partition.PartitionStartSector);
+ }
+ }
+
+ partitions.Add(partition);
+ partition = new FileSystemIDandChk.PartPlugins.Partition();
+ }
+
+ // Print offset map
+ Console.WriteLine("DEBUG (CDRWin plugin) printing partition map");
+ foreach(FileSystemIDandChk.PartPlugins.Partition partition in partitions)
+ {
+ Console.WriteLine ("DEBUG (CDRWin plugin): Partition sequence: {0}", partition.PartitionSequence);
+ Console.WriteLine ("DEBUG (CDRWin plugin): \tPartition name: {0}", partition.PartitionName);
+ Console.WriteLine ("DEBUG (CDRWin plugin): \tPartition description: {0}", partition.PartitionDescription);
+ Console.WriteLine ("DEBUG (CDRWin plugin): \tPartition type: {0}", partition.PartitionType);
+ Console.WriteLine ("DEBUG (CDRWin plugin): \tPartition starting sector: {0}", partition.PartitionStartSector);
+ Console.WriteLine ("DEBUG (CDRWin plugin): \tPartition sectors: {0}", partition.PartitionSectors);
+ Console.WriteLine ("DEBUG (CDRWin plugin): \tPartition starting offset: {0}", partition.PartitionStart);
+ Console.WriteLine ("DEBUG (CDRWin plugin): \tPartition size in bytes: {0}", partition.PartitionLength);
+ }
+
+ return true;
}
- catch(Exception ex)
+ catch (Exception ex)
{
- Console.WriteLine("Exception trying to identify image file {0}", this.imagePath);
+ Console.WriteLine("Exception trying to identify image file {0}", imagePath);
Console.WriteLine("Exception: {0}", ex.Message);
Console.WriteLine("Stack trace: {0}", ex.StackTrace);
return false;
@@ -510,95 +1137,569 @@ namespace FileSystemIDandChk.ImagePlugins
public override UInt64 GetImageSize()
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ UInt64 size;
+
+ size = 0;
+ foreach (CDRWinTrack track in discimage.tracks)
+ size += track.bps * track.sectors;
+
+ return size;
}
+
public override UInt64 GetSectors()
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ UInt64 sectors;
+
+ sectors = 0;
+ foreach (CDRWinTrack track in discimage.tracks)
+ sectors += track.sectors;
+
+ return sectors;
}
+
public override UInt32 GetSectorSize()
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ if (discimage.disktype == DiskType.CDG || discimage.disktype == DiskType.CDEG || discimage.disktype == DiskType.CDMIDI)
+ return 2448; // CD+G subchannels ARE user data, as CD+G are useless without them
+ if (discimage.disktype != DiskType.CDROMXA && discimage.disktype != DiskType.CDDA && discimage.disktype != DiskType.CDI && discimage.disktype != DiskType.CDPLUS)
+ return 2048; // Only data tracks
+ return 2352; // All others
}
public override byte[] ReadDiskTag(DiskTagType tag)
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ switch (tag)
+ {
+ case DiskTagType.CD_MCN:
+ {
+ if (discimage.mcn != null)
+ {
+ return Encoding.ASCII.GetBytes(discimage.mcn);
+ }
+ throw new FeatureNotPresentImageException("Image does not contain MCN information.");
+ }
+ case DiskTagType.CD_TEXT:
+ {
+ if (discimage.cdtextfile != null)
+ // TODO: Check that binary text file exists, open it, read it, send it to caller.
+ throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ throw new FeatureNotPresentImageException("Image does not contain CD-TEXT information.");
+ }
+ default:
+ throw new FeatureSupportedButNotImplementedImageException("Feature not supported by image format");
+ }
}
- public override byte[] ReadSector(UInt64 SectorAddress)
+ public override byte[] ReadSector(UInt64 sectorAddress)
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ return ReadSectors(sectorAddress, 1);
}
- public override byte[] ReadSectorTag(UInt64 SectorAddress, SectorTagType tag)
+ public override byte[] ReadSectorTag(UInt64 sectorAddress, SectorTagType tag)
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ return ReadSectorsTag(sectorAddress, 1, tag);
}
- public override byte[] ReadSector(UInt64 SectorAddress, UInt32 track)
+ public override byte[] ReadSector(UInt64 sectorAddress, UInt32 track)
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ return ReadSectors(sectorAddress, 1, track);
}
- public override byte[] ReadSectorTag(UInt64 SectorAddress, UInt32 track, SectorTagType tag)
+ public override byte[] ReadSectorTag(UInt64 sectorAddress, UInt32 track, SectorTagType tag)
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ return ReadSectorsTag(sectorAddress, 1, track, tag);
}
- public override byte[] ReadSectors(UInt64 SectorAddress, UInt32 length)
+ public override byte[] ReadSectors(UInt64 sectorAddress, UInt32 length)
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ foreach (KeyValuePair kvp in offsetmap)
+ {
+ if (sectorAddress >= kvp.Value)
+ {
+ foreach (CDRWinTrack cdrwin_track in discimage.tracks)
+ {
+ if (cdrwin_track.sequence == kvp.Key)
+ {
+ if((sectorAddress - kvp.Value) < cdrwin_track.sectors)
+ return ReadSectors((sectorAddress - kvp.Value), length, kvp.Key);
+ }
+ }
+ }
+ }
+
+ throw new ArgumentOutOfRangeException("sectorAddress", "Sector address not found");
}
- public override byte[] ReadSectorsTag(UInt64 SectorAddress, UInt32 length, SectorTagType tag)
+ public override byte[] ReadSectorsTag(UInt64 sectorAddress, UInt32 length, SectorTagType tag)
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ foreach (KeyValuePair kvp in offsetmap)
+ {
+ if (sectorAddress >= kvp.Value)
+ {
+ foreach (CDRWinTrack cdrwin_track in discimage.tracks)
+ {
+ if (cdrwin_track.sequence == kvp.Key)
+ {
+ if((sectorAddress - kvp.Value) < cdrwin_track.sectors)
+ return ReadSectorsTag((sectorAddress - kvp.Value), length, kvp.Key, tag);
+ }
+ }
+ }
+ }
+
+ throw new ArgumentOutOfRangeException("sectorAddress", "Sector address not found");
}
- public override byte[] ReadSectors(UInt64 SectorAddress, UInt32 length, UInt32 track)
+ public override byte[] ReadSectors(UInt64 sectorAddress, UInt32 length, UInt32 track)
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ CDRWinTrack _track = new CDRWinTrack();
+
+ _track.sequence = 0;
+
+ foreach (CDRWinTrack cdrwin_track in discimage.tracks)
+ {
+ if (cdrwin_track.sequence == track)
+ {
+ _track = cdrwin_track;
+ break;
+ }
+ }
+
+ if (_track.sequence == 0)
+ throw new ArgumentOutOfRangeException("track", "Track does not exist in disc image");
+
+ if (length > _track.sectors)
+ throw new ArgumentOutOfRangeException("length", "Requested more sectors than present in track, won't cross tracks");
+
+ uint sector_offset;
+ uint sector_size;
+ uint sector_skip;
+
+ switch (_track.tracktype)
+ {
+ case CDRWinTrackTypeMode1:
+ case CDRWinTrackTypeMode2Form1:
+ {
+ sector_offset = 0;
+ sector_size = 2048;
+ sector_skip = 0;
+ break;
+ }
+ case CDRWinTrackTypeMode2Form2:
+ {
+ sector_offset = 0;
+ sector_size = 2324;
+ sector_skip = 0;
+ break;
+ }
+ case CDRWinTrackTypeMode2Formless:
+ case CDRWinTrackTypeCDI:
+ {
+ sector_offset = 0;
+ sector_size = 2336;
+ sector_skip = 0;
+ break;
+ }
+ case CDRWinTrackTypeAudio:
+ {
+ sector_offset = 0;
+ sector_size = 2352;
+ sector_skip = 0;
+ break;
+ }
+ case CDRWinTrackTypeMode1Raw:
+ {
+ sector_offset = 16;
+ sector_size = 2048;
+ sector_skip = 288;
+ break;
+ }
+ case CDRWinTrackTypeMode2Raw:
+ {
+ sector_offset = 16;
+ sector_size = 2336;
+ sector_skip = 0;
+ break;
+ }
+ case CDRWinTrackTypeCDIRaw:
+ {
+ sector_offset = 16;
+ sector_size = 2336;
+ sector_skip = 0;
+ break;
+ }
+ case CDRWinTrackTypeCDG:
+ {
+ sector_offset = 0;
+ sector_size = 2352;
+ sector_skip = 96;
+ break;
+ }
+ default:
+ throw new FeatureSupportedButNotImplementedImageException("Unsupported track type");
+ }
+
+ byte[] buffer = new byte[sector_size * length];
+
+ this.imageStream = new FileStream(_track.trackfile.datafile, FileMode.Open, FileAccess.Read);
+ BinaryReader br = new BinaryReader(this.imageStream);
+
+ br.BaseStream.Seek((long)_track.trackfile.offset + (long)(sectorAddress*(sector_offset + sector_size + sector_skip)), SeekOrigin.Begin);
+
+ if (sector_offset == 0 && sector_skip == 0)
+ buffer = br.ReadBytes((int)(sector_size * length));
+ else
+ {
+ for (int i = 0; i < length; i++)
+ {
+ byte[] sector = new byte[sector_size];
+ br.BaseStream.Seek(sector_offset, SeekOrigin.Current);
+ sector = br.ReadBytes((int)sector_size);
+ br.BaseStream.Seek(sector_skip, SeekOrigin.Current);
+
+ System.Array.Copy(sector, 0, buffer, i * sector_size, sector_size);
+ }
+ }
+
+ return buffer;
}
- public override byte[] ReadSectorsTag(UInt64 SectorAddress, UInt32 length, UInt32 track, SectorTagType tag)
+ public override byte[] ReadSectorsTag(UInt64 sectorAddress, UInt32 length, UInt32 track, SectorTagType tag)
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ CDRWinTrack _track = new CDRWinTrack();
+
+ _track.sequence = 0;
+
+ foreach (CDRWinTrack cdrwin_track in discimage.tracks)
+ {
+ if (cdrwin_track.sequence == track)
+ {
+ _track = cdrwin_track;
+ break;
+ }
+ }
+
+ if (_track.sequence == 0)
+ throw new ArgumentOutOfRangeException("track", "Track does not exist in disc image");
+
+ if (length > _track.sectors)
+ throw new ArgumentOutOfRangeException("length", "Requested more sectors than present in track, won't cross tracks");
+
+ uint sector_offset;
+ uint sector_size;
+ uint sector_skip;
+
+ switch (tag)
+ {
+ case SectorTagType.CDSectorECC:
+ case SectorTagType.CDSectorECC_P:
+ case SectorTagType.CDSectorECC_Q:
+ case SectorTagType.CDSectorEDC:
+ case SectorTagType.CDSectorHeader:
+ case SectorTagType.CDSectorSubchannel:
+ case SectorTagType.CDSectorSubHeader:
+ case SectorTagType.CDSectorSync:
+ break;
+ case SectorTagType.CDTrackFlags:
+ {
+ byte[] flags = new byte[1];
+
+ if (_track.tracktype != CDRWinTrackTypeAudio && _track.tracktype != CDRWinTrackTypeCDG)
+ flags[0] += 0x40;
+
+ if (_track.flag_dcp)
+ flags[0] += 0x20;
+
+ if (_track.flag_pre)
+ flags[0] += 0x10;
+
+ return flags;
+ }
+ case SectorTagType.CDTrackISRC:
+ return Encoding.UTF8.GetBytes(_track.isrc);
+ case SectorTagType.CDTrackText:
+ throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ default:
+ throw new ArgumentException("Unsupported tag requested", "tag");
+ }
+
+ switch (_track.tracktype)
+ {
+ case CDRWinTrackTypeMode1:
+ case CDRWinTrackTypeMode2Form1:
+ case CDRWinTrackTypeMode2Form2:
+ throw new ArgumentException("No tags in image for requested track", "tag");
+ case CDRWinTrackTypeMode2Formless:
+ case CDRWinTrackTypeCDI:
+ {
+ switch (tag)
+ {
+ case SectorTagType.CDSectorSync:
+ case SectorTagType.CDSectorHeader:
+ case SectorTagType.CDSectorSubchannel:
+ case SectorTagType.CDSectorECC:
+ case SectorTagType.CDSectorECC_P:
+ case SectorTagType.CDSectorECC_Q:
+ throw new ArgumentException("Unsupported tag requested for this track", "tag");
+ case SectorTagType.CDSectorSubHeader:
+ {
+ sector_offset = 0;
+ sector_size = 8;
+ sector_skip = 2328;
+ break;
+ }
+ case SectorTagType.CDSectorEDC:
+ {
+ sector_offset = 2332;
+ sector_size = 4;
+ sector_skip = 0;
+ break;
+ }
+ default:
+ throw new ArgumentException("Unsupported tag requested", "tag");
+ }
+ break;
+ }
+ case CDRWinTrackTypeAudio:
+ throw new ArgumentException("There are no tags on audio tracks", "tag");
+ case CDRWinTrackTypeMode1Raw:
+ {
+ switch (tag)
+ {
+ case SectorTagType.CDSectorSync:
+ {
+ sector_offset = 0;
+ sector_size = 12;
+ sector_skip = 2340;
+ break;
+ }
+ case SectorTagType.CDSectorHeader:
+ {
+ sector_offset = 12;
+ sector_size = 4;
+ sector_skip = 2336;
+ break;
+ }
+ case SectorTagType.CDSectorSubchannel:
+ case SectorTagType.CDSectorSubHeader:
+ throw new ArgumentException("Unsupported tag requested for this track", "tag");
+ case SectorTagType.CDSectorECC:
+ {
+ sector_offset = 2076;
+ sector_size = 276;
+ sector_skip = 0;
+ break;
+ }
+ case SectorTagType.CDSectorECC_P:
+ {
+ sector_offset = 2076;
+ sector_size = 172;
+ sector_skip = 104;
+ break;
+ }
+ case SectorTagType.CDSectorECC_Q:
+ {
+ sector_offset = 2248;
+ sector_size = 104;
+ sector_skip = 0;
+ break;
+ }
+ case SectorTagType.CDSectorEDC:
+ {
+ sector_offset = 2064;
+ sector_size = 4;
+ sector_skip = 284;
+ break;
+ }
+ default:
+ throw new ArgumentException("Unsupported tag requested", "tag");
+ }
+ break;
+ }
+ case CDRWinTrackTypeMode2Raw: // Requires reading sector
+ case CDRWinTrackTypeCDIRaw:
+ throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ case CDRWinTrackTypeCDG:
+ {
+ if(tag != SectorTagType.CDSectorSubchannel)
+ throw new ArgumentException("Unsupported tag requested for this track", "tag");
+
+ sector_offset = 2352;
+ sector_size = 96;
+ sector_skip = 0;
+ break;
+ }
+ default:
+ throw new FeatureSupportedButNotImplementedImageException("Unsupported track type");
+ }
+
+ byte[] buffer = new byte[sector_size * length];
+
+ this.imageStream = new FileStream(_track.trackfile.datafile, FileMode.Open, FileAccess.Read);
+ BinaryReader br = new BinaryReader(this.imageStream);
+
+ br.BaseStream.Seek((long)_track.trackfile.offset + (long)(sectorAddress*(sector_offset + sector_size + sector_skip)), SeekOrigin.Begin);
+
+ if (sector_offset == 0 && sector_skip == 0)
+ buffer = br.ReadBytes((int)(sector_size * length));
+ else
+ {
+ for (int i = 0; i < length; i++)
+ {
+ byte[] sector = new byte[sector_size];
+ br.BaseStream.Seek(sector_offset, SeekOrigin.Current);
+ sector = br.ReadBytes((int)sector_size);
+ br.BaseStream.Seek(sector_skip, SeekOrigin.Current);
+
+ System.Array.Copy(sector, 0, buffer, i * sector_size, sector_size);
+ }
+ }
+
+ return buffer;
}
- public override byte[] ReadSectorLong(UInt64 SectorAddress)
+ public override byte[] ReadSectorLong(UInt64 sectorAddress)
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ return ReadSectorsLong(sectorAddress, 1);
}
- public override byte[] ReadSectorLong(UInt64 SectorAddress, UInt32 track)
+ public override byte[] ReadSectorLong(UInt64 sectorAddress, UInt32 track)
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ return ReadSectorsLong(sectorAddress, 1, track);
}
- public override byte[] ReadSectorsLong(UInt64 SectorAddress, UInt32 length)
+ public override byte[] ReadSectorsLong(UInt64 sectorAddress, UInt32 length)
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ foreach (KeyValuePair kvp in offsetmap)
+ {
+ if (sectorAddress >= kvp.Value)
+ {
+ foreach (CDRWinTrack cdrwin_track in discimage.tracks)
+ {
+ if (cdrwin_track.sequence == kvp.Key)
+ {
+ if((sectorAddress - kvp.Value) < cdrwin_track.sectors)
+ return ReadSectorsLong((sectorAddress - kvp.Value), length, kvp.Key);
+ }
+ }
+ }
+ }
+
+ throw new ArgumentOutOfRangeException("sectorAddress", "Sector address not found");
}
- public override byte[] ReadSectorsLong(UInt64 SectorAddress, UInt32 length, UInt32 track)
+ public override byte[] ReadSectorsLong(UInt64 sectorAddress, UInt32 length, UInt32 track)
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ CDRWinTrack _track = new CDRWinTrack();
+
+ _track.sequence = 0;
+
+ foreach (CDRWinTrack cdrwin_track in discimage.tracks)
+ {
+ if (cdrwin_track.sequence == track)
+ {
+ _track = cdrwin_track;
+ break;
+ }
+ }
+
+ if (_track.sequence == 0)
+ throw new ArgumentOutOfRangeException("track", "Track does not exist in disc image");
+
+ if (length > _track.sectors)
+ throw new ArgumentOutOfRangeException("length", "Requested more sectors than present in track, won't cross tracks");
+
+ uint sector_offset;
+ uint sector_size;
+ uint sector_skip;
+
+ switch (_track.tracktype)
+ {
+ case CDRWinTrackTypeMode1:
+ case CDRWinTrackTypeMode2Form1:
+ {
+ sector_offset = 0;
+ sector_size = 2048;
+ sector_skip = 0;
+ break;
+ }
+ case CDRWinTrackTypeMode2Form2:
+ {
+ sector_offset = 0;
+ sector_size = 2324;
+ sector_skip = 0;
+ break;
+ }
+ case CDRWinTrackTypeMode2Formless:
+ case CDRWinTrackTypeCDI:
+ {
+ sector_offset = 0;
+ sector_size = 2336;
+ sector_skip = 0;
+ break;
+ }
+ case CDRWinTrackTypeMode1Raw:
+ case CDRWinTrackTypeMode2Raw:
+ case CDRWinTrackTypeCDIRaw:
+ case CDRWinTrackTypeAudio:
+ {
+ sector_offset = 0;
+ sector_size = 2352;
+ sector_skip = 0;
+ break;
+ }
+ case CDRWinTrackTypeCDG:
+ {
+ sector_offset = 0;
+ sector_size = 2448;
+ sector_skip = 0;
+ break;
+ }
+ default:
+ throw new FeatureSupportedButNotImplementedImageException("Unsupported track type");
+ }
+
+ byte[] buffer = new byte[sector_size * length];
+
+ this.imageStream = new FileStream(_track.trackfile.datafile, FileMode.Open, FileAccess.Read);
+ BinaryReader br = new BinaryReader(this.imageStream);
+
+ br.BaseStream.Seek((long)_track.trackfile.offset + (long)(sectorAddress*(sector_offset + sector_size + sector_skip)), SeekOrigin.Begin);
+
+ if (sector_offset == 0 && sector_skip == 0)
+ buffer = br.ReadBytes((int)(sector_size * length));
+ else
+ {
+ for (int i = 0; i < length; i++)
+ {
+ byte[] sector = new byte[sector_size];
+ br.BaseStream.Seek(sector_offset, SeekOrigin.Current);
+ sector = br.ReadBytes((int)sector_size);
+ br.BaseStream.Seek(sector_skip, SeekOrigin.Current);
+
+ System.Array.Copy(sector, 0, buffer, i * sector_size, sector_size);
+ }
+ }
+
+ return buffer;
}
public override string GetImageFormat()
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ return "CDRWin CUESheet";
}
public override string GetImageVersion()
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ return null;
}
public override string GetImageApplication()
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ // Detect ISOBuster extensions
+ if (discimage.disktypestr != null || discimage.comment.ToLower().Contains("isobuster") || discimage.sessions.Count > 1)
+ return "ISOBuster";
+ return "CDRWin";
}
public override string GetImageApplicationVersion()
@@ -608,111 +1709,290 @@ namespace FileSystemIDandChk.ImagePlugins
public override DateTime GetImageCreationTime()
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ FileInfo fi = new FileInfo(discimage.tracks[0].trackfile.datafile);
+
+ return fi.CreationTimeUtc;
}
public override DateTime GetImageLastModificationTime()
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ FileInfo fi = new FileInfo(discimage.tracks[0].trackfile.datafile);
+
+ return fi.LastWriteTimeUtc;
}
public override string GetImageComments()
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ return discimage.comment;
}
public override string GetDiskSerialNumber()
{
- return this.GetDiskBarcode();
+ return discimage.mcn;
}
public override string GetDiskBarcode()
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ return discimage.barcode;
}
public override DiskType GetDiskType()
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ return discimage.disktype;
}
public override List GetPartitions()
{
- throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
+ return partitions;
}
public override List