🐛Correct track flags on CD images.

This commit is contained in:
2018-01-01 21:32:12 +00:00
parent 4756fd8e7c
commit aa493b53e5
6 changed files with 1171 additions and 1117 deletions

View File

@@ -70,8 +70,7 @@ namespace DiscImageChef.DiscImages
const string REGEX_DISCTYPE = @"^\s*(?<type>(CD_DA|CD_ROM_XA|CD_ROM|CD_I))";
const string REGEX_EMPHASIS = @"^\s*(?<no>NO)?\s*PRE_EMPHASIS";
const string REGEX_FILE_AUDIO =
@"^\s*(AUDIO)?FILE\s*""(?<filename>.+)""\s*(#(?<base_offset>\d+))?\s*((?<start>[\d]+:[\d]+:[\d]+)|(?<start_num>\d+))\s*(?<length>[\d]+:[\d]+:[\d]+)?"
;
@"^\s*(AUDIO)?FILE\s*""(?<filename>.+)""\s*(#(?<base_offset>\d+))?\s*((?<start>[\d]+:[\d]+:[\d]+)|(?<start_num>\d+))\s*(?<length>[\d]+:[\d]+:[\d]+)?";
const string REGEX_FILE_DATA =
@"^\s*DATAFILE\s*""(?<filename>.+)""\s*(#(?<base_offset>\d+))?\s*(?<length>[\d]+:[\d]+:[\d]+)?";
const string REGEX_INDEX = @"^\s*INDEX\s*(?<address>\d+:\d+:\d+)";
@@ -80,8 +79,7 @@ namespace DiscImageChef.DiscImages
const string REGEX_PREGAP = @"^\s*START\s*(?<address>\d+:\d+:\d+)?";
const string REGEX_STEREO = @"^\s*(?<num>(TWO|FOUR))_CHANNEL_AUDIO";
const string REGEX_TRACK =
@"^\s*TRACK\s*(?<type>(AUDIO|MODE1_RAW|MODE1|MODE2_FORM1|MODE2_FORM2|MODE2_FORM_MIX|MODE2_RAW|MODE2))\s*(?<subchan>(RW_RAW|RW))?"
;
@"^\s*TRACK\s*(?<type>(AUDIO|MODE1_RAW|MODE1|MODE2_FORM1|MODE2_FORM2|MODE2_FORM_MIX|MODE2_RAW|MODE2))\s*(?<subchan>(RW_RAW|RW))?";
const string REGEX_ZERO_AUDIO = @"^\s*SILENCE\s*(?<length>\d+:\d+:\d+)";
const string REGEX_ZERO_DATA = @"^\s*ZERO\s*(?<length>\d+:\d+:\d+)";
const string REGEX_ZERO_PREGAP = @"^\s*PREGAP\s*(?<length>\d+:\d+:\d+)";
@@ -109,7 +107,6 @@ namespace DiscImageChef.DiscImages
Stream imageStream;
/// <summary>Dictionary, index is track #, value is TrackFile</summary>
Dictionary<uint, ulong> offsetmap;
List<Partition> partitions;
StreamReader tocStream;
public Cdrdao()
@@ -143,7 +140,7 @@ namespace DiscImageChef.DiscImages
public string Format => "CDRDAO tocfile";
public List<Partition> Partitions => partitions;
public List<Partition> Partitions { get; set; }
public List<Track> Tracks
{
@@ -429,6 +426,7 @@ namespace DiscImageChef.DiscImages
currenttrack = new CdrdaoTrack {Indexes = new Dictionary<int, ulong>(), Pregap = 0};
nextindex = 2;
}
currentTrackNumber++;
intrack = true;
@@ -506,7 +504,8 @@ namespace DiscImageChef.DiscImages
string[] lengthString = matchFile.Groups["length"].Value.Split(':');
ulong nextIndexPos = ulong.Parse(lengthString[0]) * 60 * 75 +
ulong.Parse(lengthString[1]) * 75 + ulong.Parse(lengthString[2]);
ulong.Parse(lengthString[1]) * 75 +
ulong.Parse(lengthString[2]);
currenttrack.Indexes.Add(nextindex,
nextIndexPos + currenttrack.Pregap + currenttrack.StartSector);
}
@@ -520,7 +519,8 @@ namespace DiscImageChef.DiscImages
{
string[] lengthString = matchPregap.Groups["address"].Value.Split(':');
currenttrack.Pregap = ulong.Parse(lengthString[0]) * 60 * 75 +
ulong.Parse(lengthString[1]) * 75 + ulong.Parse(lengthString[2]);
ulong.Parse(lengthString[1]) * 75 +
ulong.Parse(lengthString[2]);
}
else currenttrack.Pregap = currenttrack.Sectors;
}
@@ -567,7 +567,8 @@ namespace DiscImageChef.DiscImages
{
string[] startString = matchAudioFile.Groups["start"].Value.Split(':');
startSectors = ulong.Parse(startString[0]) * 60 * 75 +
ulong.Parse(startString[1]) * 75 + ulong.Parse(startString[2]);
ulong.Parse(startString[1]) * 75 +
ulong.Parse(startString[2]);
}
currenttrack.Trackfile.Offset += startSectors * currenttrack.Bps;
@@ -576,7 +577,8 @@ namespace DiscImageChef.DiscImages
{
string[] lengthString = matchAudioFile.Groups["length"].Value.Split(':');
currenttrack.Sectors = ulong.Parse(lengthString[0]) * 60 * 75 +
ulong.Parse(lengthString[1]) * 75 + ulong.Parse(lengthString[2]);
ulong.Parse(lengthString[1]) * 75 +
ulong.Parse(lengthString[2]);
}
else
currenttrack.Sectors =
@@ -606,7 +608,8 @@ namespace DiscImageChef.DiscImages
{
string[] lengthString = matchFile.Groups["length"].Value.Split(':');
currenttrack.Sectors = ulong.Parse(lengthString[0]) * 60 * 75 +
ulong.Parse(lengthString[1]) * 75 + ulong.Parse(lengthString[2]);
ulong.Parse(lengthString[1]) * 75 +
ulong.Parse(lengthString[2]);
}
else
currenttrack.Sectors =
@@ -673,6 +676,7 @@ namespace DiscImageChef.DiscImages
else if(line == "") // Empty line, ignore it
{ }
}
// TODO: Regex CD-TEXT SIZE_INFO
/*
else // Non-empty unknown field
@@ -693,26 +697,43 @@ namespace DiscImageChef.DiscImages
discimage.Comment = commentBuilder.ToString();
// DEBUG information
DicConsole.DebugWriteLine("CDRDAO plugin", "Disc image parsing results");
DicConsole.DebugWriteLine("CDRDAO plugin",
"Disc image parsing results");
DicConsole.DebugWriteLine("CDRDAO plugin", "Disc CD-TEXT:");
if(discimage.Arranger == null) DicConsole.DebugWriteLine("CDRDAO plugin", "\tArranger is not set.");
else DicConsole.DebugWriteLine("CDRDAO plugin", "\tArranger: {0}", discimage.Arranger);
else
DicConsole.DebugWriteLine("CDRDAO plugin", "\tArranger: {0}",
discimage.Arranger);
if(discimage.Composer == null) DicConsole.DebugWriteLine("CDRDAO plugin", "\tComposer is not set.");
else DicConsole.DebugWriteLine("CDRDAO plugin", "\tComposer: {0}", discimage.Composer);
else
DicConsole.DebugWriteLine("CDRDAO plugin", "\tComposer: {0}",
discimage.Composer);
if(discimage.Performer == null) DicConsole.DebugWriteLine("CDRDAO plugin", "\tPerformer is not set.");
else DicConsole.DebugWriteLine("CDRDAO plugin", "\tPerformer: {0}", discimage.Performer);
else
DicConsole.DebugWriteLine("CDRDAO plugin", "\tPerformer: {0}",
discimage.Performer);
if(discimage.Songwriter == null) DicConsole.DebugWriteLine("CDRDAO plugin", "\tSongwriter is not set.");
else DicConsole.DebugWriteLine("CDRDAO plugin", "\tSongwriter: {0}", discimage.Songwriter);
else
DicConsole.DebugWriteLine("CDRDAO plugin", "\tSongwriter: {0}",
discimage.Songwriter);
if(discimage.Title == null) DicConsole.DebugWriteLine("CDRDAO plugin", "\tTitle is not set.");
else DicConsole.DebugWriteLine("CDRDAO plugin", "\tTitle: {0}", discimage.Title);
else
DicConsole.DebugWriteLine("CDRDAO plugin", "\tTitle: {0}",
discimage.Title);
DicConsole.DebugWriteLine("CDRDAO plugin", "Disc information:");
DicConsole.DebugWriteLine("CDRDAO plugin", "\tGuessed disk type: {0}", discimage.Disktype);
DicConsole.DebugWriteLine("CDRDAO plugin", "\tGuessed disk type: {0}",
discimage.Disktype);
if(discimage.Barcode == null) DicConsole.DebugWriteLine("CDRDAO plugin", "\tBarcode not set.");
else DicConsole.DebugWriteLine("CDRDAO plugin", "\tBarcode: {0}", discimage.Barcode);
else
DicConsole.DebugWriteLine("CDRDAO plugin", "\tBarcode: {0}",
discimage.Barcode);
if(discimage.DiskId == null) DicConsole.DebugWriteLine("CDRDAO plugin", "\tDisc ID not set.");
else DicConsole.DebugWriteLine("CDRDAO plugin", "\tDisc ID: {0}", discimage.DiskId);
else
DicConsole.DebugWriteLine("CDRDAO plugin", "\tDisc ID: {0}",
discimage.DiskId);
if(discimage.Mcn == null) DicConsole.DebugWriteLine("CDRDAO plugin", "\tMCN not set.");
else DicConsole.DebugWriteLine("CDRDAO plugin", "\tMCN: {0}", discimage.Mcn);
else
DicConsole.DebugWriteLine("CDRDAO plugin", "\tMCN: {0}", discimage.Mcn);
if(string.IsNullOrEmpty(discimage.Comment))
DicConsole.DebugWriteLine("CDRDAO plugin", "\tComment not set.");
else DicConsole.DebugWriteLine("CDRDAO plugin", "\tComment: \"{0}\"", discimage.Comment);
@@ -774,7 +795,7 @@ namespace DiscImageChef.DiscImages
DicConsole.DebugWriteLine("CDRDAO plugin", "Building offset map");
partitions = new List<Partition>();
Partitions = new List<Partition>();
offsetmap = new Dictionary<uint, ulong>();
ulong byteOffset = 0;
@@ -815,16 +836,17 @@ namespace DiscImageChef.DiscImages
}
}
partitions.Add(partition);
Partitions.Add(partition);
}
// Print partition map
DicConsole.DebugWriteLine("CDRDAO plugin", "printing partition map");
foreach(Partition partition in partitions)
foreach(Partition partition in Partitions)
{
DicConsole.DebugWriteLine("CDRDAO plugin", "Partition sequence: {0}", partition.Sequence);
DicConsole.DebugWriteLine("CDRDAO plugin", "\tPartition name: {0}", partition.Name);
DicConsole.DebugWriteLine("CDRDAO plugin", "\tPartition description: {0}", partition.Description);
DicConsole.DebugWriteLine("CDRDAO plugin", "\tPartition description: {0}",
partition.Description);
DicConsole.DebugWriteLine("CDRDAO plugin", "\tPartition type: {0}", partition.Type);
DicConsole.DebugWriteLine("CDRDAO plugin", "\tPartition starting sector: {0}", partition.Start);
DicConsole.DebugWriteLine("CDRDAO plugin", "\tPartition sectors: {0}", partition.Length);
@@ -842,9 +864,10 @@ namespace DiscImageChef.DiscImages
discimage.Disktype == MediaType.CDMIDI)
imageInfo.SectorSize = 2448; // CD+G subchannels ARE user data, as CD+G are useless without them
else if(discimage.Disktype != MediaType.CDROMXA && discimage.Disktype != MediaType.CDDA &&
discimage.Disktype != MediaType.CDI &&
discimage.Disktype != MediaType.CDPLUS) imageInfo.SectorSize = 2048; // Only data tracks
else imageInfo.SectorSize = 2352; // All others
discimage.Disktype != MediaType.CDI && discimage.Disktype != MediaType.CDPLUS)
imageInfo.SectorSize = 2048; // Only data tracks
else
imageInfo.SectorSize = 2352; // All others
if(discimage.Mcn != null) imageInfo.ReadableMediaTags.Add(MediaTagType.CD_MCN);
@@ -1122,17 +1145,17 @@ namespace DiscImageChef.DiscImages
case SectorTagType.CdSectorSync: break;
case SectorTagType.CdTrackFlags:
{
byte[] flags = new byte[1];
CdFlags flags = 0;
if(dicTrack.Tracktype != CDRDAO_TRACK_TYPE_AUDIO) flags[0] += 0x40;
if(dicTrack.Tracktype != CDRDAO_TRACK_TYPE_AUDIO) flags |= CdFlags.DataTrack;
if(dicTrack.FlagDcp) flags[0] += 0x20;
if(dicTrack.FlagDcp) flags |= CdFlags.CopyPermitted;
if(dicTrack.FlagPre) flags[0] += 0x10;
if(dicTrack.FlagPre) flags |= CdFlags.PreEmphasis;
if(dicTrack.Flag_4Ch) flags[0] += 0x80;
if(dicTrack.Flag_4Ch) flags |= CdFlags.FourChannel;
return flags;
return new[] {(byte)flags};
}
case SectorTagType.CdTrackIsrc: return Encoding.UTF8.GetBytes(dicTrack.Isrc);
default: throw new ArgumentException("Unsupported tag requested", nameof(tag));

View File

@@ -1438,18 +1438,18 @@ namespace DiscImageChef.DiscImages
case SectorTagType.CdSectorSync: break;
case SectorTagType.CdTrackFlags:
{
byte[] flags = new byte[1];
CdFlags flags = 0;
if(dicTrack.Tracktype != CDRWIN_TRACK_TYPE_AUDIO && dicTrack.Tracktype != CDRWIN_TRACK_TYPE_CDG)
flags[0] += 0x40;
flags |= CdFlags.DataTrack;
if(dicTrack.FlagDcp) flags[0] += 0x20;
if(dicTrack.FlagDcp) flags |= CdFlags.CopyPermitted;
if(dicTrack.FlagPre) flags[0] += 0x10;
if(dicTrack.FlagPre) flags |= CdFlags.PreEmphasis;
if(dicTrack.Flag4ch) flags[0] += 0x80;
if(dicTrack.Flag4ch) flags |= CdFlags.FourChannel;
return flags;
return new[] {(byte)flags};
}
case SectorTagType.CdTrackIsrc: return Encoding.UTF8.GetBytes(dicTrack.Isrc);
case SectorTagType.CdTrackText:

View File

@@ -85,12 +85,10 @@ namespace DiscImageChef.DiscImages
byte[] fulltoc;
ImageInfo imageInfo;
Dictionary<uint, ulong> offsetmap;
List<Partition> partitions;
bool scrambled;
List<Session> sessions;
IFilter subFilter;
Stream subStream;
List<Track> tracks;
Dictionary<byte, byte> trackFlags;
public CloneCd()
{
@@ -123,11 +121,11 @@ namespace DiscImageChef.DiscImages
public string Format => "CloneCD";
public List<Partition> Partitions => partitions;
public List<Partition> Partitions { get; set; }
public List<Track> Tracks => tracks;
public List<Track> Tracks { get; set; }
public List<Session> Sessions => sessions;
public List<Session> Sessions { get; set; }
public bool Identify(IFilter imageFilter)
{
@@ -368,7 +366,8 @@ namespace DiscImageChef.DiscImages
if(entSessMatch.Success)
{
DicConsole.DebugWriteLine("CloneCD plugin", "Found Session at line {0}", lineNumber);
currentEntry.SessionNumber = Convert.ToByte(entSessMatch.Groups["value"].Value, 10);
currentEntry.SessionNumber =
Convert.ToByte(entSessMatch.Groups["value"].Value, 10);
if(currentEntry.SessionNumber < minSession) minSession = currentEntry.SessionNumber;
if(currentEntry.SessionNumber > maxSession) maxSession = currentEntry.SessionNumber;
}
@@ -484,11 +483,12 @@ namespace DiscImageChef.DiscImages
int curSessionNo = 0;
Track currentTrack = new Track();
bool firstTrackInSession = true;
tracks = new List<Track>();
Tracks = new List<Track>();
ulong leadOutStart = 0;
dataStream = dataFilter.GetDataForkStream();
if(subFilter != null) subStream = subFilter.GetDataForkStream();
trackFlags = new Dictionary<byte, byte>();
foreach(FullTOC.TrackDataDescriptor descriptor in entries)
{
@@ -498,8 +498,9 @@ namespace DiscImageChef.DiscImages
if(!firstTrackInSession)
{
currentTrack.TrackEndSector = leadOutStart - 1;
tracks.Add(currentTrack);
Tracks.Add(currentTrack);
}
firstTrackInSession = true;
}
@@ -525,7 +526,7 @@ namespace DiscImageChef.DiscImages
currentTrack.TrackEndSector =
GetLba(descriptor.PHOUR, descriptor.PMIN, descriptor.PSEC,
descriptor.PFRAME) - 1;
tracks.Add(currentTrack);
Tracks.Add(currentTrack);
}
else firstTrackInSession = false;
@@ -550,6 +551,9 @@ namespace DiscImageChef.DiscImages
currentTrack.TrackType = TrackType.Data;
else currentTrack.TrackType = TrackType.Audio;
if(!trackFlags.ContainsKey(descriptor.POINT))
trackFlags.Add(descriptor.POINT, descriptor.CONTROL);
if(subFilter != null)
{
currentTrack.TrackSubchannelFile = subFilter.GetFilename();
@@ -608,8 +612,7 @@ namespace DiscImageChef.DiscImages
currentTrack.TrackBytesPerSector = 2324;
currentTrack.TrackType = TrackType.CdMode2Form2;
if(!imageInfo.ReadableSectorTags.Contains(SectorTagType
.CdSectorSync)
)
.CdSectorSync))
imageInfo.ReadableSectorTags.Add(SectorTagType
.CdSectorSync);
if(!imageInfo.ReadableSectorTags.Contains(SectorTagType
@@ -633,8 +636,7 @@ namespace DiscImageChef.DiscImages
currentTrack.TrackBytesPerSector = 2048;
currentTrack.TrackType = TrackType.CdMode2Form1;
if(!imageInfo.ReadableSectorTags.Contains(SectorTagType
.CdSectorSync)
)
.CdSectorSync))
imageInfo.ReadableSectorTags.Add(SectorTagType
.CdSectorSync);
if(!imageInfo.ReadableSectorTags.Contains(SectorTagType
@@ -652,13 +654,11 @@ namespace DiscImageChef.DiscImages
imageInfo.ReadableSectorTags.Add(SectorTagType
.CdSectorEcc);
if(!imageInfo.ReadableSectorTags.Contains(SectorTagType
.CdSectorEccP)
)
.CdSectorEccP))
imageInfo.ReadableSectorTags.Add(SectorTagType
.CdSectorEccP);
if(!imageInfo.ReadableSectorTags.Contains(SectorTagType
.CdSectorEccQ)
)
.CdSectorEccQ))
imageInfo.ReadableSectorTags.Add(SectorTagType
.CdSectorEccQ);
if(!imageInfo.ReadableSectorTags.Contains(SectorTagType
@@ -684,8 +684,12 @@ namespace DiscImageChef.DiscImages
}
}
}
else { if(imageInfo.SectorSize < 2352) imageInfo.SectorSize = 2352; }
else
{
if(imageInfo.SectorSize < 2352) imageInfo.SectorSize = 2352;
}
}
break;
}
@@ -705,6 +709,7 @@ namespace DiscImageChef.DiscImages
DicConsole.DebugWriteLine("CloneCD plugin", "Disc manufactured by: {0}",
imageInfo.MediaManufacturer);
}
break;
}
@@ -722,23 +727,25 @@ namespace DiscImageChef.DiscImages
if(!firstTrackInSession)
{
currentTrack.TrackEndSector = leadOutStart - 1;
tracks.Add(currentTrack);
Tracks.Add(currentTrack);
}
if(subFilter != null && !imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel))
imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel);
sessions = new List<Session>();
imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackFlags);
Sessions = new List<Session>();
Session currentSession = new Session
{
EndTrack = uint.MinValue,
StartTrack = uint.MaxValue,
SessionSequence = 1
};
partitions = new List<Partition>();
Partitions = new List<Partition>();
offsetmap = new Dictionary<uint, ulong>();
foreach(Track track in tracks)
foreach(Track track in Tracks)
{
if(track.TrackSession == currentSession.SessionSequence)
{
@@ -756,7 +763,7 @@ namespace DiscImageChef.DiscImages
}
else
{
sessions.Add(currentSession);
Sessions.Add(currentSession);
currentSession = new Session
{
EndTrack = uint.MinValue,
@@ -769,7 +776,8 @@ namespace DiscImageChef.DiscImages
{
Description = track.TrackDescription,
Size =
(track.TrackEndSector - track.TrackStartSector + 1) * (ulong)track.TrackRawBytesPerSector,
(track.TrackEndSector - track.TrackStartSector + 1) *
(ulong)track.TrackRawBytesPerSector,
Length = track.TrackEndSector - track.TrackStartSector + 1,
Sequence = track.TrackSequence,
Offset = track.TrackFileOffset,
@@ -777,7 +785,7 @@ namespace DiscImageChef.DiscImages
Type = track.TrackType.ToString()
};
imageInfo.Sectors += partition.Length;
partitions.Add(partition);
Partitions.Add(partition);
offsetmap.Add(track.TrackSequence, track.TrackStartSector);
}
@@ -787,21 +795,21 @@ namespace DiscImageChef.DiscImages
bool firstdata = false;
bool audio = false;
for(int i = 0; i < tracks.Count; i++)
for(int i = 0; i < Tracks.Count; i++)
{
// First track is audio
firstaudio |= i == 0 && tracks[i].TrackType == TrackType.Audio;
firstaudio |= i == 0 && Tracks[i].TrackType == TrackType.Audio;
// First track is data
firstdata |= i == 0 && tracks[i].TrackType != TrackType.Audio;
firstdata |= i == 0 && Tracks[i].TrackType != TrackType.Audio;
// Any non first track is data
data |= i != 0 && tracks[i].TrackType != TrackType.Audio;
data |= i != 0 && Tracks[i].TrackType != TrackType.Audio;
// Any non first track is audio
audio |= i != 0 && tracks[i].TrackType == TrackType.Audio;
audio |= i != 0 && Tracks[i].TrackType == TrackType.Audio;
switch(tracks[i].TrackType)
switch(Tracks[i].TrackType)
{
case TrackType.CdMode2Form1:
case TrackType.CdMode2Form2:
@@ -815,10 +823,14 @@ namespace DiscImageChef.DiscImages
cdtext = cdtMs.ToArray();
if(!data && !firstdata) imageInfo.MediaType = MediaType.CDDA;
else if(firstaudio && data && sessions.Count > 1 && mode2) imageInfo.MediaType = MediaType.CDPLUS;
else if(firstdata && audio || mode2) imageInfo.MediaType = MediaType.CDROMXA;
else if(!audio) imageInfo.MediaType = MediaType.CDROM;
else imageInfo.MediaType = MediaType.CD;
else if(firstaudio && data && Sessions.Count > 1 && mode2)
imageInfo.MediaType = MediaType.CDPLUS;
else if(firstdata && audio || mode2)
imageInfo.MediaType = MediaType.CDROMXA;
else if(!audio)
imageInfo.MediaType = MediaType.CDROM;
else
imageInfo.MediaType = MediaType.CD;
imageInfo.Application = "CloneCD";
imageInfo.ImageSize = (ulong)imageFilter.GetDataForkLength();
@@ -837,19 +849,11 @@ namespace DiscImageChef.DiscImages
}
}
static ulong GetLba(int hour, int minute, int second, int frame)
{
return (ulong)(hour * 60 * 60 * 75 + minute * 60 * 75 + second * 75 + frame - 150);
}
public byte[] ReadDiskTag(MediaTagType tag)
{
switch(tag)
{
case MediaTagType.CD_FullTOC:
{
return fulltoc;
}
case MediaTagType.CD_FullTOC: { return fulltoc; }
case MediaTagType.CD_TEXT:
{
if(cdtext != null && cdtext.Length > 0) return cdtext;
@@ -885,7 +889,7 @@ namespace DiscImageChef.DiscImages
{
foreach(KeyValuePair<uint, ulong> kvp in from kvp in offsetmap
where sectorAddress >= kvp.Value
from track in tracks
from track in Tracks
where track.TrackSequence == kvp.Key
where sectorAddress <= track.TrackEndSector
select kvp)
@@ -898,7 +902,7 @@ namespace DiscImageChef.DiscImages
{
foreach(KeyValuePair<uint, ulong> kvp in from kvp in offsetmap
where sectorAddress >= kvp.Value
from track in tracks
from track in Tracks
where track.TrackSequence == kvp.Key
where sectorAddress <= track.TrackEndSector
select kvp)
@@ -911,7 +915,7 @@ namespace DiscImageChef.DiscImages
{
Track dicTrack = new Track {TrackSequence = 0};
foreach(Track linqTrack in tracks.Where(linqTrack => linqTrack.TrackSequence == track))
foreach(Track linqTrack in Tracks.Where(linqTrack => linqTrack.TrackSequence == track))
{
dicTrack = linqTrack;
break;
@@ -988,12 +992,11 @@ namespace DiscImageChef.DiscImages
return buffer;
}
// TODO: Flags
public byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
{
Track dicTrack = new Track {TrackSequence = 0};
foreach(Track linqTrack in tracks.Where(linqTrack => linqTrack.TrackSequence == track))
foreach(Track linqTrack in Tracks.Where(linqTrack => linqTrack.TrackSequence == track))
{
dicTrack = linqTrack;
break;
@@ -1020,6 +1023,10 @@ namespace DiscImageChef.DiscImages
case SectorTagType.CdSectorHeader:
case SectorTagType.CdSectorSubHeader:
case SectorTagType.CdSectorSync: break;
case SectorTagType.CdTrackFlags:
return !trackFlags.TryGetValue((byte)dicTrack.TrackSequence, out byte flags)
? new[] {flags}
: new byte[1];
case SectorTagType.CdSectorSubchannel:
buffer = new byte[96 * length];
subStream.Seek((long)(dicTrack.TrackSubchannelOffset + sectorAddress * 96), SeekOrigin.Begin);
@@ -1205,11 +1212,9 @@ namespace DiscImageChef.DiscImages
}
break;
case TrackType.Audio:
{
throw new ArgumentException("Unsupported tag requested", nameof(tag));
}
default: throw new FeatureSupportedButNotImplementedImageException("Unsupported track type");
case TrackType.Audio: { throw new ArgumentException("Unsupported tag requested", nameof(tag)); }
default:
throw new FeatureSupportedButNotImplementedImageException("Unsupported track type");
}
buffer = new byte[sectorSize * length];
@@ -1243,7 +1248,7 @@ namespace DiscImageChef.DiscImages
{
foreach(KeyValuePair<uint, ulong> kvp in from kvp in offsetmap
where sectorAddress >= kvp.Value
from track in tracks
from track in Tracks
where track.TrackSequence == kvp.Key
where sectorAddress - kvp.Value <
track.TrackEndSector - track.TrackStartSector + 1
@@ -1257,7 +1262,7 @@ namespace DiscImageChef.DiscImages
{
Track dicTrack = new Track {TrackSequence = 0};
foreach(Track linqTrack in tracks.Where(linqTrack => linqTrack.TrackSequence == track))
foreach(Track linqTrack in Tracks.Where(linqTrack => linqTrack.TrackSequence == track))
{
dicTrack = linqTrack;
break;
@@ -1280,14 +1285,14 @@ namespace DiscImageChef.DiscImages
public List<Track> GetSessionTracks(Session session)
{
if(sessions.Contains(session)) return GetSessionTracks(session.SessionSequence);
if(Sessions.Contains(session)) return GetSessionTracks(session.SessionSequence);
throw new ImageNotSupportedException("Session does not exist in disc image");
}
public List<Track> GetSessionTracks(ushort session)
{
return tracks.Where(track => track.TrackSession == session).ToList();
return Tracks.Where(track => track.TrackSession == session).ToList();
}
public bool? VerifySector(ulong sectorAddress)
@@ -1366,5 +1371,10 @@ namespace DiscImageChef.DiscImages
{
return null;
}
static ulong GetLba(int hour, int minute, int second, int frame)
{
return (ulong)(hour * 60 * 60 * 75 + minute * 60 * 75 + second * 75 + frame - 150);
}
}
}

View File

@@ -281,12 +281,12 @@ namespace DiscImageChef.DiscImages
public enum CdFlags : byte
{
/// <summary>Track is quadraphonic.</summary>
FourChannel = 0x20,
FourChannel = 0x08,
/// <summary>Track is non-audio (data).</summary>
DataTrack = 0x10,
DataTrack = 0x04,
/// <summary>Track is copy protected.</summary>
CopyPrevent = 0x08,
CopyPermitted = 0x02,
/// <summary>Track has pre-emphasis.</summary>
PreEmphasis = 0x04
PreEmphasis = 0x01
}
}

View File

@@ -56,7 +56,6 @@ namespace DiscImageChef.DiscImages
Stream imageStream;
/// <summary>Dictionary, index is track #, value is track number, or 0 if a TOC</summary>
Dictionary<uint, ulong> offsetmap;
List<Partition> partitions;
public Gdi()
{
@@ -88,7 +87,7 @@ namespace DiscImageChef.DiscImages
public string Format => "Dreamcast GDI image";
public List<Partition> Partitions => partitions;
public List<Partition> Partitions { get; set; }
public List<Track> Tracks
{
@@ -164,7 +163,10 @@ namespace DiscImageChef.DiscImages
lineNumber++;
string line = gdiStream.ReadLine();
if(lineNumber == 1) { if(!int.TryParse(line, out tracks)) return false; }
if(lineNumber == 1)
{
if(!int.TryParse(line, out tracks)) return false;
}
else
{
Regex regexTrack = new Regex(REGEX_TRACK);
@@ -241,7 +243,7 @@ namespace DiscImageChef.DiscImages
GdiTrack currentTrack = new GdiTrack
{
Bps = ushort.Parse(trackMatch.Groups["type"].Value),
Flags = (byte)(byte.Parse(trackMatch.Groups["flags"].Value) * 0x10),
Flags = byte.Parse(trackMatch.Groups["flags"].Value),
Offset = long.Parse(trackMatch.Groups["offset"].Value),
Sequence = uint.Parse(trackMatch.Groups["track"].Value),
StartSector = ulong.Parse(trackMatch.Groups["start"].Value),
@@ -277,7 +279,7 @@ namespace DiscImageChef.DiscImages
currentTrack.HighDensity = highDensity;
currentTrack.Tracktype =
(currentTrack.Flags & 0x40) == 0x40 ? TrackType.CdMode1 : TrackType.Audio;
(currentTrack.Flags & 0x4) == 0x4 ? TrackType.CdMode1 : TrackType.Audio;
discimage.Tracks.Add(currentTrack);
}
@@ -292,7 +294,8 @@ namespace DiscImageChef.DiscImages
foreach(GdiTrack trk in discimage.Tracks.Where(trk => !trk.HighDensity))
{
if(sessions[s].StartTrack == 0) sessions[s].StartTrack = trk.Sequence;
else if(sessions[s].StartTrack > trk.Sequence) sessions[s].StartTrack = trk.Sequence;
else if(sessions[s].StartTrack > trk.Sequence)
sessions[s].StartTrack = trk.Sequence;
if(sessions[s].EndTrack < trk.Sequence) sessions[s].EndTrack = trk.Sequence;
@@ -309,7 +312,8 @@ namespace DiscImageChef.DiscImages
foreach(GdiTrack trk in discimage.Tracks.Where(trk => trk.HighDensity))
{
if(sessions[s].StartTrack == 0) sessions[s].StartTrack = trk.Sequence;
else if(sessions[s].StartTrack > trk.Sequence) sessions[s].StartTrack = trk.Sequence;
else if(sessions[s].StartTrack > trk.Sequence)
sessions[s].StartTrack = trk.Sequence;
if(sessions[s].EndTrack < trk.Sequence) sessions[s].EndTrack = trk.Sequence;
@@ -349,13 +353,13 @@ namespace DiscImageChef.DiscImages
DicConsole.DebugWriteLine("GDI plugin", "\t\t{0} bytes per sector", discimage.Tracks[i].Bps);
DicConsole.DebugWriteLine("GDI plugin", "\t\tPregap: {0} sectors", discimage.Tracks[i].Pregap);
if((discimage.Tracks[i].Flags & 0x80) == 0x80)
if((discimage.Tracks[i].Flags & 0x8) == 0x8)
DicConsole.DebugWriteLine("GDI plugin", "\t\tTrack is flagged as quadraphonic");
if((discimage.Tracks[i].Flags & 0x40) == 0x40)
if((discimage.Tracks[i].Flags & 0x4) == 0x4)
DicConsole.DebugWriteLine("GDI plugin", "\t\tTrack is data");
if((discimage.Tracks[i].Flags & 0x20) == 0x20)
if((discimage.Tracks[i].Flags & 0x2) == 0x2)
DicConsole.DebugWriteLine("GDI plugin", "\t\tTrack allows digital copy");
if((discimage.Tracks[i].Flags & 0x10) == 0x10)
if((discimage.Tracks[i].Flags & 0x1) == 0x1)
DicConsole.DebugWriteLine("GDI plugin", "\t\tTrack has pre-emphasis applied");
DicConsole.DebugWriteLine("GDI plugin",
@@ -366,7 +370,7 @@ namespace DiscImageChef.DiscImages
DicConsole.DebugWriteLine("GDI plugin", "Building offset map");
partitions = new List<Partition>();
Partitions = new List<Partition>();
ulong byteOffset = 0;
for(int i = 0; i < discimage.Tracks.Count; i++)
@@ -389,7 +393,7 @@ namespace DiscImageChef.DiscImages
byteOffset += partition.Size;
offsetmap.Add(discimage.Tracks[i].Sequence, partition.Start);
partitions.Add(partition);
Partitions.Add(partition);
}
foreach(GdiTrack track in discimage.Tracks) imageInfo.ImageSize += track.Bps * track.Sectors;
@@ -399,8 +403,8 @@ namespace DiscImageChef.DiscImages
imageInfo.SectorSize = 2352; // All others
foreach(GdiTrack unused in
discimage.Tracks.Where(track => (track.Flags & 0x40) == 0x40 && track.Bps == 2352))
foreach(GdiTrack unused in discimage.Tracks.Where(track => (track.Flags & 0x4) == 0x4 &&
track.Bps == 2352))
{
imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync);
imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader);
@@ -470,7 +474,8 @@ namespace DiscImageChef.DiscImages
offsetmap.TryGetValue(0, out ulong transitionStart);
if(sectorAddress >= transitionStart && sectorAddress < densitySeparationSectors + transitionStart)
return ReadSectors(sectorAddress - transitionStart, length, 0);
return ReadSectors(sectorAddress - transitionStart, length,
0);
throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
}
@@ -487,7 +492,8 @@ namespace DiscImageChef.DiscImages
offsetmap.TryGetValue(0, out ulong transitionStart);
if(sectorAddress >= transitionStart && sectorAddress < densitySeparationSectors + transitionStart)
return ReadSectorsTag(sectorAddress - transitionStart, length, 0, tag);
return ReadSectorsTag(sectorAddress - transitionStart, length,
0, tag);
throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
}
@@ -545,6 +551,7 @@ namespace DiscImageChef.DiscImages
sectorSize = 2048;
sectorSkip = 0;
}
break;
}
default: throw new FeatureSupportedButNotImplementedImageException("Unsupported track type");
@@ -824,6 +831,7 @@ namespace DiscImageChef.DiscImages
sectorSize = 2048;
sectorSkip = 0;
}
break;
}
default: throw new FeatureSupportedButNotImplementedImageException("Unsupported track type");

View File

@@ -95,13 +95,10 @@ namespace DiscImageChef.DiscImages
// "END!"
const uint NERO_END = 0x454E4421;
bool imageNewFormat;
List<Partition> imagePartitions;
List<Session> imageSessions;
Stream imageStream;
ImageInfo imageInfo;
public ImageInfo Info => imageInfo;
List<Track> imageTracks;
NeroCdText neroCdtxt;
NeroV1Cuesheet neroCuesheetV1;
NeroV2Cuesheet neroCuesheetV2;
@@ -135,8 +132,8 @@ namespace DiscImageChef.DiscImages
neroSessions = new Dictionary<ushort, uint>();
neroTracks = new Dictionary<uint, NeroTrack>();
offsetmap = new Dictionary<uint, ulong>();
imageSessions = new List<Session>();
imagePartitions = new List<Partition>();
Sessions = new List<Session>();
Partitions = new List<Partition>();
}
// Due to .cue format, this method must parse whole file, ignoring errors (those will be thrown by OpenImage()).
@@ -218,7 +215,7 @@ namespace DiscImageChef.DiscImages
ushort currentsession = 1;
uint currenttrack = 1;
imageTracks = new List<Track>();
Tracks = new List<Track>();
trackIsrCs = new Dictionary<uint, byte[]>();
imageInfo.MediaType = MediaType.CD;
@@ -272,7 +269,8 @@ namespace DiscImageChef.DiscImages
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].TrackNumber = {1:X2}",
i / 8 + 1, entry.TrackNumber);
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].IndexNumber = {1:X2}",
i / 8 + 1, entry.IndexNumber);
i / 8 + 1,
entry.IndexNumber);
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Dummy = {1:X4}", i / 8 + 1,
entry.Dummy);
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Minute = {1:X2}", i / 8 + 1,
@@ -316,7 +314,8 @@ namespace DiscImageChef.DiscImages
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].TrackNumber = {1:X2}",
i / 8 + 1, entry.TrackNumber);
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].IndexNumber = {1:X2}",
i / 8 + 1, entry.IndexNumber);
i / 8 + 1,
entry.IndexNumber);
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Dummy = {1:X2}", i / 8 + 1,
entry.Dummy);
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].LBAStart = {1}", i / 8 + 1,
@@ -383,7 +382,8 @@ namespace DiscImageChef.DiscImages
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Mode = {1} (0x{2:X4})",
i / 32 + 1, (DaoMode)entry.Mode, entry.Mode);
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Unknown = 0x{1:X4}",
i / 32 + 1, entry.Unknown);
i / 32 + 1,
entry.Unknown);
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Index0 = {1}", i / 32 + 1,
entry.Index0);
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Index1 = {1}", i / 32 + 1,
@@ -475,7 +475,8 @@ namespace DiscImageChef.DiscImages
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].SectorSize = {1}", i / 32 + 1,
entry.SectorSize);
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Mode = {1} (0x{2:X4})",
i / 32 + 1, (DaoMode)entry.Mode, entry.Mode);
i / 32 + 1,
(DaoMode)entry.Mode, entry.Mode);
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Unknown = {1:X2}", i / 32 + 1,
entry.Unknown);
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Index0 = {1}", i / 32 + 1,
@@ -550,7 +551,8 @@ namespace DiscImageChef.DiscImages
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].PackNumber = 0x{1:X2}",
i / 18 + 1, entry.PackNumber);
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].BlockNumber = 0x{1:X2}",
i / 18 + 1, entry.BlockNumber);
i / 18 + 1,
entry.BlockNumber);
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Text = \"{1}\"", i / 18 + 1,
StringHandlers.CToString(entry.Text));
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].CRC = 0x{1:X4}", i / 18 + 1,
@@ -591,7 +593,8 @@ namespace DiscImageChef.DiscImages
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Length = {1} bytes",
i / 20 + 1, entry.Length);
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Mode = {1} (0x{2:X4})",
i / 20 + 1, (DaoMode)entry.Mode, entry.Mode);
i / 20 + 1,
(DaoMode)entry.Mode, entry.Mode);
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].StartLBA = {1}", i / 20 + 1,
entry.StartLba);
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Unknown = 0x{1:X4}",
@@ -657,11 +660,13 @@ namespace DiscImageChef.DiscImages
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Length = {1} bytes",
i / 32 + 1, entry.Length);
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Mode = {1} (0x{2:X4})",
i / 32 + 1, (DaoMode)entry.Mode, entry.Mode);
i / 32 + 1,
(DaoMode)entry.Mode, entry.Mode);
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].StartLBA = {1}", i / 32 + 1,
entry.StartLba);
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Unknown = 0x{1:X4}",
i / 32 + 1, entry.Unknown);
i / 32 + 1,
entry.Unknown);
DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Sectors = {1}", i / 32 + 1,
entry.Sectors);
@@ -852,7 +857,8 @@ namespace DiscImageChef.DiscImages
track.Indexes.Add(1, neroTrack.Index1 / neroTrack.SectorSize);
track.TrackDescription = StringHandlers.CToString(neroTrack.Isrc);
track.TrackEndSector = neroTrack.Length / neroTrack.SectorSize + neroTrack.StartLba - 1;
track.TrackPregap = (neroTrack.Index1 - neroTrack.Index0) / neroTrack.SectorSize;
track.TrackPregap = (neroTrack.Index1 - neroTrack.Index0) /
neroTrack.SectorSize;
track.TrackSequence = neroTrack.Sequence;
track.TrackSession = currentsession;
track.TrackStartSector = neroTrack.StartLba;
@@ -909,7 +915,7 @@ namespace DiscImageChef.DiscImages
track.TrackSubchannelOffset = neroTrack.Offset;
}
imageTracks.Add(track);
Tracks.Add(track);
DicConsole.DebugWriteLine("Nero plugin", "\t\t _track.TrackDescription = {0}",
track.TrackDescription);
@@ -936,7 +942,7 @@ namespace DiscImageChef.DiscImages
currentsessioncurrenttrack = 1;
currentsessionstruct.EndTrack = track.TrackSequence;
currentsessionstruct.EndSector = track.TrackEndSector;
imageSessions.Add(currentsessionstruct);
Sessions.Add(currentsessionstruct);
}
if(i == neroTracks.Count)
@@ -945,7 +951,7 @@ namespace DiscImageChef.DiscImages
currentsessioncurrenttrack = 1;
currentsessionstruct.EndTrack = track.TrackSequence;
currentsessionstruct.EndSector = track.TrackEndSector;
imageSessions.Add(currentsessionstruct);
Sessions.Add(currentsessionstruct);
}
offsetmap.Add(track.TrackSequence, track.TrackStartSector);
@@ -978,7 +984,7 @@ namespace DiscImageChef.DiscImages
Type = NeroTrackModeToTrackType((DaoMode)neroTrack.Mode).ToString()
};
partition.Length = partition.Size / neroTrack.SectorSize;
imagePartitions.Add(partition);
Partitions.Add(partition);
partitionSequence++;
partitionStartByte += partition.Size;
}
@@ -996,19 +1002,23 @@ namespace DiscImageChef.DiscImages
for(int i = 0; i < neroTracks.Count; i++)
{
// First track is audio
firstaudio |= i == 0 && ((DaoMode)neroTracks.ElementAt(i).Value.Mode == DaoMode.Audio ||
firstaudio |= i == 0 &&
((DaoMode)neroTracks.ElementAt(i).Value.Mode == DaoMode.Audio ||
(DaoMode)neroTracks.ElementAt(i).Value.Mode == DaoMode.AudioSub);
// First track is data
firstdata |= i == 0 && (DaoMode)neroTracks.ElementAt(i).Value.Mode != DaoMode.Audio &&
firstdata |= i == 0 &&
(DaoMode)neroTracks.ElementAt(i).Value.Mode != DaoMode.Audio &&
(DaoMode)neroTracks.ElementAt(i).Value.Mode != DaoMode.AudioSub;
// Any non first track is data
data |= i != 0 && (DaoMode)neroTracks.ElementAt(i).Value.Mode != DaoMode.Audio &&
data |= i != 0 &&
(DaoMode)neroTracks.ElementAt(i).Value.Mode != DaoMode.Audio &&
(DaoMode)neroTracks.ElementAt(i).Value.Mode != DaoMode.AudioSub;
// Any non first track is audio
audio |= i != 0 && ((DaoMode)neroTracks.ElementAt(i).Value.Mode == DaoMode.Audio ||
audio |= i != 0 &&
((DaoMode)neroTracks.ElementAt(i).Value.Mode == DaoMode.Audio ||
(DaoMode)neroTracks.ElementAt(i).Value.Mode == DaoMode.AudioSub);
switch((DaoMode)neroTracks.ElementAt(i).Value.Mode)
@@ -1023,11 +1033,14 @@ namespace DiscImageChef.DiscImages
}
if(!data && !firstdata) imageInfo.MediaType = MediaType.CDDA;
else if(firstaudio && data && imageSessions.Count > 1 && mode2)
else if(firstaudio && data && Sessions.Count > 1 && mode2)
imageInfo.MediaType = MediaType.CDPLUS;
else if(firstdata && audio || mode2) imageInfo.MediaType = MediaType.CDROMXA;
else if(!audio) imageInfo.MediaType = MediaType.CDROM;
else imageInfo.MediaType = MediaType.CD;
else if(firstdata && audio || mode2)
imageInfo.MediaType = MediaType.CDROMXA;
else if(!audio)
imageInfo.MediaType = MediaType.CDROM;
else
imageInfo.MediaType = MediaType.CD;
}
imageInfo.XmlMediaType = XmlMediaType.OpticalDisc;
@@ -1077,7 +1090,7 @@ namespace DiscImageChef.DiscImages
{
foreach(KeyValuePair<uint, ulong> kvp in from kvp in offsetmap
where sectorAddress >= kvp.Value
from track in imageTracks
from track in Tracks
where track.TrackSequence == kvp.Key
where sectorAddress - kvp.Value <
track.TrackEndSector - track.TrackStartSector
@@ -1091,7 +1104,7 @@ namespace DiscImageChef.DiscImages
{
foreach(KeyValuePair<uint, ulong> kvp in from kvp in offsetmap
where sectorAddress >= kvp.Value
from track in imageTracks
from track in Tracks
where track.TrackSequence == kvp.Key
where sectorAddress - kvp.Value <
track.TrackEndSector - track.TrackStartSector
@@ -1225,7 +1238,7 @@ namespace DiscImageChef.DiscImages
flags[0] = 0x00;
if((DaoMode)dicTrack.Mode != DaoMode.Audio && (DaoMode)dicTrack.Mode != DaoMode.AudioSub)
flags[0] += 0x40;
flags[0] += 0x4;
return flags;
}
@@ -1433,7 +1446,7 @@ namespace DiscImageChef.DiscImages
{
foreach(KeyValuePair<uint, ulong> kvp in from kvp in offsetmap
where sectorAddress >= kvp.Value
from track in imageTracks
from track in Tracks
where track.TrackSequence == kvp.Key
where sectorAddress - kvp.Value <
track.TrackEndSector - track.TrackStartSector
@@ -1518,9 +1531,9 @@ namespace DiscImageChef.DiscImages
public string Format => "Nero Burning ROM";
public List<Partition> Partitions => imagePartitions;
public List<Partition> Partitions { get; }
public List<Track> Tracks => imageTracks;
public List<Track> Tracks { get; set; }
public List<Track> GetSessionTracks(Session session)
{
@@ -1529,10 +1542,10 @@ namespace DiscImageChef.DiscImages
public List<Track> GetSessionTracks(ushort session)
{
return imageTracks.Where(track => track.TrackSession == session).ToList();
return Tracks.Where(track => track.TrackSession == session).ToList();
}
public List<Session> Sessions => imageSessions;
public List<Session> Sessions { get; }
public bool? VerifySector(ulong sectorAddress)
{