diff --git a/DiscImageChef.Decoders b/DiscImageChef.Decoders index 1856c6ddb..3c5b8db65 160000 --- a/DiscImageChef.Decoders +++ b/DiscImageChef.Decoders @@ -1 +1 @@ -Subproject commit 1856c6ddb4d7881272af787498cfc771a865be54 +Subproject commit 3c5b8db6549478b14f6c9ca3159845dec59dc7b4 diff --git a/DiscImageChef.DiscImages/Alcohol120/Read.cs b/DiscImageChef.DiscImages/Alcohol120/Read.cs index 89492c42a..120f9addb 100644 --- a/DiscImageChef.DiscImages/Alcohol120/Read.cs +++ b/DiscImageChef.DiscImages/Alcohol120/Read.cs @@ -55,7 +55,9 @@ namespace DiscImageChef.DiscImages { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); - if(stream.Length < 88) return false; + + if(stream.Length < 88) + return false; isDvd = false; byte[] hdr = new byte[88]; @@ -64,34 +66,41 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("Alcohol 120% plugin", "header.signature = {0}", Encoding.ASCII.GetString(header.signature)); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "header.version = {0}.{1}", header.version[0], header.version[1]); - DicConsole.DebugWriteLine("Alcohol 120% plugin", "header.type = {0}", header.type); + + DicConsole.DebugWriteLine("Alcohol 120% plugin", "header.type = {0}", header.type); DicConsole.DebugWriteLine("Alcohol 120% plugin", "header.sessions = {0}", header.sessions); + for(int i = 0; i < header.unknown1.Length; i++) DicConsole.DebugWriteLine("Alcohol 120% plugin", "header.unknown1[{1}] = 0x{0:X4}", header.unknown1[i], i); DicConsole.DebugWriteLine("Alcohol 120% plugin", "header.bcaLength = {0}", header.bcaLength); + for(int i = 0; i < header.unknown2.Length; i++) DicConsole.DebugWriteLine("Alcohol 120% plugin", "header.unknown2[{1}] = 0x{0:X8}", header.unknown2[i], i); DicConsole.DebugWriteLine("Alcohol 120% plugin", "header.bcaOffset = {0}", header.bcaOffset); + for(int i = 0; i < header.unknown3.Length; i++) DicConsole.DebugWriteLine("Alcohol 120% plugin", "header.unknown3[{1}] = 0x{0:X8}", header.unknown3[i], i); DicConsole.DebugWriteLine("Alcohol 120% plugin", "header.structuresOffset = {0}", header.structuresOffset); + for(int i = 0; i < header.unknown4.Length; i++) DicConsole.DebugWriteLine("Alcohol 120% plugin", "header.unknown4[{1}] = 0x{0:X8}", header.unknown4[i], i); DicConsole.DebugWriteLine("Alcohol 120% plugin", "header.sessionOffset = {0}", header.sessionOffset); - DicConsole.DebugWriteLine("Alcohol 120% plugin", "header.dpmOffset = {0}", header.dpmOffset); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "header.dpmOffset = {0}", header.dpmOffset); stream.Seek(header.sessionOffset, SeekOrigin.Begin); alcSessions = new Dictionary(); + for(int i = 0; i < header.sessions; i++) { byte[] sesHdr = new byte[24]; @@ -100,19 +109,24 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{1}].sessionStart = {0}", session.sessionStart, i); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{1}].sessionEnd = {0}", session.sessionEnd, i); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{1}].sessionSequence = {0}", session.sessionSequence, i); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{1}].allBlocks = {0}", session.allBlocks, i); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{1}].nonTrackBlocks = {0}", session.nonTrackBlocks, i); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{1}].firstTrack = {0}", session.firstTrack, i); - DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{1}].lastTrack = {0}", session.lastTrack, - i); - DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{1}].unknown = 0x{0:X8}", session.unknown, - i); + + DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{1}].lastTrack = {0}", session.lastTrack, i); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{1}].unknown = 0x{0:X8}", session.unknown, i); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{1}].trackOffset = {0}", session.trackOffset, i); @@ -124,17 +138,20 @@ namespace DiscImageChef.DiscImages alcTracks = new Dictionary(); alcToc = new Dictionary>(); + foreach(AlcoholSession session in alcSessions.Values) { stream.Seek(session.trackOffset, SeekOrigin.Begin); Dictionary sesToc = new Dictionary(); + for(int i = 0; i < session.allBlocks; i++) { byte[] trkHdr = new byte[80]; stream.Read(trkHdr, 0, 80); AlcoholTrack track = Marshal.ByteArrayToStructureLittleEndian(trkHdr); - if(track.mode == AlcoholTrackMode.Mode2F1Alt || track.mode == AlcoholTrackMode.Mode2F1Alt) + if(track.mode == AlcoholTrackMode.Mode2F1Alt || + track.mode == AlcoholTrackMode.Mode2F1Alt) oldIncorrectImage = true; // Solve our own mistake here, sorry, but anyway seems Alcohol doesn't support DDCD @@ -147,52 +164,74 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].mode = {0}", track.mode, track.point, session.sessionSequence); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].subMode = {0}", track.subMode, track.point, session.sessionSequence); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].adrCtl = {0}", track.adrCtl, track.point, session.sessionSequence); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].tno = {0}", track.tno, track.point, session.sessionSequence); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].point = {0:X2}", track.point, track.point, session.sessionSequence); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].min = {0}", track.min, track.point, session.sessionSequence); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].sec = {0}", track.sec, track.point, session.sessionSequence); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].frame = {0}", track.frame, track.point, session.sessionSequence); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].zero = {0}", track.zero, track.point, session.sessionSequence); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].pmin = {0}", track.pmin, track.point, session.sessionSequence); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].psec = {0}", track.psec, track.point, session.sessionSequence); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].pframe = {0}", track.pframe, track.point, session.sessionSequence); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].extraOffset = {0}", track.extraOffset, track.point, session.sessionSequence); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].sectorSize = {0}", track.sectorSize, track.point, session.sessionSequence); + //for(int j = 0; j < track.unknown.Length; j++) // DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].unknown[{2}] = {0}", track.unknown[j], i, j, session.sessionSequence); DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].startLba = {0}", track.startLba, track.point, session.sessionSequence); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].startOffset = {0}", track.startOffset, track.point, session.sessionSequence); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].files = {0}", track.files, track.point, session.sessionSequence); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].footerOffset = {0}", track.footerOffset, track.point, session.sessionSequence); + //for(int j = 0; j < track.unknown2.Length; j++) // DicConsole.DebugWriteLine("Alcohol 120% plugin", "session[{2}].track[{1}].unknown2[{2}] = {0}", track.unknown2[j], i, j, session.sessionSequence); - if(track.subMode == AlcoholSubchannelMode.Interleaved) track.sectorSize -= 96; + if(track.subMode == AlcoholSubchannelMode.Interleaved) + track.sectorSize -= 96; - if(!sesToc.ContainsKey(track.point)) sesToc.Add(track.point, track); + if(!sesToc.ContainsKey(track.point)) + sesToc.Add(track.point, track); - if(track.point < 0xA0) alcTracks.Add(track.point, track); + if(track.point < 0xA0) + alcTracks.Add(track.point, track); - if(footerOff == 0) footerOff = track.footerOffset; + if(footerOff == 0) + footerOff = track.footerOffset; isDvd |= track.mode == AlcoholTrackMode.DVD; } @@ -201,8 +240,10 @@ namespace DiscImageChef.DiscImages } alcTrackExtras = new Dictionary(); + foreach(AlcoholTrack track in alcTracks.Values) - if(track.extraOffset > 0 && !isDvd) + if(track.extraOffset > 0 && + !isDvd) { byte[] extHdr = new byte[8]; stream.Seek(track.extraOffset, SeekOrigin.Begin); @@ -211,6 +252,7 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("Alcohol 120% plugin", "track[{1}].extra.pregap = {0}", extra.pregap, track.point); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "track[{1}].extra.sectors = {0}", extra.sectors, track.point); @@ -218,7 +260,11 @@ namespace DiscImageChef.DiscImages } else if(isDvd) { - AlcoholTrackExtra extra = new AlcoholTrackExtra {sectors = track.extraOffset}; + var extra = new AlcoholTrackExtra + { + sectors = track.extraOffset + }; + alcTrackExtras.Add(track.point, extra); } @@ -231,7 +277,8 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("Alcohol 120% plugin", "footer.filenameOffset = {0}", alcFooter.filenameOffset); - DicConsole.DebugWriteLine("Alcohol 120% plugin", "footer.widechar = {0}", alcFooter.widechar); + + DicConsole.DebugWriteLine("Alcohol 120% plugin", "footer.widechar = {0}", alcFooter.widechar); DicConsole.DebugWriteLine("Alcohol 120% plugin", "footer.unknown1 = 0x{0:X8}", alcFooter.unknown1); DicConsole.DebugWriteLine("Alcohol 120% plugin", "footer.unknown2 = 0x{0:X8}", alcFooter.unknown2); } @@ -241,13 +288,13 @@ namespace DiscImageChef.DiscImages if(alcFooter.filenameOffset > 0) { stream.Seek(alcFooter.filenameOffset, SeekOrigin.Begin); - byte[] filename = header.dpmOffset == 0 - ? new byte[stream.Length - stream.Position] - : new byte[header.dpmOffset - stream.Position]; + + byte[] filename = header.dpmOffset == 0 ? new byte[stream.Length - stream.Position] + : new byte[header.dpmOffset - stream.Position]; stream.Read(filename, 0, filename.Length); - alcFile = alcFooter.widechar == 1 - ? Encoding.Unicode.GetString(filename) + + alcFile = alcFooter.widechar == 1 ? Encoding.Unicode.GetString(filename) : Encoding.Default.GetString(filename); DicConsole.DebugWriteLine("Alcohol 120% plugin", "footer.filename = {0}", alcFile); @@ -257,7 +304,9 @@ namespace DiscImageChef.DiscImages string.Compare(alcFile, "*.mdf", StringComparison.InvariantCultureIgnoreCase) == 0) alcFile = Path.GetFileNameWithoutExtension(imageFilter.GetBasePath()) + ".mdf"; - if(header.bcaLength > 0 && header.bcaOffset > 0 && isDvd) + if(header.bcaLength > 0 && + header.bcaOffset > 0 && + isDvd) { bca = new byte[header.bcaLength]; stream.Seek(header.bcaOffset, SeekOrigin.Begin); @@ -269,6 +318,7 @@ namespace DiscImageChef.DiscImages case AlcoholMediumType.DVD: case AlcoholMediumType.DVDR: imageInfo.ReadableMediaTags.Add(MediaTagType.DVD_BCA); + break; } } @@ -276,22 +326,30 @@ namespace DiscImageChef.DiscImages imageInfo.MediaType = AlcoholMediumTypeToMediaType(header.type); Sessions = new List(); + foreach(AlcoholSession alcSes in alcSessions.Values) { - Session session = new Session(); + var session = new Session(); - if(!alcTracks.TryGetValue(alcSes.firstTrack, out AlcoholTrack startingTrack)) break; - if(!alcTracks.TryGetValue(alcSes.lastTrack, out AlcoholTrack endingTrack)) break; - if(!alcTrackExtras.TryGetValue(alcSes.lastTrack, out AlcoholTrackExtra endingTrackExtra)) break; + if(!alcTracks.TryGetValue(alcSes.firstTrack, out AlcoholTrack startingTrack)) + break; + + if(!alcTracks.TryGetValue(alcSes.lastTrack, out AlcoholTrack endingTrack)) + break; + + if(!alcTrackExtras.TryGetValue(alcSes.lastTrack, out AlcoholTrackExtra endingTrackExtra)) + break; session.StartSector = startingTrack.startLba; session.StartTrack = alcSes.firstTrack; session.SessionSequence = alcSes.sessionSequence; - session.EndSector = endingTrack.startLba + endingTrackExtra.sectors - 1; + session.EndSector = (endingTrack.startLba + endingTrackExtra.sectors) - 1; session.EndTrack = alcSes.lastTrack; Sessions.Add(session); - if(session.EndSector > imageInfo.Sectors) imageInfo.Sectors = session.EndSector + 1; + + if(session.EndSector > imageInfo.Sectors) + imageInfo.Sectors = session.EndSector + 1; } if(isDvd) @@ -305,7 +363,7 @@ namespace DiscImageChef.DiscImages dmi = new byte[2052]; pfi = new byte[2052]; - Array.Copy(structures, 0, dmi, 0, 2052); + Array.Copy(structures, 0, dmi, 0, 2052); Array.Copy(structures, 0x804, pfi, 4, 2048); pfi[0] = 0x08; @@ -323,51 +381,67 @@ namespace DiscImageChef.DiscImages { case DiskCategory.DVDPR: imageInfo.MediaType = MediaType.DVDPR; + break; case DiskCategory.DVDPRDL: imageInfo.MediaType = MediaType.DVDPRDL; + break; case DiskCategory.DVDPRW: imageInfo.MediaType = MediaType.DVDPRW; + break; case DiskCategory.DVDPRWDL: imageInfo.MediaType = MediaType.DVDPRWDL; + break; case DiskCategory.DVDR: imageInfo.MediaType = pfi0.Value.PartVersion == 6 ? MediaType.DVDRDL : MediaType.DVDR; + break; case DiskCategory.DVDRAM: imageInfo.MediaType = MediaType.DVDRAM; + break; default: imageInfo.MediaType = MediaType.DVDROM; + break; case DiskCategory.DVDRW: imageInfo.MediaType = pfi0.Value.PartVersion == 3 ? MediaType.DVDRWDL : MediaType.DVDRW; + break; case DiskCategory.HDDVDR: imageInfo.MediaType = MediaType.HDDVDR; + break; case DiskCategory.HDDVDRAM: imageInfo.MediaType = MediaType.HDDVDRAM; + break; case DiskCategory.HDDVDROM: imageInfo.MediaType = MediaType.HDDVDROM; + break; case DiskCategory.HDDVDRW: imageInfo.MediaType = MediaType.HDDVDRW; + break; case DiskCategory.Nintendo: imageInfo.MediaType = pfi0.Value.DiscSize == DVDSize.Eighty ? MediaType.GOD : MediaType.WOD; + break; case DiskCategory.UMD: imageInfo.MediaType = MediaType.UMD; + break; } - if(DMI.IsXbox(dmi)) imageInfo.MediaType = MediaType.XGD; - else if(DMI.IsXbox360(dmi)) imageInfo.MediaType = MediaType.XGD2; + if(DMI.IsXbox(dmi)) + imageInfo.MediaType = MediaType.XGD; + else if(DMI.IsXbox360(dmi)) + imageInfo.MediaType = MediaType.XGD2; imageInfo.ReadableMediaTags.Add(MediaTagType.DVD_PFI); imageInfo.ReadableMediaTags.Add(MediaTagType.DVD_DMI); @@ -404,15 +478,25 @@ namespace DiscImageChef.DiscImages case AlcoholTrackMode.Mode2F1Alt: case AlcoholTrackMode.Mode2F2Alt: mode2 = true; + break; } } - 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; + 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; } DicConsole.DebugWriteLine("Alcohol 120% plugin", "ImageInfo.mediaType = {0}", imageInfo.MediaType); @@ -425,22 +509,19 @@ namespace DiscImageChef.DiscImages { if(alcTrackExtras.TryGetValue(trk.point, out AlcoholTrackExtra extra)) { - Partition partition = new Partition + var partition = new Partition { - Description = $"Track {trk.point}.", - Start = trk.startLba, - Size = extra.sectors * trk.sectorSize, - Length = extra.sectors, - Sequence = trk.point, - Offset = byteOffset, - Type = trk.mode.ToString() + Description = $"Track {trk.point}.", Start = trk.startLba, + Size = extra.sectors * trk.sectorSize, Length = extra.sectors, Sequence = trk.point, + Offset = byteOffset, Type = trk.mode.ToString() }; Partitions.Add(partition); byteOffset += partition.Size; } - if(!offsetmap.ContainsKey(trk.point)) offsetmap.Add(trk.point, trk.startLba); + if(!offsetmap.ContainsKey(trk.point)) + offsetmap.Add(trk.point, trk.startLba); switch(trk.mode) { @@ -449,44 +530,65 @@ namespace DiscImageChef.DiscImages case AlcoholTrackMode.Mode2F1Alt: if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); - if(imageInfo.SectorSize < 2048) imageInfo.SectorSize = 2048; + + if(imageInfo.SectorSize < 2048) + imageInfo.SectorSize = 2048; + break; case AlcoholTrackMode.Mode2: if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); - if(imageInfo.SectorSize < 2336) imageInfo.SectorSize = 2336; + + if(imageInfo.SectorSize < 2336) + imageInfo.SectorSize = 2336; + break; case AlcoholTrackMode.Mode2F2: case AlcoholTrackMode.Mode2F2Alt: if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); - if(imageInfo.SectorSize < 2324) imageInfo.SectorSize = 2324; + + if(imageInfo.SectorSize < 2324) + imageInfo.SectorSize = 2324; + break; case AlcoholTrackMode.DVD: imageInfo.SectorSize = 2048; + break; default: imageInfo.SectorSize = 2352; + break; } @@ -496,28 +598,28 @@ namespace DiscImageChef.DiscImages } DicConsole.DebugWriteLine("Alcohol 120% plugin", "printing partition map"); + foreach(Partition partition in Partitions) { - DicConsole.DebugWriteLine("Alcohol 120% plugin", "Partition sequence: {0}", - partition.Sequence); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "Partition sequence: {0}", partition.Sequence); DicConsole.DebugWriteLine("Alcohol 120% plugin", "\tPartition name: {0}", partition.Name); - DicConsole.DebugWriteLine("Alcohol 120% plugin", "\tPartition description: {0}", - partition.Description); - DicConsole.DebugWriteLine("Alcohol 120% plugin", "\tPartition type: {0}", partition.Type); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "\tPartition description: {0}", partition.Description); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "\tPartition type: {0}", partition.Type); DicConsole.DebugWriteLine("Alcohol 120% plugin", "\tPartition starting sector: {0}", partition.Start); - DicConsole.DebugWriteLine("Alcohol 120% plugin", "\tPartition sectors: {0}", partition.Length); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "\tPartition sectors: {0}", partition.Length); DicConsole.DebugWriteLine("Alcohol 120% plugin", "\tPartition starting offset: {0}", partition.Offset); - DicConsole.DebugWriteLine("Alcohol 120% plugin", "\tPartition size in bytes: {0}", partition.Size); + DicConsole.DebugWriteLine("Alcohol 120% plugin", "\tPartition size in bytes: {0}", partition.Size); } imageInfo.Application = "Alcohol 120%"; DicConsole.DebugWriteLine("Alcohol 120% plugin", "Data filename: {0}", alcFile); - FiltersList filtersList = new FiltersList(); + var filtersList = new FiltersList(); alcImage = filtersList.GetFilter(alcFile); - if(alcImage == null) throw new Exception("Cannot open data file"); + if(alcImage == null) + throw new Exception("Cannot open data file"); imageInfo.ImageSize = (ulong)alcImage.GetDataForkLength(); imageInfo.CreationTime = alcImage.GetCreationTime(); @@ -528,14 +630,22 @@ namespace DiscImageChef.DiscImages if(!isDvd) { DicConsole.DebugWriteLine("Alcohol 120% plugin", "Rebuilding TOC"); - byte firstSession = byte.MaxValue; - byte lastSession = 0; - MemoryStream tocMs = new MemoryStream(); - tocMs.Write(new byte[] {0, 0, 0, 0}, 0, 4); // Reserved for TOC response size and session numbers + byte firstSession = byte.MaxValue; + byte lastSession = 0; + var tocMs = new MemoryStream(); + + tocMs.Write(new byte[] + { + 0, 0, 0, 0 + }, 0, 4); // Reserved for TOC response size and session numbers + foreach(KeyValuePair> sessionToc in alcToc) { - if(sessionToc.Key < firstSession) firstSession = (byte)sessionToc.Key; - if(sessionToc.Key > lastSession) lastSession = (byte)sessionToc.Key; + if(sessionToc.Key < firstSession) + firstSession = (byte)sessionToc.Key; + + if(sessionToc.Key > lastSession) + lastSession = (byte)sessionToc.Key; foreach(AlcoholTrack sessionTrack in sessionToc.Value.Values) { @@ -567,7 +677,8 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("Alcohol 120% plugin", "TOC not correctly rebuilt"); fullToc = null; } - else imageInfo.ReadableMediaTags.Add(MediaTagType.CD_FullTOC); + else + imageInfo.ReadableMediaTags.Add(MediaTagType.CD_FullTOC); imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackFlags); } @@ -592,28 +703,32 @@ namespace DiscImageChef.DiscImages { case MediaTagType.DVD_BCA: { - if(bca != null) return (byte[])bca.Clone(); + if(bca != null) + return(byte[])bca.Clone(); throw new FeatureNotPresentImageException("Image does not contain BCA information."); } case MediaTagType.DVD_PFI: { - if(pfi != null) return (byte[])pfi.Clone(); + if(pfi != null) + return(byte[])pfi.Clone(); throw new FeatureNotPresentImageException("Image does not contain PFI."); } case MediaTagType.DVD_DMI: { - if(dmi != null) return (byte[])dmi.Clone(); + if(dmi != null) + return(byte[])dmi.Clone(); throw new FeatureNotPresentImageException("Image does not contain DMI."); } case MediaTagType.CD_FullTOC: { - if(fullToc != null) return (byte[])fullToc.Clone(); + if(fullToc != null) + return(byte[])fullToc.Clone(); throw new FeatureNotPresentImageException("Image does not contain TOC information."); } @@ -639,7 +754,8 @@ namespace DiscImageChef.DiscImages foreach(AlcoholTrack track in alcTracks.Values) { if(track.point != kvp.Key || - !alcTrackExtras.TryGetValue(track.point, out AlcoholTrackExtra extra)) continue; + !alcTrackExtras.TryGetValue(track.point, out AlcoholTrackExtra extra)) + continue; if(sectorAddress - kvp.Value < extra.sectors) return ReadSectors(sectorAddress - kvp.Value, length, kvp.Key); @@ -655,7 +771,8 @@ namespace DiscImageChef.DiscImages foreach(AlcoholTrack track in alcTracks.Values) { if(track.point != kvp.Key || - !alcTrackExtras.TryGetValue(track.point, out AlcoholTrackExtra extra)) continue; + !alcTrackExtras.TryGetValue(track.point, out AlcoholTrackExtra extra)) + continue; if(sectorAddress - kvp.Value < extra.sectors) return ReadSectorsTag(sectorAddress - kvp.Value, length, kvp.Key, tag); @@ -677,6 +794,7 @@ namespace DiscImageChef.DiscImages uint sectorOffset; uint sectorSize; uint sectorSkip; + bool mode2 = false; switch(alcTrack.mode) { @@ -685,14 +803,17 @@ namespace DiscImageChef.DiscImages sectorOffset = 16; sectorSize = 2048; sectorSkip = 288; + break; } case AlcoholTrackMode.Mode2: { - sectorOffset = 16; - sectorSize = 2336; + mode2 = true; + sectorOffset = 0; + sectorSize = 2352; sectorSkip = 0; + break; } @@ -702,6 +823,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 24; sectorSize = 2048; sectorSkip = 280; + break; } @@ -711,6 +833,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 24; sectorSize = 2324; sectorSkip = 4; + break; } @@ -719,6 +842,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 2352; sectorSkip = 0; + break; } @@ -727,6 +851,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 2048; sectorSkip = 0; + break; } @@ -737,9 +862,11 @@ namespace DiscImageChef.DiscImages { case AlcoholSubchannelMode.None: sectorSkip += 0; + break; case AlcoholSubchannelMode.Interleaved: sectorSkip += 96; + break; default: throw new FeatureSupportedButNotImplementedImageException("Unsupported subchannel type"); } @@ -747,11 +874,31 @@ namespace DiscImageChef.DiscImages byte[] buffer = new byte[sectorSize * length]; imageStream = alcImage.GetDataForkStream(); - BinaryReader br = new BinaryReader(imageStream); - br.BaseStream - .Seek((long)alcTrack.startOffset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), + var br = new BinaryReader(imageStream); + + br.BaseStream. + Seek((long)alcTrack.startOffset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), SeekOrigin.Begin); - if(sectorOffset == 0 && sectorSkip == 0) buffer = br.ReadBytes((int)(sectorSize * length)); + + if(mode2) + { + var mode2Ms = new MemoryStream((int)(sectorSize * length)); + + buffer = br.ReadBytes((int)(sectorSize * length)); + + for(int i = 0; i < length; i++) + { + byte[] sector = new byte[sectorSize]; + Array.Copy(buffer, sectorSize * i, sector, 0, sectorSize); + sector = Sector.GetUserDataFromMode2(sector); + mode2Ms.Write(sector, 0, sector.Length); + } + + buffer = mode2Ms.ToArray(); + } + else if(sectorOffset == 0 && + sectorSkip == 0) + buffer = br.ReadBytes((int)(sectorSize * length)); else for(int i = 0; i < length; i++) { @@ -791,8 +938,12 @@ namespace DiscImageChef.DiscImages case SectorTagType.CdSectorSubchannel: case SectorTagType.CdSectorSubHeader: case SectorTagType.CdSectorSync: break; - case SectorTagType.CdTrackFlags: return new[] {(byte)(alcTrack.adrCtl & 0x0F)}; - default: throw new ArgumentException("Unsupported tag requested", nameof(tag)); + case SectorTagType.CdTrackFlags: + return new[] + { + (byte)(alcTrack.adrCtl & 0x0F) + }; + default: throw new ArgumentException("Unsupported tag requested", nameof(tag)); } switch(alcTrack.mode) @@ -805,6 +956,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 12; sectorSkip = 2340; + break; } @@ -813,6 +965,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 12; sectorSize = 4; sectorSkip = 2336; + break; } @@ -823,6 +976,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2076; sectorSize = 276; sectorSkip = 0; + break; } @@ -831,6 +985,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2076; sectorSize = 172; sectorSkip = 104; + break; } @@ -839,6 +994,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2248; sectorSize = 104; sectorSkip = 0; + break; } @@ -847,6 +1003,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2064; sectorSize = 4; sectorSkip = 284; + break; } @@ -859,6 +1016,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2352; sectorSize = 96; sectorSkip = 0; + break; default: throw new ArgumentException("Unsupported tag requested", nameof(tag)); } @@ -885,6 +1043,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 8; sectorSkip = 2328; + break; } @@ -893,6 +1052,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2332; sectorSize = 4; sectorSkip = 0; + break; } @@ -905,6 +1065,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2352; sectorSize = 96; sectorSkip = 0; + break; default: throw new ArgumentException("Unsupported tag requested", nameof(tag)); } @@ -927,6 +1088,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 12; sectorSkip = 2340; + break; } @@ -935,6 +1097,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 12; sectorSize = 4; sectorSkip = 2336; + break; } @@ -943,6 +1106,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 16; sectorSize = 8; sectorSkip = 2328; + break; } @@ -951,6 +1115,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2076; sectorSize = 276; sectorSkip = 0; + break; } @@ -959,6 +1124,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2076; sectorSize = 172; sectorSkip = 104; + break; } @@ -967,6 +1133,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2248; sectorSize = 104; sectorSkip = 0; + break; } @@ -975,6 +1142,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2072; sectorSize = 4; sectorSkip = 276; + break; } @@ -987,6 +1155,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2352; sectorSize = 96; sectorSkip = 0; + break; default: throw new ArgumentException("Unsupported tag requested", nameof(tag)); } @@ -1007,6 +1176,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 12; sectorSkip = 2340; + break; } @@ -1015,6 +1185,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 12; sectorSize = 4; sectorSkip = 2336; + break; } @@ -1023,6 +1194,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 16; sectorSize = 8; sectorSkip = 2328; + break; } @@ -1031,6 +1203,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2348; sectorSize = 4; sectorSkip = 0; + break; } @@ -1043,6 +1216,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2352; sectorSize = 96; sectorSkip = 0; + break; default: throw new ArgumentException("Unsupported tag requested", nameof(tag)); } @@ -1067,6 +1241,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2352; sectorSize = 96; sectorSkip = 0; + break; default: throw new ArgumentException("Unsupported tag requested", nameof(tag)); } @@ -1087,9 +1262,12 @@ namespace DiscImageChef.DiscImages { case AlcoholSubchannelMode.None: sectorSkip += 0; + break; case AlcoholSubchannelMode.Interleaved: - if(tag != SectorTagType.CdSectorSubchannel) sectorSkip += 96; + if(tag != SectorTagType.CdSectorSubchannel) + sectorSkip += 96; + break; default: throw new FeatureSupportedButNotImplementedImageException("Unsupported subchannel type"); } @@ -1097,11 +1275,15 @@ namespace DiscImageChef.DiscImages byte[] buffer = new byte[sectorSize * length]; imageStream = alcImage.GetDataForkStream(); - BinaryReader br = new BinaryReader(imageStream); - br.BaseStream - .Seek((long)alcTrack.startOffset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), + var br = new BinaryReader(imageStream); + + br.BaseStream. + Seek((long)alcTrack.startOffset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), SeekOrigin.Begin); - if(sectorOffset == 0 && sectorSkip == 0) buffer = br.ReadBytes((int)(sectorSize * length)); + + if(sectorOffset == 0 && + sectorSkip == 0) + buffer = br.ReadBytes((int)(sectorSize * length)); else for(int i = 0; i < length; i++) { @@ -1125,7 +1307,8 @@ namespace DiscImageChef.DiscImages foreach(AlcoholTrack alcTrack in alcTracks.Values) { if(alcTrack.point != kvp.Key || - !alcTrackExtras.TryGetValue(alcTrack.point, out AlcoholTrackExtra alcExtra)) continue; + !alcTrackExtras.TryGetValue(alcTrack.point, out AlcoholTrackExtra alcExtra)) + continue; if(sectorAddress - kvp.Value < alcExtra.sectors) return ReadSectorsLong(sectorAddress - kvp.Value, length, kvp.Key); @@ -1162,24 +1345,28 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = alcTrack.sectorSize; sectorSkip = 0; + break; } default: throw new FeatureSupportedButNotImplementedImageException("Unsupported track type"); } - if(alcTrack.subMode == AlcoholSubchannelMode.Interleaved) sectorSkip = 96; + if(alcTrack.subMode == AlcoholSubchannelMode.Interleaved) + sectorSkip = 96; byte[] buffer = new byte[sectorSize * length]; imageStream = alcImage.GetDataForkStream(); - BinaryReader br = new BinaryReader(imageStream); + var br = new BinaryReader(imageStream); - br.BaseStream - .Seek((long)alcTrack.startOffset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), + br.BaseStream. + Seek((long)alcTrack.startOffset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), SeekOrigin.Begin); - if(sectorOffset == 0 && sectorSkip == 0) buffer = br.ReadBytes((int)(sectorSize * length)); + if(sectorOffset == 0 && + sectorSkip == 0) + buffer = br.ReadBytes((int)(sectorSize * length)); else for(int i = 0; i < length; i++) { @@ -1195,7 +1382,8 @@ namespace DiscImageChef.DiscImages public List 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"); } @@ -1207,28 +1395,30 @@ namespace DiscImageChef.DiscImages foreach(AlcoholTrack alcTrack in alcTracks.Values) { ushort sessionNo = - (from ses in Sessions - where alcTrack.point >= ses.StartTrack || alcTrack.point <= ses.EndTrack + (from ses in Sessions where alcTrack.point >= ses.StartTrack || alcTrack.point <= ses.EndTrack select ses.SessionSequence).FirstOrDefault(); if(!alcTrackExtras.TryGetValue(alcTrack.point, out AlcoholTrackExtra alcExtra) || - session != sessionNo) continue; + session != sessionNo) + continue; - Track dicTrack = new Track + var dicTrack = new Track { - Indexes = new Dictionary {{1, alcTrack.startLba}}, - TrackStartSector = alcTrack.startLba, - TrackEndSector = alcExtra.sectors - 1, - TrackPregap = alcExtra.pregap, - TrackSession = sessionNo, - TrackSequence = alcTrack.point, - TrackType = AlcoholTrackTypeToTrackType(alcTrack.mode), - TrackFilter = alcImage, - TrackFile = alcImage.GetFilename(), - TrackFileOffset = alcTrack.startOffset, - TrackFileType = "BINARY", - TrackRawBytesPerSector = alcTrack.sectorSize, - TrackBytesPerSector = AlcoholTrackModeToCookedBytesPerSector(alcTrack.mode) + Indexes = new Dictionary + { + { + 1, alcTrack.startLba + } + }, + TrackStartSector = alcTrack.startLba, + TrackEndSector = alcExtra.sectors - 1, + TrackPregap = alcExtra.pregap, TrackSession = sessionNo, + TrackSequence = alcTrack.point, + TrackType = AlcoholTrackTypeToTrackType(alcTrack.mode), TrackFilter = alcImage, + TrackFile = alcImage.GetFilename(), + TrackFileOffset = alcTrack.startOffset, + TrackFileType = "BINARY", TrackRawBytesPerSector = alcTrack.sectorSize, + TrackBytesPerSector = AlcoholTrackModeToCookedBytesPerSector(alcTrack.mode) }; switch(alcTrack.subMode) @@ -1238,9 +1428,11 @@ namespace DiscImageChef.DiscImages dicTrack.TrackSubchannelFile = alcImage.GetFilename(); dicTrack.TrackSubchannelOffset = alcTrack.startOffset; dicTrack.TrackSubchannelType = TrackSubchannelType.RawInterleaved; + break; case AlcoholSubchannelMode.None: dicTrack.TrackSubchannelType = TrackSubchannelType.None; + break; } diff --git a/DiscImageChef.DiscImages/BlindWrite4/Read.cs b/DiscImageChef.DiscImages/BlindWrite4/Read.cs index 3f2796218..464b9b982 100644 --- a/DiscImageChef.DiscImages/BlindWrite4/Read.cs +++ b/DiscImageChef.DiscImages/BlindWrite4/Read.cs @@ -42,6 +42,8 @@ using DiscImageChef.CommonTypes.Exceptions; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Structs; using DiscImageChef.Console; +using DiscImageChef.Decoders.CD; +using Session = DiscImageChef.CommonTypes.Structs.Session; namespace DiscImageChef.DiscImages { @@ -51,7 +53,9 @@ namespace DiscImageChef.DiscImages { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); - if(stream.Length < 19) return false; + + if(stream.Length < 19) + return false; byte[] tmpArray = new byte[19]; byte[] tmpUShort = new byte[2]; @@ -60,13 +64,18 @@ namespace DiscImageChef.DiscImages stream.Read(tmpArray, 0, 19); - if(!bw4Signature.SequenceEqual(tmpArray)) return false; + if(!bw4Signature.SequenceEqual(tmpArray)) + return false; - header = new Bw4Header {Signature = tmpArray}; + header = new Bw4Header + { + Signature = tmpArray + }; // Seems to always be 2 stream.Read(tmpUInt, 0, 4); header.Unknown1 = BitConverter.ToUInt32(tmpUInt, 0); + // Seems to be a timetamp stream.Read(tmpULong, 0, 8); header.Timestamp = BitConverter.ToUInt64(tmpULong, 0); @@ -118,25 +127,28 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.signature = {0}", StringHandlers.CToString(header.Signature)); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.unknown1 = {0}", header.Unknown1); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.timestamp = {0}", header.Timestamp); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.volumeIdLength = {0}", header.VolumeIdLength); + + DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.unknown1 = {0}", header.Unknown1); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.timestamp = {0}", header.Timestamp); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.volumeIdLength = {0}", header.VolumeIdLength); DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.volumeIdentifier = {0}", header.VolumeIdentifier); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.sysIdLength = {0}", header.SysIdLength); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.sysIdLength = {0}", header.SysIdLength); DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.systemIdentifier = {0}", header.SystemIdentifier); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.commentsLength = {0}", header.CommentsLength); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.comments = {0}", header.Comments); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.commentsLength = {0}", header.CommentsLength); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.comments = {0}", header.Comments); DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.trackDescriptors = {0}", header.TrackDescriptors); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.dataFileLength = {0}", header.DataFileLength); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.dataFilter = {0}", header.DataFilter); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.dataFile = {0}", header.DataFile); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.dataFileLength = {0}", header.DataFileLength); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.dataFilter = {0}", header.DataFilter); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.dataFile = {0}", header.DataFile); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.subchannelFileLength = {0}", header.SubchannelFileLength); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.subchannelFilter = {0}", header.SubchannelFilter); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.subchannelFile = {0}", header.SubchannelFile); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.unknown2 = {0}", header.Unknown2); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.unknown3 = {0}", header.Unknown3); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.unknown4.Length = {0}", header.Unknown4.Length); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.subchannelFile = {0}", header.SubchannelFile); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.unknown2 = {0}", header.Unknown2); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.unknown3 = {0}", header.Unknown3); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "header.unknown4.Length = {0}", header.Unknown4.Length); bwTracks = new List(); @@ -144,7 +156,7 @@ namespace DiscImageChef.DiscImages { DicConsole.DebugWriteLine("BlindWrite4 plugin", "stream.Position = {0}", stream.Position); - Bw4TrackDescriptor track = new Bw4TrackDescriptor(); + var track = new Bw4TrackDescriptor(); stream.Read(tmpUInt, 0, 4); track.filenameLen = BitConverter.ToUInt32(tmpUInt, 0); @@ -193,6 +205,7 @@ namespace DiscImageChef.DiscImages track.startSector = BitConverter.ToInt32(tmpUInt, 0); track.unknown13 = new uint[2]; + for(int j = 0; j < track.unknown13.Length; j++) { stream.Read(tmpUInt, 0, 4); @@ -305,111 +318,139 @@ namespace DiscImageChef.DiscImages track.isrcUpc = StringHandlers.CToString(track.isrcBytes, Encoding.Default); DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.filenameLen = {0}", track.filenameLen); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.filename = {0}", track.filename); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.offset = {0}", track.offset); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.subchannel = {0}", track.subchannel); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.filename = {0}", track.filename); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.offset = {0}", track.offset); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.subchannel = {0}", track.subchannel); + for(int j = 0; j < track.unknown1.Length; j++) DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unknown1[{1}] = 0x{0:X8}", track.unknown1[j], j); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unknown2 = {0}", track.unknown2); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unknown3 = {0}", track.unknown3); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.session = {0}", track.session); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unknown4 = {0}", track.unknown4); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.adrCtl = {0}", track.adrCtl); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unknown5 = {0}", track.unknown5); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.trackMode = {0}", track.trackMode); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unknown6 = {0}", track.unknown6); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.point = {0}", track.point); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unknown7 = {0}", track.unknown7); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unknown8 = {0}", track.unknown8); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unknown9 = {0}", track.unknown9); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unknown10 = {0}", track.unknown10); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unknown11 = {0}", track.unknown11); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.lastSector = {0}", track.lastSector); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unknown12 = {0}", track.unknown12); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.pregap = {0}", track.pregap); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unknown2 = {0}", track.unknown2); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unknown3 = {0}", track.unknown3); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.session = {0}", track.session); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unknown4 = {0}", track.unknown4); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.adrCtl = {0}", track.adrCtl); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unknown5 = {0}", track.unknown5); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.trackMode = {0}", track.trackMode); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unknown6 = {0}", track.unknown6); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.point = {0}", track.point); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unknown7 = {0}", track.unknown7); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unknown8 = {0}", track.unknown8); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unknown9 = {0}", track.unknown9); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unknown10 = {0}", track.unknown10); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unknown11 = {0}", track.unknown11); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.lastSector = {0}", track.lastSector); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unknown12 = {0}", track.unknown12); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.pregap = {0}", track.pregap); DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.startSector = {0}", track.startSector); + for(int j = 0; j < track.unknown13.Length; j++) DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unknown13[{1}] = 0x{0:X8}", track.unknown13[j], j); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.titleLen = {0}", track.titleLen); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.title = {0}", track.title); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.titleLen = {0}", track.titleLen); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.title = {0}", track.title); DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.performerLen = {0}", track.performerLen); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.performer = {0}", track.performer); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkStrLen1 = {0}", track.unkStrLen1); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkString1 = {0}", track.unkString1); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkStrLen2 = {0}", track.unkStrLen2); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkString2 = {0}", track.unkString2); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkStrLen3 = {0}", track.unkStrLen3); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkString3 = {0}", track.unkString3); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkStrLen4 = {0}", track.unkStrLen4); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkString4 = {0}", track.unkString4); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.discIdLen = {0}", track.discIdLen); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.discId = {0}", track.discId); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkStrLen5 = {0}", track.unkStrLen5); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkString5 = {0}", track.unkString5); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkStrLen6 = {0}", track.unkStrLen6); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkString6 = {0}", track.unkString6); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkStrLen7 = {0}", track.unkStrLen7); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkString7 = {0}", track.unkString7); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkStrLen8 = {0}", track.unkStrLen8); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkString8 = {0}", track.unkString8); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkStrLen9 = {0}", track.unkStrLen9); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkString9 = {0}", track.unkString9); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkStrLen10 = {0}", track.unkStrLen10); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkString10 = {0}", track.unkString10); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkStrLen11 = {0}", track.unkStrLen11); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkString11 = {0}", track.unkString11); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.isrcLen = {0}", track.isrcLen); - DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.isrcUpc = {0}", track.isrcUpc); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.performer = {0}", track.performer); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkStrLen1 = {0}", track.unkStrLen1); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkString1 = {0}", track.unkString1); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkStrLen2 = {0}", track.unkStrLen2); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkString2 = {0}", track.unkString2); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkStrLen3 = {0}", track.unkStrLen3); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkString3 = {0}", track.unkString3); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkStrLen4 = {0}", track.unkStrLen4); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkString4 = {0}", track.unkString4); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.discIdLen = {0}", track.discIdLen); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.discId = {0}", track.discId); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkStrLen5 = {0}", track.unkStrLen5); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkString5 = {0}", track.unkString5); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkStrLen6 = {0}", track.unkStrLen6); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkString6 = {0}", track.unkString6); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkStrLen7 = {0}", track.unkStrLen7); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkString7 = {0}", track.unkString7); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkStrLen8 = {0}", track.unkStrLen8); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkString8 = {0}", track.unkString8); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkStrLen9 = {0}", track.unkStrLen9); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkString9 = {0}", track.unkString9); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkStrLen10 = {0}", track.unkStrLen10); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkString10 = {0}", track.unkString10); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkStrLen11 = {0}", track.unkStrLen11); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.unkString11 = {0}", track.unkString11); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.isrcLen = {0}", track.isrcLen); + DicConsole.DebugWriteLine("BlindWrite4 plugin", "track.isrcUpc = {0}", track.isrcUpc); bwTracks.Add(track); } - FiltersList filtersList = new FiltersList(); + var filtersList = new FiltersList(); if(!string.IsNullOrEmpty(header.DataFile)) while(true) { dataFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), header.DataFile)); - if(dataFilter != null) break; + + if(dataFilter != null) + break; dataFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), - header.DataFile.ToLower(CultureInfo - .CurrentCulture))); - if(dataFilter != null) break; + header.DataFile.ToLower(CultureInfo. + CurrentCulture))); + + if(dataFilter != null) + break; dataFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), - header.DataFile.ToUpper(CultureInfo - .CurrentCulture))); - if(dataFilter != null) break; + header.DataFile.ToUpper(CultureInfo. + CurrentCulture))); - dataFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), - header.DataFile.Split(new[] {'\\'}, - StringSplitOptions - .RemoveEmptyEntries) - .Last())); - if(dataFilter != null) break; + if(dataFilter != null) + break; - dataFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), - header.DataFile.Split(new[] {'\\'}, - StringSplitOptions - .RemoveEmptyEntries).Last() - .ToLower(CultureInfo.CurrentCulture))); - if(dataFilter != null) break; + dataFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), header. + DataFile.Split(new[] + { + '\\' + }, + StringSplitOptions. + RemoveEmptyEntries). + Last())); - dataFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), - header.DataFile.Split(new[] {'\\'}, - StringSplitOptions - .RemoveEmptyEntries).Last() - .ToUpper(CultureInfo.CurrentCulture))); - if(dataFilter != null) break; + if(dataFilter != null) + break; + + dataFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), header. + DataFile.Split(new[] + { + '\\' + }, + StringSplitOptions. + RemoveEmptyEntries). + Last(). + ToLower(CultureInfo. + CurrentCulture))); + + if(dataFilter != null) + break; + + dataFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), header. + DataFile.Split(new[] + { + '\\' + }, + StringSplitOptions. + RemoveEmptyEntries). + Last(). + ToUpper(CultureInfo. + CurrentCulture))); + + if(dataFilter != null) + break; throw new ArgumentException($"Data file {header.DataFile} not found"); } - else throw new ArgumentException("Unable to find data file"); + else + throw new ArgumentException("Unable to find data file"); if(!string.IsNullOrEmpty(header.SubchannelFile)) { @@ -419,24 +460,35 @@ namespace DiscImageChef.DiscImages ((((filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), header.SubchannelFile)) ?? filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), header.SubchannelFile.ToLower(CultureInfo.CurrentCulture))) - ) ?? - filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), - header.SubchannelFile.ToUpper(CultureInfo.CurrentCulture))) - ) ?? - filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), - header.SubchannelFile.Split(new[] {'\\'}, - StringSplitOptions - .RemoveEmptyEntries).Last())) - ) ?? filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), - header.SubchannelFile.Split(new[] {'\\'}, - StringSplitOptions - .RemoveEmptyEntries).Last() - .ToLower(CultureInfo.CurrentCulture)))) ?? - filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), - header.SubchannelFile.Split(new[] {'\\'}, - StringSplitOptions - .RemoveEmptyEntries).Last() - .ToUpper(CultureInfo.CurrentCulture))); + ) ?? filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), + header.SubchannelFile. + ToUpper(CultureInfo.CurrentCulture)))) ?? + filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), header. + SubchannelFile.Split(new[] + { + '\\' + }, + StringSplitOptions. + RemoveEmptyEntries). + Last())) + ) ?? filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), header. + SubchannelFile.Split(new[] + { + '\\' + }, + StringSplitOptions. + RemoveEmptyEntries). + Last().ToLower(CultureInfo. + CurrentCulture))) + ) ?? filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), header. + SubchannelFile.Split(new[] + { + '\\' + }, + StringSplitOptions. + RemoveEmptyEntries). + Last().ToUpper(CultureInfo. + CurrentCulture))); } Tracks = new List(); @@ -445,78 +497,111 @@ namespace DiscImageChef.DiscImages trackFlags = new Dictionary(); ushort maxSession = 0; ulong currentPos = 0; + foreach(Bw4TrackDescriptor bwTrack in bwTracks) if(bwTrack.point < 0xA0) { - Track track = new Track {TrackDescription = bwTrack.title, TrackEndSector = bwTrack.lastSector}; + var track = new Track + { + TrackDescription = bwTrack.title, TrackEndSector = bwTrack.lastSector + }; if(!string.IsNullOrEmpty(bwTrack.filename)) do { track.TrackFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), bwTrack.filename)); - if(track.TrackFilter != null) break; + + if(track.TrackFilter != null) + break; track.TrackFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), - bwTrack.filename.ToLower(CultureInfo - .CurrentCulture))); - if(track.TrackFilter != null) break; + bwTrack.filename.ToLower(CultureInfo. + CurrentCulture))); + + if(track.TrackFilter != null) + break; track.TrackFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), - bwTrack.filename.ToUpper(CultureInfo - .CurrentCulture))); - if(track.TrackFilter != null) break; + bwTrack.filename.ToUpper(CultureInfo. + CurrentCulture))); - track.TrackFilter = - filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), - bwTrack.filename.Split(new[] {'\\'}, - StringSplitOptions - .RemoveEmptyEntries) - .Last())); - if(track.TrackFilter != null) break; + if(track.TrackFilter != null) + break; - track.TrackFilter = - filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), - bwTrack.filename.Split(new[] {'\\'}, - StringSplitOptions - .RemoveEmptyEntries).Last() - .ToLower(CultureInfo.CurrentCulture))); - if(track.TrackFilter != null) break; + track.TrackFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), + bwTrack.filename.Split(new[] + { + '\\' + }, + StringSplitOptions. + RemoveEmptyEntries). + Last())); - track.TrackFilter = - filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), - bwTrack.filename.Split(new[] {'\\'}, - StringSplitOptions - .RemoveEmptyEntries).Last() - .ToUpper(CultureInfo.CurrentCulture))); + if(track.TrackFilter != null) + break; + + track.TrackFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), + bwTrack.filename.Split(new[] + { + '\\' + }, + StringSplitOptions. + RemoveEmptyEntries). + Last(). + ToLower(CultureInfo. + CurrentCulture))); + + if(track.TrackFilter != null) + break; + + track.TrackFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), + bwTrack.filename.Split(new[] + { + '\\' + }, + StringSplitOptions. + RemoveEmptyEntries). + Last(). + ToUpper(CultureInfo. + CurrentCulture))); track.TrackFilter = dataFilter; - } - while(true); - else track.TrackFilter = dataFilter; + } while(true); + else + track.TrackFilter = dataFilter; track.TrackFile = dataFilter.GetFilename(); + if(bwTrack.pregap != 0) track.TrackFileOffset += (ulong)(bwTrack.startSector - bwTrack.pregap) * 2352; + track.TrackFileType = "BINARY"; track.TrackPregap = (ulong)(bwTrack.startSector - bwTrack.pregap); track.TrackRawBytesPerSector = 2352; track.TrackSequence = bwTrack.point; track.TrackSession = bwTrack.session; - if(track.TrackSession > maxSession) maxSession = track.TrackSession; + + if(track.TrackSession > maxSession) + maxSession = track.TrackSession; + track.TrackStartSector = (ulong)bwTrack.startSector; track.TrackSubchannelFilter = subFilter; track.TrackSubchannelFile = subFilter.GetFilename(); - track.TrackSubchannelOffset = track.TrackStartSector * 96 + track.TrackPregap * 96; - if(subFilter != null && bwTrack.subchannel > 0) + track.TrackSubchannelOffset = (track.TrackStartSector * 96) + (track.TrackPregap * 96); + + if(subFilter != null && + bwTrack.subchannel > 0) { track.TrackSubchannelType = TrackSubchannelType.Packed; + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel); } - else track.TrackSubchannelType = TrackSubchannelType.None; + else + track.TrackSubchannelType = TrackSubchannelType.None; switch(bwTrack.trackMode) { @@ -524,51 +609,76 @@ namespace DiscImageChef.DiscImages track.TrackType = TrackType.Audio; imageInfo.SectorSize = 2352; track.TrackBytesPerSector = 2352; + break; case Bw4TrackType.Mode1: track.TrackType = TrackType.CdMode1; + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); - if(imageInfo.SectorSize < 2048) imageInfo.SectorSize = 2048; + + if(imageInfo.SectorSize < 2048) + imageInfo.SectorSize = 2048; + track.TrackBytesPerSector = 2048; + break; case Bw4TrackType.Mode2: track.TrackType = TrackType.CdMode2Formless; + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); - if(imageInfo.SectorSize < 2336) imageInfo.SectorSize = 2336; + + if(imageInfo.SectorSize < 2336) + imageInfo.SectorSize = 2336; + track.TrackBytesPerSector = 2336; + break; default: track.TrackType = TrackType.Data; track.TrackRawBytesPerSector = 2048; imageInfo.SectorSize = 2048; track.TrackBytesPerSector = 2048; + break; } track.Indexes = new Dictionary(); - if(bwTrack.pregap > 0) track.Indexes.Add(0, (ulong)bwTrack.pregap); + + if(bwTrack.pregap > 0) + track.Indexes.Add(0, (ulong)bwTrack.pregap); + track.Indexes.Add(1, (ulong)bwTrack.startSector); - Partition partition = new Partition(); - if(bwTrack.pregap > 0) currentPos += (ulong)(bwTrack.startSector - bwTrack.pregap) * 2352; + var partition = new Partition(); + + if(bwTrack.pregap > 0) + currentPos += (ulong)(bwTrack.startSector - bwTrack.pregap) * 2352; + partition.Description = track.TrackDescription; - partition.Size = (track.TrackEndSector - track.TrackStartSector + 1) * 2352; + partition.Size = ((track.TrackEndSector - track.TrackStartSector) + 1) * 2352; partition.Length = track.TrackEndSector - track.TrackStartSector; partition.Sequence = track.TrackSequence; partition.Offset = currentPos; @@ -585,7 +695,7 @@ namespace DiscImageChef.DiscImages if(!trackFlags.ContainsKey(track.TrackSequence)) trackFlags.Add(track.TrackSequence, (byte)(bwTrack.adrCtl & 0x0F)); - imageInfo.Sectors += (ulong)(bwTrack.lastSector - bwTrack.startSector + 1); + imageInfo.Sectors += (ulong)((bwTrack.lastSector - bwTrack.startSector) + 1); } else { @@ -599,19 +709,27 @@ namespace DiscImageChef.DiscImages } Sessions = new List(); + for(ushort i = 1; i <= maxSession; i++) { - Session session = new Session + var session = new Session { SessionSequence = i, StartTrack = uint.MaxValue, StartSector = uint.MaxValue }; foreach(Track track in Tracks.Where(track => track.TrackSession == i)) { - if(track.TrackSequence < session.StartTrack) session.StartTrack = track.TrackSequence; - if(track.TrackSequence > session.EndTrack) session.StartTrack = track.TrackSequence; - if(track.TrackStartSector < session.StartSector) session.StartSector = track.TrackStartSector; - if(track.TrackEndSector > session.EndSector) session.EndSector = track.TrackEndSector; + if(track.TrackSequence < session.StartTrack) + session.StartTrack = track.TrackSequence; + + if(track.TrackSequence > session.EndTrack) + session.StartTrack = track.TrackSequence; + + if(track.TrackStartSector < session.StartSector) + session.StartSector = track.TrackStartSector; + + if(track.TrackEndSector > session.EndSector) + session.EndSector = track.TrackEndSector; } Sessions.Add(session); @@ -652,19 +770,30 @@ namespace DiscImageChef.DiscImages { case TrackType.CdMode2Formless: mode2 = true; + break; } } - 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; + 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; imageInfo.Comments = header.Comments; DicConsole.VerboseWriteLine("BlindWrite image describes a disc of type {0}", imageInfo.MediaType); + if(!string.IsNullOrEmpty(imageInfo.Comments)) DicConsole.VerboseWriteLine("BlindrWrite comments: {0}", imageInfo.Comments); @@ -677,7 +806,8 @@ namespace DiscImageChef.DiscImages { case MediaTagType.CD_MCN: { - if(imageInfo.MediaSerialNumber != null) return Encoding.ASCII.GetBytes(imageInfo.MediaSerialNumber); + if(imageInfo.MediaSerialNumber != null) + return Encoding.ASCII.GetBytes(imageInfo.MediaSerialNumber); throw new FeatureNotPresentImageException("Image does not contain MCN information."); } @@ -697,12 +827,10 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectors(ulong sectorAddress, uint length) { - foreach(KeyValuePair kvp in from kvp in offsetmap - where sectorAddress >= kvp.Value - from track in Tracks - where track.TrackSequence == kvp.Key - where sectorAddress - kvp.Value < - track.TrackEndSector - track.TrackStartSector + 1 + foreach(KeyValuePair kvp in from kvp in offsetmap where sectorAddress >= kvp.Value + from track in Tracks where track.TrackSequence == kvp.Key + where sectorAddress - kvp.Value < + (track.TrackEndSector - track.TrackStartSector) + 1 select kvp) return ReadSectors(sectorAddress - kvp.Value, length, kvp.Key); @@ -711,12 +839,10 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) { - foreach(KeyValuePair kvp in from kvp in offsetmap - where sectorAddress >= kvp.Value - from track in Tracks - where track.TrackSequence == kvp.Key - where sectorAddress - kvp.Value < - track.TrackEndSector - track.TrackStartSector + 1 + foreach(KeyValuePair kvp in from kvp in offsetmap where sectorAddress >= kvp.Value + from track in Tracks where track.TrackSequence == kvp.Key + where sectorAddress - kvp.Value < + (track.TrackEndSector - track.TrackStartSector) + 1 select kvp) return ReadSectorsTag(sectorAddress - kvp.Value, length, kvp.Key, tag); @@ -725,24 +851,29 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectors(ulong sectorAddress, uint length, uint track) { - Track dicTrack = new Track {TrackSequence = 0}; + var dicTrack = new Track + { + TrackSequence = 0 + }; foreach(Track bwTrack in Tracks.Where(bwTrack => bwTrack.TrackSequence == track)) { dicTrack = bwTrack; + break; } if(dicTrack.TrackSequence == 0) throw new ArgumentOutOfRangeException(nameof(track), "Track does not exist in disc image"); - if(length + sectorAddress > dicTrack.TrackEndSector - dicTrack.TrackStartSector + 1) + if(length + sectorAddress > (dicTrack.TrackEndSector - dicTrack.TrackStartSector) + 1) throw new ArgumentOutOfRangeException(nameof(length), - $"Requested more sectors ({length + sectorAddress}) than present in track ({dicTrack.TrackEndSector - dicTrack.TrackStartSector + 1}), won't cross tracks"); + $"Requested more sectors ({length + sectorAddress}) than present in track ({(dicTrack.TrackEndSector - dicTrack.TrackStartSector) + 1}), won't cross tracks"); uint sectorOffset; uint sectorSize; uint sectorSkip; + bool mode2 = false; switch(dicTrack.TrackType) { @@ -751,13 +882,16 @@ namespace DiscImageChef.DiscImages sectorOffset = 16; sectorSize = 2048; sectorSkip = 288; + break; } case TrackType.CdMode2Formless: { - sectorOffset = 16; - sectorSize = 2336; + mode2 = true; + sectorOffset = 0; + sectorSize = 2352; sectorSkip = 0; + break; } case TrackType.Audio: @@ -765,6 +899,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 2352; sectorSkip = 0; + break; } case TrackType.Data: @@ -772,6 +907,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 2048; sectorSkip = 0; + break; } default: throw new FeatureSupportedButNotImplementedImageException("Unsupported track type"); @@ -780,11 +916,31 @@ namespace DiscImageChef.DiscImages byte[] buffer = new byte[sectorSize * length]; imageStream = dicTrack.TrackFilter.GetDataForkStream(); - BinaryReader br = new BinaryReader(imageStream); - br.BaseStream - .Seek((long)dicTrack.TrackFileOffset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), + var br = new BinaryReader(imageStream); + + br.BaseStream. + Seek((long)dicTrack.TrackFileOffset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), SeekOrigin.Begin); - if(sectorOffset == 0 && sectorSkip == 0) buffer = br.ReadBytes((int)(sectorSize * length)); + + if(mode2) + { + var mode2Ms = new MemoryStream((int)(sectorSize * length)); + + buffer = br.ReadBytes((int)(sectorSize * length)); + + for(int i = 0; i < length; i++) + { + byte[] sector = new byte[sectorSize]; + Array.Copy(buffer, sectorSize * i, sector, 0, sectorSize); + sector = Sector.GetUserDataFromMode2(sector); + mode2Ms.Write(sector, 0, sector.Length); + } + + buffer = mode2Ms.ToArray(); + } + else if(sectorOffset == 0 && + sectorSkip == 0) + buffer = br.ReadBytes((int)(sectorSize * length)); else for(int i = 0; i < length; i++) { @@ -799,20 +955,24 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) { - Track dicTrack = new Track {TrackSequence = 0}; + var dicTrack = new Track + { + TrackSequence = 0 + }; foreach(Track bwTrack in Tracks.Where(bwTrack => bwTrack.TrackSequence == track)) { dicTrack = bwTrack; + break; } if(dicTrack.TrackSequence == 0) throw new ArgumentOutOfRangeException(nameof(track), "Track does not exist in disc image"); - if(length + sectorAddress > dicTrack.TrackEndSector - dicTrack.TrackStartSector + 1) + if(length + sectorAddress > (dicTrack.TrackEndSector - dicTrack.TrackStartSector) + 1) throw new ArgumentOutOfRangeException(nameof(length), - $"Requested more sectors ({length + sectorAddress}) than present in track ({dicTrack.TrackEndSector - dicTrack.TrackStartSector + 1}), won't cross tracks"); + $"Requested more sectors ({length + sectorAddress}) than present in track ({(dicTrack.TrackEndSector - dicTrack.TrackStartSector) + 1}), won't cross tracks"); uint sectorOffset; uint sectorSize; @@ -832,7 +992,11 @@ namespace DiscImageChef.DiscImages case SectorTagType.CdSectorSubHeader: case SectorTagType.CdSectorSync: break; case SectorTagType.CdTrackFlags: - if(trackFlags.TryGetValue(track, out byte flag)) return new[] {flag}; + if(trackFlags.TryGetValue(track, out byte flag)) + return new[] + { + flag + }; throw new ArgumentException("Unsupported tag requested", nameof(tag)); default: throw new ArgumentException("Unsupported tag requested", nameof(tag)); @@ -848,6 +1012,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 12; sectorSkip = 2340; + break; } case SectorTagType.CdSectorHeader: @@ -855,6 +1020,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 12; sectorSize = 4; sectorSkip = 2336; + break; } case SectorTagType.CdSectorSubHeader: @@ -864,6 +1030,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2076; sectorSize = 276; sectorSkip = 0; + break; } case SectorTagType.CdSectorEccP: @@ -871,6 +1038,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2076; sectorSize = 172; sectorSkip = 104; + break; } case SectorTagType.CdSectorEccQ: @@ -878,6 +1046,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2248; sectorSize = 104; sectorSkip = 0; + break; } case SectorTagType.CdSectorEdc: @@ -885,6 +1054,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2064; sectorSize = 4; sectorSkip = 284; + break; } case SectorTagType.CdSectorSubchannel: @@ -908,6 +1078,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 8; sectorSkip = 2328; + break; } case SectorTagType.CdSectorEdc: @@ -915,6 +1086,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2332; sectorSize = 4; sectorSkip = 0; + break; } case SectorTagType.CdSectorSubchannel: @@ -939,11 +1111,15 @@ namespace DiscImageChef.DiscImages byte[] buffer = new byte[sectorSize * length]; imageStream = dicTrack.TrackFilter.GetDataForkStream(); - BinaryReader br = new BinaryReader(imageStream); - br.BaseStream - .Seek((long)dicTrack.TrackFileOffset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), + var br = new BinaryReader(imageStream); + + br.BaseStream. + Seek((long)dicTrack.TrackFileOffset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), SeekOrigin.Begin); - if(sectorOffset == 0 && sectorSkip == 0) buffer = br.ReadBytes((int)(sectorSize * length)); + + if(sectorOffset == 0 && + sectorSkip == 0) + buffer = br.ReadBytes((int)(sectorSize * length)); else for(int i = 0; i < length; i++) { @@ -962,12 +1138,10 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectorsLong(ulong sectorAddress, uint length) { - foreach(KeyValuePair kvp in from kvp in offsetmap - where sectorAddress >= kvp.Value - from track in Tracks - where track.TrackSequence == kvp.Key - where sectorAddress - kvp.Value < - track.TrackEndSector - track.TrackStartSector + 1 + foreach(KeyValuePair kvp in from kvp in offsetmap where sectorAddress >= kvp.Value + from track in Tracks where track.TrackSequence == kvp.Key + where sectorAddress - kvp.Value < + (track.TrackEndSector - track.TrackStartSector) + 1 select kvp) return ReadSectorsLong(sectorAddress - kvp.Value, length, kvp.Key); @@ -976,20 +1150,24 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) { - Track dicTrack = new Track {TrackSequence = 0}; + var dicTrack = new Track + { + TrackSequence = 0 + }; foreach(Track bwTrack in Tracks.Where(bwTrack => bwTrack.TrackSequence == track)) { dicTrack = bwTrack; + break; } if(dicTrack.TrackSequence == 0) throw new ArgumentOutOfRangeException(nameof(track), "Track does not exist in disc image"); - if(length + sectorAddress > dicTrack.TrackEndSector - dicTrack.TrackStartSector + 1) + if(length + sectorAddress > (dicTrack.TrackEndSector - dicTrack.TrackStartSector) + 1) throw new ArgumentOutOfRangeException(nameof(length), - $"Requested more sectors ({length + sectorAddress}) than present in track ({dicTrack.TrackEndSector - dicTrack.TrackStartSector + 1}), won't cross tracks"); + $"Requested more sectors ({length + sectorAddress}) than present in track ({(dicTrack.TrackEndSector - dicTrack.TrackStartSector) + 1}), won't cross tracks"); uint sectorOffset; uint sectorSize; @@ -1005,16 +1183,19 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = (uint)dicTrack.TrackRawBytesPerSector; sectorSkip = 0; + break; } default: throw new FeatureSupportedButNotImplementedImageException("Unsupported track type"); } imageStream = dicTrack.TrackFilter.GetDataForkStream(); - BinaryReader br = new BinaryReader(imageStream); - br.BaseStream - .Seek((long)dicTrack.TrackFileOffset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), + var br = new BinaryReader(imageStream); + + br.BaseStream. + Seek((long)dicTrack.TrackFileOffset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), SeekOrigin.Begin); + byte[] buffer = br.ReadBytes((int)(sectorSize * length)); return buffer; @@ -1022,14 +1203,13 @@ namespace DiscImageChef.DiscImages public List 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 GetSessionTracks(ushort session) - { - return Tracks.Where(track => track.TrackSession == session).ToList(); - } + public List GetSessionTracks(ushort session) => + Tracks.Where(track => track.TrackSession == session).ToList(); } } \ No newline at end of file diff --git a/DiscImageChef.DiscImages/BlindWrite5/Read.cs b/DiscImageChef.DiscImages/BlindWrite5/Read.cs index b152b1aa9..05f3c2947 100644 --- a/DiscImageChef.DiscImages/BlindWrite5/Read.cs +++ b/DiscImageChef.DiscImages/BlindWrite5/Read.cs @@ -1276,6 +1276,7 @@ namespace DiscImageChef.DiscImages uint sectorOffset; uint sectorSize; uint sectorSkip; + bool mode2 = false; switch(dicTrack.TrackType) { @@ -1288,26 +1289,13 @@ namespace DiscImageChef.DiscImages break; } case TrackType.CdMode2Formless: - { - sectorOffset = 16; - sectorSize = 2336; - sectorSkip = 0; - - break; - } case TrackType.CdMode2Form1: - { - sectorOffset = 24; - sectorSize = 2048; - sectorSkip = 280; - - break; - } case TrackType.CdMode2Form2: { - sectorOffset = 24; - sectorSize = 2324; - sectorSkip = 4; + mode2 = true; + sectorOffset = 0; + sectorSize = 2352; + sectorSkip = 0; break; } @@ -1356,8 +1344,24 @@ namespace DiscImageChef.DiscImages Seek((long)dicTrack.TrackFileOffset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), SeekOrigin.Begin); - if(sectorOffset == 0 && - sectorSkip == 0) + if(mode2) + { + var mode2Ms = new MemoryStream((int)(sectorSize * length)); + + buffer = br.ReadBytes((int)(sectorSize * length)); + + for(int i = 0; i < length; i++) + { + byte[] sector = new byte[sectorSize]; + Array.Copy(buffer, sectorSize * i, sector, 0, sectorSize); + sector = Sector.GetUserDataFromMode2(sector); + mode2Ms.Write(sector, 0, sector.Length); + } + + buffer = mode2Ms.ToArray(); + } + else if(sectorOffset == 0 && + sectorSkip == 0) buffer = br.ReadBytes((int)(sectorSize * length)); else for(int i = 0; i < length; i++) diff --git a/DiscImageChef.DiscImages/CDRDAO/Read.cs b/DiscImageChef.DiscImages/CDRDAO/Read.cs index 7b8cbdf33..be90aae3b 100644 --- a/DiscImageChef.DiscImages/CDRDAO/Read.cs +++ b/DiscImageChef.DiscImages/CDRDAO/Read.cs @@ -42,6 +42,8 @@ using DiscImageChef.CommonTypes.Exceptions; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Structs; using DiscImageChef.Console; +using DiscImageChef.Decoders.CD; +using Session = DiscImageChef.CommonTypes.Structs.Session; namespace DiscImageChef.DiscImages { @@ -816,6 +818,7 @@ namespace DiscImageChef.DiscImages uint sectorOffset; uint sectorSize; uint sectorSkip; + bool mode2 = false; switch(dicTrack.Tracktype) { @@ -837,6 +840,7 @@ namespace DiscImageChef.DiscImages case CDRDAO_TRACK_TYPE_MODE2: case CDRDAO_TRACK_TYPE_MODE2_MIX: { + mode2 = true; sectorOffset = 0; sectorSize = 2336; sectorSkip = 0; @@ -858,8 +862,9 @@ namespace DiscImageChef.DiscImages } case CDRDAO_TRACK_TYPE_MODE2_RAW: { - sectorOffset = 16; - sectorSize = 2336; + mode2 = true; + sectorOffset = 0; + sectorSize = 2352; sectorSkip = 0; break; } @@ -875,7 +880,23 @@ namespace DiscImageChef.DiscImages br.BaseStream .Seek((long)dicTrack.Trackfile.Offset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), SeekOrigin.Begin); - if(sectorOffset == 0 && sectorSkip == 0) buffer = br.ReadBytes((int)(sectorSize * length)); + if(mode2) + { + var mode2Ms = new MemoryStream((int)(sectorSize * length)); + + buffer = br.ReadBytes((int)(sectorSize * length)); + + for(int i = 0; i < length; i++) + { + byte[] sector = new byte[sectorSize]; + Array.Copy(buffer, sectorSize * i, sector, 0, sectorSize); + sector = Sector.GetUserDataFromMode2(sector); + mode2Ms.Write(sector, 0, sector.Length); + } + + buffer = mode2Ms.ToArray(); + } +else if(sectorOffset == 0 && sectorSkip == 0) buffer = br.ReadBytes((int)(sectorSize * length)); else for(int i = 0; i < length; i++) { diff --git a/DiscImageChef.DiscImages/CDRWin/Read.cs b/DiscImageChef.DiscImages/CDRWin/Read.cs index d0c97f48d..076967cda 100644 --- a/DiscImageChef.DiscImages/CDRWin/Read.cs +++ b/DiscImageChef.DiscImages/CDRWin/Read.cs @@ -42,7 +42,9 @@ using DiscImageChef.CommonTypes.Exceptions; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Structs; using DiscImageChef.Console; +using DiscImageChef.Decoders.CD; using Schemas; +using Session = DiscImageChef.CommonTypes.Structs.Session; namespace DiscImageChef.DiscImages { @@ -1319,6 +1321,7 @@ namespace DiscImageChef.DiscImages uint sectorOffset; uint sectorSize; uint sectorSkip; + bool mode2 = false; switch(dicTrack.TrackType) { @@ -1342,6 +1345,7 @@ namespace DiscImageChef.DiscImages case CDRWIN_TRACK_TYPE_MODE2_FORMLESS: case CDRWIN_TRACK_TYPE_CDI: { + mode2 = true; sectorOffset = 0; sectorSize = 2336; sectorSkip = 0; @@ -1365,17 +1369,11 @@ namespace DiscImageChef.DiscImages break; } case CDRWIN_TRACK_TYPE_MODE2_RAW: - { - sectorOffset = 16; - sectorSize = 2336; - sectorSkip = 0; - - break; - } case CDRWIN_TRACK_TYPE_CDI_RAW: { - sectorOffset = 16; - sectorSize = 2336; + mode2 = true; + sectorOffset = 0; + sectorSize = 2352; sectorSkip = 0; break; @@ -1400,8 +1398,24 @@ namespace DiscImageChef.DiscImages Seek((long)dicTrack.TrackFile.Offset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), SeekOrigin.Begin); - if(sectorOffset == 0 && - sectorSkip == 0) + if(mode2) + { + var mode2Ms = new MemoryStream((int)(sectorSize * length)); + + buffer = br.ReadBytes((int)(sectorSize * length)); + + for(int i = 0; i < length; i++) + { + byte[] sector = new byte[sectorSize]; + Array.Copy(buffer, sectorSize * i, sector, 0, sectorSize); + sector = Sector.GetUserDataFromMode2(sector); + mode2Ms.Write(sector, 0, sector.Length); + } + + buffer = mode2Ms.ToArray(); + } + else if(sectorOffset == 0 && + sectorSkip == 0) buffer = br.ReadBytes((int)(sectorSize * length)); else for(int i = 0; i < length; i++) diff --git a/DiscImageChef.DiscImages/CHD/Read.cs b/DiscImageChef.DiscImages/CHD/Read.cs index 0937fd3be..5eaa83dac 100644 --- a/DiscImageChef.DiscImages/CHD/Read.cs +++ b/DiscImageChef.DiscImages/CHD/Read.cs @@ -43,7 +43,9 @@ using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Structs; using DiscImageChef.CommonTypes.Structs.Devices.ATA; using DiscImageChef.Console; +using DiscImageChef.Decoders.CD; using DiscImageChef.Helpers; +using Session = DiscImageChef.CommonTypes.Structs.Session; namespace DiscImageChef.DiscImages { @@ -1198,11 +1200,11 @@ namespace DiscImageChef.DiscImages return sector; uint sectorOffset; + bool mode2 = false; switch(track.TrackType) { case TrackType.CdMode1: - case TrackType.CdMode2Form1: { if(track.TrackRawBytesPerSector == 2352) { @@ -1217,13 +1219,30 @@ namespace DiscImageChef.DiscImages break; } + case TrackType.CdMode2Form1: + { + if(track.TrackRawBytesPerSector == 2352) + { + sectorOffset = 0; + sectorSize = 2352; + mode2 = true; + } + else + { + sectorOffset = 0; + sectorSize = 2048; + } + + break; + } case TrackType.CdMode2Form2: { if(track.TrackRawBytesPerSector == 2352) { - sectorOffset = 16; - sectorSize = 2324; + sectorOffset = 0; + sectorSize = 2352; + mode2 = true; } else { @@ -1236,16 +1255,9 @@ namespace DiscImageChef.DiscImages case TrackType.CdMode2Formless: { - if(track.TrackRawBytesPerSector == 2352) - { - sectorOffset = 16; - sectorSize = 2336; - } - else - { - sectorOffset = 0; - sectorSize = 2336; - } + sectorOffset = 0; + sectorSize = (uint)track.TrackRawBytesPerSector; + mode2 = true; break; } @@ -1263,7 +1275,9 @@ namespace DiscImageChef.DiscImages byte[] buffer = new byte[sectorSize]; - if(track.TrackType == TrackType.Audio && swapAudio) + if(mode2) + buffer = Sector.GetUserDataFromMode2(sector); + else if(track.TrackType == TrackType.Audio && swapAudio) for(int i = 0; i < 2352; i += 2) { buffer[i + 1] = sector[i]; diff --git a/DiscImageChef.DiscImages/CloneCD/Read.cs b/DiscImageChef.DiscImages/CloneCD/Read.cs index 80466411c..e05a005a3 100644 --- a/DiscImageChef.DiscImages/CloneCD/Read.cs +++ b/DiscImageChef.DiscImages/CloneCD/Read.cs @@ -50,7 +50,8 @@ namespace DiscImageChef.DiscImages { public bool Open(IFilter imageFilter) { - if(imageFilter == null) return false; + if(imageFilter == null) + return false; ccdFilter = imageFilter; @@ -60,36 +61,36 @@ namespace DiscImageChef.DiscImages cueStream = new StreamReader(imageFilter.GetDataForkStream()); int lineNumber = 0; - Regex ccdIdRegex = new Regex(CCD_IDENTIFIER); - Regex discIdRegex = new Regex(DISC_IDENTIFIER); - Regex sessIdRegex = new Regex(SESSION_IDENTIFIER); - Regex entryIdRegex = new Regex(ENTRY_IDENTIFIER); - Regex trackIdRegex = new Regex(TRACK_IDENTIFIER); - Regex cdtIdRegex = new Regex(CDTEXT_IDENTIFIER); - Regex ccdVerRegex = new Regex(CCD_VERSION); - Regex discEntRegex = new Regex(DISC_ENTRIES); - Regex discSessRegex = new Regex(DISC_SESSIONS); - Regex discScrRegex = new Regex(DISC_SCRAMBLED); - Regex cdtLenRegex = new Regex(CDTEXT_LENGTH); - Regex discCatRegex = new Regex(DISC_CATALOG); - Regex sessPregRegex = new Regex(SESSION_PREGAP); - Regex sessSubcRegex = new Regex(SESSION_SUBCHANNEL); - Regex entSessRegex = new Regex(ENTRY_SESSION); - Regex entPointRegex = new Regex(ENTRY_POINT); - Regex entAdrRegex = new Regex(ENTRY_ADR); - Regex entCtrlRegex = new Regex(ENTRY_CONTROL); - Regex entTnoRegex = new Regex(ENTRY_TRACKNO); - Regex entAMinRegex = new Regex(ENTRY_AMIN); - Regex entASecRegex = new Regex(ENTRY_ASEC); - Regex entAFrameRegex = new Regex(ENTRY_AFRAME); - Regex entAlbaRegex = new Regex(ENTRY_ALBA); - Regex entZeroRegex = new Regex(ENTRY_ZERO); - Regex entPMinRegex = new Regex(ENTRY_PMIN); - Regex entPSecRegex = new Regex(ENTRY_PSEC); - Regex entPFrameRegex = new Regex(ENTRY_PFRAME); - Regex entPlbaRegex = new Regex(ENTRY_PLBA); - Regex cdtEntsRegex = new Regex(CDTEXT_ENTRIES); - Regex cdtEntRegex = new Regex(CDTEXT_ENTRY); + var ccdIdRegex = new Regex(CCD_IDENTIFIER); + var discIdRegex = new Regex(DISC_IDENTIFIER); + var sessIdRegex = new Regex(SESSION_IDENTIFIER); + var entryIdRegex = new Regex(ENTRY_IDENTIFIER); + var trackIdRegex = new Regex(TRACK_IDENTIFIER); + var cdtIdRegex = new Regex(CDTEXT_IDENTIFIER); + var ccdVerRegex = new Regex(CCD_VERSION); + var discEntRegex = new Regex(DISC_ENTRIES); + var discSessRegex = new Regex(DISC_SESSIONS); + var discScrRegex = new Regex(DISC_SCRAMBLED); + var cdtLenRegex = new Regex(CDTEXT_LENGTH); + var discCatRegex = new Regex(DISC_CATALOG); + var sessPregRegex = new Regex(SESSION_PREGAP); + var sessSubcRegex = new Regex(SESSION_SUBCHANNEL); + var entSessRegex = new Regex(ENTRY_SESSION); + var entPointRegex = new Regex(ENTRY_POINT); + var entAdrRegex = new Regex(ENTRY_ADR); + var entCtrlRegex = new Regex(ENTRY_CONTROL); + var entTnoRegex = new Regex(ENTRY_TRACKNO); + var entAMinRegex = new Regex(ENTRY_AMIN); + var entASecRegex = new Regex(ENTRY_ASEC); + var entAFrameRegex = new Regex(ENTRY_AFRAME); + var entAlbaRegex = new Regex(ENTRY_ALBA); + var entZeroRegex = new Regex(ENTRY_ZERO); + var entPMinRegex = new Regex(ENTRY_PMIN); + var entPSecRegex = new Regex(ENTRY_PSEC); + var entPFrameRegex = new Regex(ENTRY_PFRAME); + var entPlbaRegex = new Regex(ENTRY_PLBA); + var cdtEntsRegex = new Regex(CDTEXT_ENTRIES); + var cdtEntRegex = new Regex(CDTEXT_ENTRY); bool inCcd = false; bool inDisk = false; @@ -97,10 +98,10 @@ namespace DiscImageChef.DiscImages bool inEntry = false; bool inTrack = false; bool inCdText = false; - MemoryStream cdtMs = new MemoryStream(); + var cdtMs = new MemoryStream(); int minSession = int.MaxValue; int maxSession = int.MinValue; - FullTOC.TrackDataDescriptor currentEntry = new FullTOC.TrackDataDescriptor(); + var currentEntry = new FullTOC.TrackDataDescriptor(); List entries = new List(); scrambled = false; catalog = null; @@ -120,7 +121,11 @@ namespace DiscImageChef.DiscImages // [CloneCD] if(ccdIdMatch.Success) { - if(inDisk || inSession || inEntry || inTrack || inCdText) + if(inDisk || + inSession || + inEntry || + inTrack || + inCdText) throw new FeatureUnsupportedImageException($"Found [CloneCD] out of order in line {lineNumber}"); @@ -131,8 +136,11 @@ namespace DiscImageChef.DiscImages inTrack = false; inCdText = false; } - else if(discIdMatch.Success || sessIdMatch.Success || entryIdMatch.Success || - trackIdMatch.Success || cdtIdMatch.Success) + else if(discIdMatch.Success || + sessIdMatch.Success || + entryIdMatch.Success || + trackIdMatch.Success || + cdtIdMatch.Success) { if(inEntry) { @@ -153,14 +161,17 @@ namespace DiscImageChef.DiscImages { Match ccdVerMatch = ccdVerRegex.Match(line); - if(!ccdVerMatch.Success) continue; + if(!ccdVerMatch.Success) + continue; DicConsole.DebugWriteLine("CloneCD plugin", "Found Version at line {0}", lineNumber); imageInfo.Version = ccdVerMatch.Groups["value"].Value; - if(imageInfo.Version != "2" && imageInfo.Version != "3") - DicConsole - .ErrorWriteLine("(CloneCD plugin): Warning! Unknown CCD image version {0}, may not work!", + + if(imageInfo.Version != "2" && + imageInfo.Version != "3") + DicConsole. + ErrorWriteLine("(CloneCD plugin): Warning! Unknown CCD image version {0}, may not work!", imageInfo.Version); } else if(inDisk) @@ -179,6 +190,7 @@ namespace DiscImageChef.DiscImages { DicConsole.DebugWriteLine("CloneCD plugin", "Found DataTracksScrambled at line {0}", lineNumber); + scrambled |= discScrMatch.Groups["value"].Value == "1"; } else if(cdtLenMatch.Success) @@ -190,6 +202,7 @@ namespace DiscImageChef.DiscImages catalog = discCatMatch.Groups["value"].Value; } } + // TODO: Do not suppose here entries come sorted else if(inCdText) { @@ -203,12 +216,17 @@ namespace DiscImageChef.DiscImages { DicConsole.DebugWriteLine("CloneCD plugin", "Found CD-Text Entry at line {0}", lineNumber); - string[] bytes = cdtEntMatch.Groups["value"].Value.Split(new[] {' '}, - StringSplitOptions - .RemoveEmptyEntries); - foreach(string byt in bytes) cdtMs.WriteByte(Convert.ToByte(byt, 16)); + + string[] bytes = cdtEntMatch.Groups["value"].Value.Split(new[] + { + ' ' + }, StringSplitOptions.RemoveEmptyEntries); + + foreach(string byt in bytes) + cdtMs.WriteByte(Convert.ToByte(byt, 16)); } } + // Is this useful? else if(inSession) { @@ -241,8 +259,12 @@ namespace DiscImageChef.DiscImages { DicConsole.DebugWriteLine("CloneCD plugin", "Found Session at line {0}", lineNumber); currentEntry.SessionNumber = Convert.ToByte(entSessMatch.Groups["value"].Value, 10); - if(currentEntry.SessionNumber < minSession) minSession = currentEntry.SessionNumber; - if(currentEntry.SessionNumber > maxSession) maxSession = currentEntry.SessionNumber; + + if(currentEntry.SessionNumber < minSession) + minSession = currentEntry.SessionNumber; + + if(currentEntry.SessionNumber > maxSession) + maxSession = currentEntry.SessionNumber; } else if(entPointMatch.Success) { @@ -309,19 +331,22 @@ namespace DiscImageChef.DiscImages } } - if(inEntry) entries.Add(currentEntry); + if(inEntry) + entries.Add(currentEntry); - if(entries.Count == 0) throw new FeatureUnsupportedImageException("Did not find any track."); + if(entries.Count == 0) + throw new FeatureUnsupportedImageException("Did not find any track."); FullTOC.CDFullTOC toc; toc.TrackDescriptors = entries.ToArray(); toc.LastCompleteSession = (byte)maxSession; toc.FirstCompleteSession = (byte)minSession; - toc.DataLength = (ushort)(entries.Count * 11 + 2); - MemoryStream tocMs = new MemoryStream(); + toc.DataLength = (ushort)((entries.Count * 11) + 2); + var tocMs = new MemoryStream(); tocMs.Write(BigEndianBitConverter.GetBytes(toc.DataLength), 0, 2); tocMs.WriteByte(toc.FirstCompleteSession); tocMs.WriteByte(toc.LastCompleteSession); + foreach(FullTOC.TrackDataDescriptor descriptor in toc.TrackDescriptors) { tocMs.WriteByte(descriptor.SessionNumber); @@ -345,22 +370,26 @@ namespace DiscImageChef.DiscImages string dataFile = Path.GetFileNameWithoutExtension(imageFilter.GetBasePath()) + ".img"; string subFile = Path.GetFileNameWithoutExtension(imageFilter.GetBasePath()) + ".sub"; - FiltersList filtersList = new FiltersList(); + var filtersList = new FiltersList(); dataFilter = filtersList.GetFilter(dataFile); - if(dataFilter == null) throw new Exception("Cannot open data file"); + if(dataFilter == null) + throw new Exception("Cannot open data file"); filtersList = new FiltersList(); subFilter = filtersList.GetFilter(subFile); - int curSessionNo = 0; - Track currentTrack = new Track(); - bool firstTrackInSession = true; + int curSessionNo = 0; + var currentTrack = new Track(); + bool firstTrackInSession = true; Tracks = new List(); ulong leadOutStart = 0; dataStream = dataFilter.GetDataForkStream(); - if(subFilter != null) subStream = subFilter.GetDataForkStream(); + + if(subFilter != null) + subStream = subFilter.GetDataForkStream(); + trackFlags = new Dictionary(); foreach(FullTOC.TrackDataDescriptor descriptor in entries) @@ -368,6 +397,7 @@ namespace DiscImageChef.DiscImages if(descriptor.SessionNumber > curSessionNo) { curSessionNo = descriptor.SessionNumber; + if(!firstTrackInSession) { currentTrack.TrackEndSector = leadOutStart - 1; @@ -386,40 +416,45 @@ namespace DiscImageChef.DiscImages case 0xA0: byte discType = descriptor.PSEC; DicConsole.DebugWriteLine("CloneCD plugin", "Disc Type: {0}", discType); + break; case 0xA2: leadOutStart = GetLba(descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME); + break; default: - if(descriptor.POINT >= 0x01 && descriptor.POINT <= 0x63) + if(descriptor.POINT >= 0x01 && + descriptor.POINT <= 0x63) { if(!firstTrackInSession) { currentTrack.TrackEndSector = GetLba(descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME) - 1; + Tracks.Add(currentTrack); } - else firstTrackInSession = false; + else + firstTrackInSession = false; currentTrack = new Track { - TrackBytesPerSector = 2352, - TrackFile = dataFilter.GetFilename(), - TrackFileType = scrambled ? "SCRAMBLED" : "BINARY", - TrackFilter = dataFilter, - TrackRawBytesPerSector = 2352, - TrackSequence = descriptor.POINT, + TrackBytesPerSector = 2352, TrackFile = dataFilter.GetFilename(), + TrackFileType = scrambled ? "SCRAMBLED" : "BINARY", + TrackFilter = dataFilter, TrackRawBytesPerSector = 2352, + TrackSequence = descriptor.POINT, TrackStartSector = GetLba(descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME), TrackSession = descriptor.SessionNumber }; + currentTrack.TrackFileOffset = currentTrack.TrackStartSector * 2352; // Need to check exact data type later if((TocControl)(descriptor.CONTROL & 0x0D) == TocControl.DataTrack || (TocControl)(descriptor.CONTROL & 0x0D) == TocControl.DataTrackIncremental) - currentTrack.TrackType = TrackType.Data; - else currentTrack.TrackType = TrackType.Audio; + currentTrack.TrackType = TrackType.Data; + else + currentTrack.TrackType = TrackType.Audio; if(!trackFlags.ContainsKey(descriptor.POINT)) trackFlags.Add(descriptor.POINT, descriptor.CONTROL); @@ -431,7 +466,8 @@ namespace DiscImageChef.DiscImages currentTrack.TrackSubchannelOffset = currentTrack.TrackStartSector * 96; currentTrack.TrackSubchannelType = TrackSubchannelType.Raw; } - else currentTrack.TrackSubchannelType = TrackSubchannelType.None; + else + currentTrack.TrackSubchannelType = TrackSubchannelType.None; if(currentTrack.TrackType == TrackType.Data) { @@ -443,29 +479,40 @@ namespace DiscImageChef.DiscImages if(Sector.SyncMark.SequenceEqual(syncTest)) { - if(scrambled) sectTest = Sector.Scramble(sectTest); + if(scrambled) + sectTest = Sector.Scramble(sectTest); if(sectTest[15] == 1) { currentTrack.TrackBytesPerSector = 2048; currentTrack.TrackType = TrackType.CdMode1; - if(!imageInfo.ReadableSectorTags - .Contains(SectorTagType.CdSectorSync)) + + if(!imageInfo.ReadableSectorTags. + Contains(SectorTagType.CdSectorSync)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); - if(!imageInfo.ReadableSectorTags.Contains(SectorTagType - .CdSectorHeader)) + + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType. + CdSectorHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc) - ) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc); - if(!imageInfo.ReadableSectorTags - .Contains(SectorTagType.CdSectorEccP)) + ) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc); + + if(!imageInfo.ReadableSectorTags. + Contains(SectorTagType.CdSectorEccP)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP); - if(!imageInfo.ReadableSectorTags - .Contains(SectorTagType.CdSectorEccQ)) + + if(!imageInfo.ReadableSectorTags. + Contains(SectorTagType.CdSectorEccQ)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc) - ) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); - if(imageInfo.SectorSize < 2048) imageInfo.SectorSize = 2048; + ) + imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); + + if(imageInfo.SectorSize < 2048) + imageInfo.SectorSize = 2048; } else if(sectTest[15] == 2) { @@ -476,87 +523,108 @@ namespace DiscImageChef.DiscImages Array.Copy(sectTest, 16, subHdr1, 0, 4); Array.Copy(sectTest, 20, subHdr2, 0, 4); - if(subHdr1.SequenceEqual(subHdr2) && !empHdr.SequenceEqual(subHdr1)) + if(subHdr1.SequenceEqual(subHdr2) && + !empHdr.SequenceEqual(subHdr1)) if((subHdr1[2] & 0x20) == 0x20) { currentTrack.TrackBytesPerSector = 2324; currentTrack.TrackType = TrackType.CdMode2Form2; - if(!imageInfo.ReadableSectorTags.Contains(SectorTagType - .CdSectorSync)) - imageInfo.ReadableSectorTags.Add(SectorTagType - .CdSectorSync); - if(!imageInfo.ReadableSectorTags.Contains(SectorTagType - .CdSectorHeader) + + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType. + CdSectorSync)) + imageInfo.ReadableSectorTags.Add(SectorTagType. + CdSectorSync); + + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType. + CdSectorHeader) ) - imageInfo.ReadableSectorTags.Add(SectorTagType - .CdSectorHeader); - if(!imageInfo.ReadableSectorTags.Contains(SectorTagType - .CdSectorSubHeader) + imageInfo.ReadableSectorTags.Add(SectorTagType. + CdSectorHeader); + + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType. + CdSectorSubHeader) ) - imageInfo.ReadableSectorTags.Add(SectorTagType - .CdSectorSubHeader); - if(!imageInfo.ReadableSectorTags.Contains(SectorTagType - .CdSectorEdc)) - imageInfo.ReadableSectorTags.Add(SectorTagType - .CdSectorEdc); - if(imageInfo.SectorSize < 2324) imageInfo.SectorSize = 2324; + imageInfo.ReadableSectorTags.Add(SectorTagType. + CdSectorSubHeader); + + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType. + CdSectorEdc)) + imageInfo.ReadableSectorTags.Add(SectorTagType. + CdSectorEdc); + + if(imageInfo.SectorSize < 2324) + imageInfo.SectorSize = 2324; } else { currentTrack.TrackBytesPerSector = 2048; currentTrack.TrackType = TrackType.CdMode2Form1; - if(!imageInfo.ReadableSectorTags.Contains(SectorTagType - .CdSectorSync)) - imageInfo.ReadableSectorTags.Add(SectorTagType - .CdSectorSync); - if(!imageInfo.ReadableSectorTags.Contains(SectorTagType - .CdSectorHeader) + + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType. + CdSectorSync)) + imageInfo.ReadableSectorTags.Add(SectorTagType. + CdSectorSync); + + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType. + CdSectorHeader) ) - imageInfo.ReadableSectorTags.Add(SectorTagType - .CdSectorHeader); - if(!imageInfo.ReadableSectorTags.Contains(SectorTagType - .CdSectorSubHeader) + imageInfo.ReadableSectorTags.Add(SectorTagType. + CdSectorHeader); + + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType. + CdSectorSubHeader) ) - imageInfo.ReadableSectorTags.Add(SectorTagType - .CdSectorSubHeader); - if(!imageInfo.ReadableSectorTags.Contains(SectorTagType - .CdSectorEcc)) - imageInfo.ReadableSectorTags.Add(SectorTagType - .CdSectorEcc); - if(!imageInfo.ReadableSectorTags.Contains(SectorTagType - .CdSectorEccP)) - imageInfo.ReadableSectorTags.Add(SectorTagType - .CdSectorEccP); - if(!imageInfo.ReadableSectorTags.Contains(SectorTagType - .CdSectorEccQ)) - imageInfo.ReadableSectorTags.Add(SectorTagType - .CdSectorEccQ); - if(!imageInfo.ReadableSectorTags.Contains(SectorTagType - .CdSectorEdc)) - imageInfo.ReadableSectorTags.Add(SectorTagType - .CdSectorEdc); - if(imageInfo.SectorSize < 2048) imageInfo.SectorSize = 2048; + imageInfo.ReadableSectorTags.Add(SectorTagType. + CdSectorSubHeader); + + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType. + CdSectorEcc)) + imageInfo.ReadableSectorTags.Add(SectorTagType. + CdSectorEcc); + + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType. + CdSectorEccP)) + imageInfo.ReadableSectorTags.Add(SectorTagType. + CdSectorEccP); + + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType. + CdSectorEccQ)) + imageInfo.ReadableSectorTags.Add(SectorTagType. + CdSectorEccQ); + + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType. + CdSectorEdc)) + imageInfo.ReadableSectorTags.Add(SectorTagType. + CdSectorEdc); + + if(imageInfo.SectorSize < 2048) + imageInfo.SectorSize = 2048; } else { currentTrack.TrackBytesPerSector = 2336; currentTrack.TrackType = TrackType.CdMode2Formless; - if(!imageInfo.ReadableSectorTags.Contains(SectorTagType - .CdSectorSync)) - imageInfo.ReadableSectorTags - .Add(SectorTagType.CdSectorSync); - if(!imageInfo.ReadableSectorTags.Contains(SectorTagType - .CdSectorHeader)) - imageInfo.ReadableSectorTags.Add(SectorTagType - .CdSectorHeader); - if(imageInfo.SectorSize < 2336) imageInfo.SectorSize = 2336; + + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType. + CdSectorSync)) + imageInfo.ReadableSectorTags. + Add(SectorTagType.CdSectorSync); + + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType. + CdSectorHeader)) + imageInfo.ReadableSectorTags.Add(SectorTagType. + CdSectorHeader); + + if(imageInfo.SectorSize < 2336) + imageInfo.SectorSize = 2336; } } } } else { - if(imageInfo.SectorSize < 2352) imageInfo.SectorSize = 2352; + if(imageInfo.SectorSize < 2352) + imageInfo.SectorSize = 2352; } } @@ -589,6 +657,7 @@ namespace DiscImageChef.DiscImages uint id = (uint)((descriptor.Min << 16) + (descriptor.Sec << 8) + descriptor.Frame); DicConsole.DebugWriteLine("CloneCD plugin", "Disc ID: {0:X6}", id & 0x00FFFFFF); imageInfo.MediaSerialNumber = $"{id & 0x00FFFFFF:X6}"; + break; } } @@ -600,16 +669,19 @@ namespace DiscImageChef.DiscImages Tracks.Add(currentTrack); } - if(subFilter != null && !imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel)) + if(subFilter != null && + !imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel); imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackFlags); Sessions = new List(); - Session currentSession = new Session + + var currentSession = new Session { EndTrack = uint.MinValue, StartTrack = uint.MaxValue, SessionSequence = 1 }; + Partitions = new List(); offsetmap = new Dictionary(); @@ -632,26 +704,23 @@ namespace DiscImageChef.DiscImages else { Sessions.Add(currentSession); + currentSession = new Session { - EndTrack = uint.MinValue, - StartTrack = uint.MaxValue, - SessionSequence = track.TrackSession + EndTrack = uint.MinValue, StartTrack = uint.MaxValue, SessionSequence = track.TrackSession }; } - Partition partition = new Partition + var partition = new Partition { Description = track.TrackDescription, - Size = - (track.TrackEndSector - track.TrackStartSector + 1) * - (ulong)track.TrackRawBytesPerSector, - Length = track.TrackEndSector - track.TrackStartSector + 1, - Sequence = track.TrackSequence, - Offset = track.TrackFileOffset, - Start = track.TrackStartSector, - Type = track.TrackType.ToString() + Size = ((track.TrackEndSector - track.TrackStartSector) + 1) * + (ulong)track.TrackRawBytesPerSector, + Length = (track.TrackEndSector - track.TrackStartSector) + 1, Sequence = track.TrackSequence, + Offset = track.TrackFileOffset, Start = track.TrackStartSector, + Type = track.TrackType.ToString() }; + imageInfo.Sectors += partition.Length; Partitions.Add(partition); offsetmap.Add(track.TrackSequence, track.TrackStartSector); @@ -683,6 +752,7 @@ namespace DiscImageChef.DiscImages case TrackType.CdMode2Form2: case TrackType.CdMode2Formless: mode2 = true; + break; } } @@ -690,11 +760,20 @@ namespace DiscImageChef.DiscImages // TODO: Check format 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; + 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; imageInfo.Application = "CloneCD"; imageInfo.ImageSize = (ulong)imageFilter.GetDataForkLength(); @@ -707,8 +786,9 @@ namespace DiscImageChef.DiscImages catch(Exception ex) { DicConsole.ErrorWriteLine("Exception trying to identify image file {0}", imageFilter.GetFilename()); - DicConsole.ErrorWriteLine("Exception: {0}", ex.Message); - DicConsole.ErrorWriteLine("Stack trace: {0}", ex.StackTrace); + DicConsole.ErrorWriteLine("Exception: {0}", ex.Message); + DicConsole.ErrorWriteLine("Stack trace: {0}", ex.StackTrace); + return false; } } @@ -717,10 +797,15 @@ namespace DiscImageChef.DiscImages { 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; + if(cdtext != null && + cdtext.Length > 0) + return cdtext; throw new FeatureNotPresentImageException("Image does not contain CD-TEXT information."); } @@ -740,12 +825,10 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectors(ulong sectorAddress, uint length) { - foreach(KeyValuePair kvp in from kvp in offsetmap - where sectorAddress >= kvp.Value - from track in Tracks - where track.TrackSequence == kvp.Key - where sectorAddress <= track.TrackEndSector - select kvp) + foreach(KeyValuePair kvp in from kvp in offsetmap where sectorAddress >= kvp.Value + from track in Tracks where track.TrackSequence == kvp.Key + where sectorAddress <= + track.TrackEndSector select kvp) return ReadSectors(sectorAddress - kvp.Value, length, kvp.Key); throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found"); @@ -753,12 +836,10 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) { - foreach(KeyValuePair kvp in from kvp in offsetmap - where sectorAddress >= kvp.Value - from track in Tracks - where track.TrackSequence == kvp.Key - where sectorAddress <= track.TrackEndSector - select kvp) + foreach(KeyValuePair kvp in from kvp in offsetmap where sectorAddress >= kvp.Value + from track in Tracks where track.TrackSequence == kvp.Key + where sectorAddress <= + track.TrackEndSector select kvp) return ReadSectorsTag(sectorAddress - kvp.Value, length, kvp.Key, tag); throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found"); @@ -766,27 +847,32 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectors(ulong sectorAddress, uint length, uint track) { - Track dicTrack = new Track {TrackSequence = 0}; + var dicTrack = new Track + { + TrackSequence = 0 + }; foreach(Track linqTrack in Tracks.Where(linqTrack => linqTrack.TrackSequence == track)) { dicTrack = linqTrack; + break; } if(dicTrack.TrackSequence == 0) throw new ArgumentOutOfRangeException(nameof(track), "Track does not exist in disc image"); - if(length + sectorAddress - 1 > dicTrack.TrackEndSector) + if((length + sectorAddress) - 1 > dicTrack.TrackEndSector) throw new ArgumentOutOfRangeException(nameof(length), - string - .Format("Requested more sectors ({0} {2}) than present in track ({1}), won't cross tracks", + string. + Format("Requested more sectors ({0} {2}) than present in track ({1}), won't cross tracks", length + sectorAddress, dicTrack.TrackEndSector, sectorAddress)); uint sectorOffset; uint sectorSize; uint sectorSkip; + bool mode2 = false; switch(dicTrack.TrackType) { @@ -795,6 +881,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 2352; sectorSkip = 0; + break; } case TrackType.CdMode1: @@ -802,27 +889,18 @@ namespace DiscImageChef.DiscImages sectorOffset = 16; sectorSize = 2048; sectorSkip = 288; + break; } case TrackType.CdMode2Formless: - { - sectorOffset = 16; - sectorSize = 2336; - sectorSkip = 0; - break; - } case TrackType.CdMode2Form1: - { - sectorOffset = 24; - sectorSize = 2048; - sectorSkip = 280; - break; - } case TrackType.CdMode2Form2: { - sectorOffset = 24; - sectorSize = 2324; - sectorSkip = 4; + mode2 = true; + sectorOffset = 0; + sectorSize = 2352; + sectorSkip = 0; + break; } default: throw new FeatureSupportedButNotImplementedImageException("Unsupported track type"); @@ -830,8 +908,27 @@ namespace DiscImageChef.DiscImages byte[] buffer = new byte[sectorSize * length]; - dataStream.Seek((long)(dicTrack.TrackFileOffset + sectorAddress * 2352), SeekOrigin.Begin); - if(sectorOffset == 0 && sectorSkip == 0) dataStream.Read(buffer, 0, buffer.Length); + dataStream.Seek((long)(dicTrack.TrackFileOffset + (sectorAddress * 2352)), SeekOrigin.Begin); + + if(mode2) + { + var mode2Ms = new MemoryStream((int)(sectorSize * length)); + + dataStream.Read(buffer, 0, buffer.Length); + + for(int i = 0; i < length; i++) + { + byte[] sector = new byte[sectorSize]; + Array.Copy(buffer, sectorSize * i, sector, 0, sectorSize); + sector = Sector.GetUserDataFromMode2(sector); + mode2Ms.Write(sector, 0, sector.Length); + } + + buffer = mode2Ms.ToArray(); + } + else if(sectorOffset == 0 && + sectorSkip == 0) + dataStream.Read(buffer, 0, buffer.Length); else for(int i = 0; i < length; i++) { @@ -847,18 +944,22 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) { - Track dicTrack = new Track {TrackSequence = 0}; + var dicTrack = new Track + { + TrackSequence = 0 + }; foreach(Track linqTrack in Tracks.Where(linqTrack => linqTrack.TrackSequence == track)) { dicTrack = linqTrack; + break; } if(dicTrack.TrackSequence == 0) throw new ArgumentOutOfRangeException(nameof(track), "Track does not exist in disc image"); - if(length + sectorAddress - 1 > dicTrack.TrackEndSector) + if((length + sectorAddress) - 1 > dicTrack.TrackEndSector) throw new ArgumentOutOfRangeException(nameof(length), $"Requested more sectors ({length + sectorAddress}) than present in track ({dicTrack.TrackEndSector}), won't cross tracks"); @@ -877,13 +978,15 @@ namespace DiscImageChef.DiscImages case SectorTagType.CdSectorSubHeader: case SectorTagType.CdSectorSync: break; case SectorTagType.CdTrackFlags: - return !trackFlags.TryGetValue((byte)dicTrack.TrackSequence, out byte flags) - ? new[] {flags} - : new byte[1]; + 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); + subStream.Seek((long)(dicTrack.TrackSubchannelOffset + (sectorAddress * 96)), SeekOrigin.Begin); subStream.Read(buffer, 0, buffer.Length); + return buffer; default: throw new ArgumentException("Unsupported tag requested", nameof(tag)); } @@ -902,6 +1005,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 12; sectorSkip = 2340; + break; } case SectorTagType.CdSectorHeader: @@ -909,6 +1013,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 12; sectorSize = 4; sectorSkip = 2336; + break; } case SectorTagType.CdSectorSubHeader: @@ -918,6 +1023,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2076; sectorSize = 276; sectorSkip = 0; + break; } case SectorTagType.CdSectorEccP: @@ -925,6 +1031,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2076; sectorSize = 172; sectorSkip = 104; + break; } case SectorTagType.CdSectorEccQ: @@ -932,6 +1039,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2248; sectorSize = 104; sectorSkip = 0; + break; } case SectorTagType.CdSectorEdc: @@ -939,6 +1047,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2064; sectorSize = 4; sectorSkip = 284; + break; } default: throw new ArgumentException("Unsupported tag requested", nameof(tag)); @@ -960,6 +1069,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 8; sectorSkip = 2328; + break; } case SectorTagType.CdSectorEdc: @@ -967,6 +1077,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2332; sectorSize = 4; sectorSkip = 0; + break; } default: throw new ArgumentException("Unsupported tag requested", nameof(tag)); @@ -982,6 +1093,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 12; sectorSkip = 2340; + break; } case SectorTagType.CdSectorHeader: @@ -989,6 +1101,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 12; sectorSize = 4; sectorSkip = 2336; + break; } case SectorTagType.CdSectorSubHeader: @@ -996,6 +1109,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 16; sectorSize = 8; sectorSkip = 2328; + break; } case SectorTagType.CdSectorEcc: @@ -1003,6 +1117,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2076; sectorSize = 276; sectorSkip = 0; + break; } case SectorTagType.CdSectorEccP: @@ -1010,6 +1125,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2076; sectorSize = 172; sectorSkip = 104; + break; } case SectorTagType.CdSectorEccQ: @@ -1017,6 +1133,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2248; sectorSize = 104; sectorSkip = 0; + break; } case SectorTagType.CdSectorEdc: @@ -1024,6 +1141,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2072; sectorSize = 4; sectorSkip = 276; + break; } default: throw new ArgumentException("Unsupported tag requested", nameof(tag)); @@ -1038,6 +1156,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 12; sectorSkip = 2340; + break; } case SectorTagType.CdSectorHeader: @@ -1045,6 +1164,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 12; sectorSize = 4; sectorSkip = 2336; + break; } case SectorTagType.CdSectorSubHeader: @@ -1052,6 +1172,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 16; sectorSize = 8; sectorSkip = 2328; + break; } case SectorTagType.CdSectorEdc: @@ -1059,21 +1180,27 @@ namespace DiscImageChef.DiscImages sectorOffset = 2348; sectorSize = 4; sectorSkip = 0; + break; } default: throw new ArgumentException("Unsupported tag requested", nameof(tag)); } 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]; - dataStream.Seek((long)(dicTrack.TrackFileOffset + sectorAddress * 2352), SeekOrigin.Begin); - if(sectorOffset == 0 && sectorSkip == 0) dataStream.Read(buffer, 0, buffer.Length); + dataStream.Seek((long)(dicTrack.TrackFileOffset + (sectorAddress * 2352)), SeekOrigin.Begin); + + if(sectorOffset == 0 && + sectorSkip == 0) + dataStream.Read(buffer, 0, buffer.Length); else for(int i = 0; i < length; i++) { @@ -1093,12 +1220,10 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectorsLong(ulong sectorAddress, uint length) { - foreach(KeyValuePair kvp in from kvp in offsetmap - where sectorAddress >= kvp.Value - from track in Tracks - where track.TrackSequence == kvp.Key - where sectorAddress - kvp.Value < - track.TrackEndSector - track.TrackStartSector + 1 + foreach(KeyValuePair kvp in from kvp in offsetmap where sectorAddress >= kvp.Value + from track in Tracks where track.TrackSequence == kvp.Key + where sectorAddress - kvp.Value < + (track.TrackEndSector - track.TrackStartSector) + 1 select kvp) return ReadSectorsLong(sectorAddress - kvp.Value, length, kvp.Key); @@ -1107,24 +1232,28 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) { - Track dicTrack = new Track {TrackSequence = 0}; + var dicTrack = new Track + { + TrackSequence = 0 + }; foreach(Track linqTrack in Tracks.Where(linqTrack => linqTrack.TrackSequence == track)) { dicTrack = linqTrack; + break; } if(dicTrack.TrackSequence == 0) throw new ArgumentOutOfRangeException(nameof(track), "Track does not exist in disc image"); - if(length + sectorAddress - 1 > dicTrack.TrackEndSector) + if((length + sectorAddress) - 1 > dicTrack.TrackEndSector) throw new ArgumentOutOfRangeException(nameof(length), $"Requested more sectors ({length + sectorAddress}) than present in track ({dicTrack.TrackEndSector}), won't cross tracks"); byte[] buffer = new byte[2352 * length]; - dataStream.Seek((long)(dicTrack.TrackFileOffset + sectorAddress * 2352), SeekOrigin.Begin); + dataStream.Seek((long)(dicTrack.TrackFileOffset + (sectorAddress * 2352)), SeekOrigin.Begin); dataStream.Read(buffer, 0, buffer.Length); return buffer; @@ -1132,14 +1261,13 @@ namespace DiscImageChef.DiscImages public List 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 GetSessionTracks(ushort session) - { - return Tracks.Where(track => track.TrackSession == session).ToList(); - } + public List GetSessionTracks(ushort session) => + Tracks.Where(track => track.TrackSession == session).ToList(); } } \ No newline at end of file diff --git a/DiscImageChef.DiscImages/DiscJuggler/Read.cs b/DiscImageChef.DiscImages/DiscJuggler/Read.cs index 65cba3e5d..5658837ff 100644 --- a/DiscImageChef.DiscImages/DiscJuggler/Read.cs +++ b/DiscImageChef.DiscImages/DiscJuggler/Read.cs @@ -41,6 +41,8 @@ using DiscImageChef.CommonTypes.Exceptions; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Structs; using DiscImageChef.Console; +using DiscImageChef.Decoders.CD; +using Session = DiscImageChef.CommonTypes.Structs.Session; namespace DiscImageChef.DiscImages { @@ -55,14 +57,17 @@ namespace DiscImageChef.DiscImages imageStream.Read(dscLenB, 0, 4); int dscLen = BitConverter.ToInt32(dscLenB, 0); - if(dscLen >= imageStream.Length) return false; + if(dscLen >= imageStream.Length) + return false; byte[] descriptor = new byte[dscLen]; imageStream.Seek(-dscLen, SeekOrigin.End); imageStream.Read(descriptor, 0, dscLen); // Sessions - if(descriptor[0] > 99 || descriptor[0] == 0) return false; + if(descriptor[0] > 99 || + descriptor[0] == 0) + return false; int position = 1; @@ -85,22 +90,32 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("DiscJuggler plugin", "s = {0}", s); // Seems all sessions start with this data - if(descriptor[position + 0] != 0x00 || descriptor[position + 2] != 0x00 || - descriptor[position + 3] != 0x00 || descriptor[position + 4] != 0x00 || - descriptor[position + 5] != 0x00 || descriptor[position + 6] != 0x00 || - descriptor[position + 7] != 0x00 || descriptor[position + 8] != 0x00 || - descriptor[position + 9] != 0x01 || descriptor[position + 10] != 0x00 || - descriptor[position + 11] != 0x00 || descriptor[position + 12] != 0x00 || - descriptor[position + 13] != 0xFF || descriptor[position + 14] != 0xFF) return false; + if(descriptor[position + 0] != 0x00 || + descriptor[position + 2] != 0x00 || + descriptor[position + 3] != 0x00 || + descriptor[position + 4] != 0x00 || + descriptor[position + 5] != 0x00 || + descriptor[position + 6] != 0x00 || + descriptor[position + 7] != 0x00 || + descriptor[position + 8] != 0x00 || + descriptor[position + 9] != 0x01 || + descriptor[position + 10] != 0x00 || + descriptor[position + 11] != 0x00 || + descriptor[position + 12] != 0x00 || + descriptor[position + 13] != 0xFF || + descriptor[position + 14] != 0xFF) + return false; // Too many tracks - if(descriptor[position + 1] > 99) return false; + if(descriptor[position + 1] > 99) + return false; byte maxT = descriptor[position + 1]; DicConsole.DebugWriteLine("DiscJuggler plugin", "maxT = {0}", maxT); sessionSequence++; - Session session = new Session + + var session = new Session { SessionSequence = sessionSequence, EndTrack = uint.MinValue, StartTrack = uint.MaxValue }; @@ -112,7 +127,7 @@ namespace DiscImageChef.DiscImages for(byte t = 0; t < maxT; t++) { DicConsole.DebugWriteLine("DiscJuggler plugin", "t = {0}", t); - Track track = new Track(); + var track = new Track(); // Skip unknown position += 16; @@ -136,6 +151,7 @@ namespace DiscImageChef.DiscImages ushort maxI = BitConverter.ToUInt16(descriptor, position); position += 2; DicConsole.DebugWriteLine("DiscJuggler plugin", "\tmaxI = {0}", maxI); + for(ushort i = 0; i < maxI; i++) { uint index = BitConverter.ToUInt32(descriptor, position); @@ -148,6 +164,7 @@ namespace DiscImageChef.DiscImages uint maxC = BitConverter.ToUInt32(descriptor, position); position += 4; DicConsole.DebugWriteLine("DiscJuggler plugin", "\tmaxC = {0}", maxC); + for(uint c = 0; c < maxC; c++) { for(int cb = 0; cb < 18; cb++) @@ -155,15 +172,20 @@ namespace DiscImageChef.DiscImages int bLen = descriptor[position]; position++; DicConsole.DebugWriteLine("DiscJuggler plugin", "\tc[{1}][{2}].Length = {0}", bLen, c, cb); - if(bLen <= 0) continue; + + if(bLen <= 0) + continue; byte[] textBlk = new byte[bLen]; Array.Copy(descriptor, position, textBlk, 0, bLen); position += bLen; + // Track title - if(cb != 10) continue; + if(cb != 10) + continue; track.TrackDescription = Encoding.Default.GetString(textBlk, 0, bLen); + DicConsole.DebugWriteLine("DiscJuggler plugin", "\tTrack title = {0}", track.TrackDescription); } @@ -182,15 +204,17 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("DiscJuggler plugin", "\tsession = {0}", session.SessionSequence); position += 4; track.TrackSequence = BitConverter.ToUInt32(descriptor, position) + lastSessionTrack + 1; + DicConsole.DebugWriteLine("DiscJuggler plugin", "\ttrack = {1} + {2} + 1 = {0}", track.TrackSequence, BitConverter.ToUInt32(descriptor, position), lastSessionTrack); + position += 4; track.TrackStartSector = BitConverter.ToUInt32(descriptor, position); DicConsole.DebugWriteLine("DiscJuggler plugin", "\ttrackStart = {0}", track.TrackStartSector); position += 4; uint trackLen = BitConverter.ToUInt32(descriptor, position); - track.TrackEndSector = track.TrackStartSector + trackLen - 1; + track.TrackEndSector = (track.TrackStartSector + trackLen) - 1; DicConsole.DebugWriteLine("DiscJuggler plugin", "\ttrackEnd = {0}", track.TrackEndSector); position += 4; @@ -254,51 +278,73 @@ namespace DiscImageChef.DiscImages { // Audio case 0: - if(imageInfo.SectorSize < 2352) imageInfo.SectorSize = 2352; + if(imageInfo.SectorSize < 2352) + imageInfo.SectorSize = 2352; + track.TrackType = TrackType.Audio; track.TrackBytesPerSector = 2352; track.TrackRawBytesPerSector = 2352; + switch(readMode) { case 2: - if(firstTrack) currentOffset += 150 * (ulong)track.TrackRawBytesPerSector; + if(firstTrack) + currentOffset += 150 * (ulong)track.TrackRawBytesPerSector; + track.TrackFileOffset = currentOffset; currentOffset += trackLen * (ulong)track.TrackRawBytesPerSector; + break; case 3: - if(firstTrack) currentOffset += 150 * (ulong)(track.TrackRawBytesPerSector + 16); + if(firstTrack) + currentOffset += 150 * (ulong)(track.TrackRawBytesPerSector + 16); + track.TrackFileOffset = currentOffset; track.TrackSubchannelFile = track.TrackFile; track.TrackSubchannelOffset = currentOffset; track.TrackSubchannelType = TrackSubchannelType.Q16Interleaved; + currentOffset += trackLen * (ulong)(track.TrackRawBytesPerSector + 16); + break; case 4: - if(firstTrack) currentOffset += 150 * (ulong)(track.TrackRawBytesPerSector + 96); + if(firstTrack) + currentOffset += 150 * (ulong)(track.TrackRawBytesPerSector + 96); + track.TrackFileOffset = currentOffset; track.TrackSubchannelFile = track.TrackFile; track.TrackSubchannelOffset = currentOffset; track.TrackSubchannelType = TrackSubchannelType.RawInterleaved; + currentOffset += trackLen * (ulong)(track.TrackRawBytesPerSector + 96); + break; default: throw new ImageNotSupportedException($"Unknown read mode {readMode}"); } break; + // Mode 1 or DVD case 1: - if(imageInfo.SectorSize < 2048) imageInfo.SectorSize = 2048; + if(imageInfo.SectorSize < 2048) + imageInfo.SectorSize = 2048; + track.TrackType = TrackType.CdMode1; track.TrackBytesPerSector = 2048; + switch(readMode) { case 0: track.TrackRawBytesPerSector = 2048; - if(firstTrack) currentOffset += 150 * (ulong)track.TrackRawBytesPerSector; + + if(firstTrack) + currentOffset += 150 * (ulong)track.TrackRawBytesPerSector; + track.TrackFileOffset = currentOffset; currentOffset += trackLen * (ulong)track.TrackRawBytesPerSector; + break; case 1: throw @@ -306,72 +352,105 @@ namespace DiscImageChef.DiscImages case 2: track.TrackRawBytesPerSector = 2352; currentOffset += trackLen * (ulong)track.TrackRawBytesPerSector; + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); + break; case 3: track.TrackRawBytesPerSector = 2352; - if(firstTrack) currentOffset += 150 * (ulong)(track.TrackRawBytesPerSector + 16); + + if(firstTrack) + currentOffset += 150 * (ulong)(track.TrackRawBytesPerSector + 16); + track.TrackFileOffset = currentOffset; track.TrackSubchannelFile = track.TrackFile; track.TrackSubchannelOffset = currentOffset; track.TrackSubchannelType = TrackSubchannelType.Q16Interleaved; + currentOffset += trackLen * (ulong)(track.TrackRawBytesPerSector + 16); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); + break; case 4: track.TrackRawBytesPerSector = 2352; - if(firstTrack) currentOffset += 150 * (ulong)(track.TrackRawBytesPerSector + 96); + + if(firstTrack) + currentOffset += 150 * (ulong)(track.TrackRawBytesPerSector + 96); + track.TrackFileOffset = currentOffset; track.TrackSubchannelFile = track.TrackFile; track.TrackSubchannelOffset = currentOffset; track.TrackSubchannelType = TrackSubchannelType.RawInterleaved; + currentOffset += trackLen * (ulong)(track.TrackRawBytesPerSector + 96); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); + break; default: throw new ImageNotSupportedException($"Unknown read mode {readMode}"); } break; + // Mode 2 case 2: - if(imageInfo.SectorSize < 2336) imageInfo.SectorSize = 2336; + if(imageInfo.SectorSize < 2336) + imageInfo.SectorSize = 2336; + track.TrackType = TrackType.CdMode2Formless; track.TrackBytesPerSector = 2336; + switch(readMode) { case 0: @@ -379,45 +458,66 @@ namespace DiscImageChef.DiscImages new ImageNotSupportedException($"Invalid read mode {readMode} for this track"); case 1: track.TrackRawBytesPerSector = 2336; - if(firstTrack) currentOffset += 150 * (ulong)track.TrackRawBytesPerSector; + + if(firstTrack) + currentOffset += 150 * (ulong)track.TrackRawBytesPerSector; + track.TrackFileOffset = currentOffset; currentOffset += trackLen * (ulong)track.TrackRawBytesPerSector; + break; case 2: track.TrackRawBytesPerSector = 2352; currentOffset += trackLen * (ulong)track.TrackRawBytesPerSector; + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + break; case 3: track.TrackRawBytesPerSector = 2352; - if(firstTrack) currentOffset += 150 * (ulong)(track.TrackRawBytesPerSector + 16); + + if(firstTrack) + currentOffset += 150 * (ulong)(track.TrackRawBytesPerSector + 16); + track.TrackFileOffset = currentOffset; track.TrackSubchannelFile = track.TrackFile; track.TrackSubchannelOffset = currentOffset; track.TrackSubchannelType = TrackSubchannelType.Q16Interleaved; + currentOffset += trackLen * (ulong)(track.TrackRawBytesPerSector + 16); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + break; case 4: track.TrackRawBytesPerSector = 2352; - if(firstTrack) currentOffset += 150 * (ulong)(track.TrackRawBytesPerSector + 96); + + if(firstTrack) + currentOffset += 150 * (ulong)(track.TrackRawBytesPerSector + 96); + track.TrackFileOffset = currentOffset; track.TrackSubchannelFile = track.TrackFile; track.TrackSubchannelOffset = currentOffset; track.TrackSubchannelType = TrackSubchannelType.RawInterleaved; + currentOffset += trackLen * (ulong)(track.TrackRawBytesPerSector + 96); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + break; default: throw new ImageNotSupportedException($"Unknown read mode {readMode}"); } @@ -428,24 +528,24 @@ namespace DiscImageChef.DiscImages track.TrackFile = imageFilter.GetFilename(); track.TrackFilter = imageFilter; + if(track.TrackSubchannelType != TrackSubchannelType.None) { track.TrackSubchannelFile = imageFilter.GetFilename(); track.TrackSubchannelFilter = imageFilter; + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel); } - Partition partition = new Partition + var partition = new Partition { - Description = track.TrackDescription, - Size = (ulong)(trackLen * track.TrackBytesPerSector), - Length = trackLen, - Sequence = track.TrackSequence, + Description = track.TrackDescription, Size = (ulong)(trackLen * track.TrackBytesPerSector), + Length = trackLen, Sequence = track.TrackSequence, Offset = track.TrackFileOffset, - Start = track.TrackStartSector, - Type = track.TrackType.ToString() + Start = track.TrackStartSector, Type = track.TrackType.ToString() }; + imageInfo.Sectors += partition.Length; Partitions.Add(partition); offsetmap.Add(track.TrackSequence, track.TrackStartSector); @@ -454,14 +554,16 @@ namespace DiscImageChef.DiscImages addedATrack = true; } - if(!addedATrack) continue; + if(!addedATrack) + continue; lastSessionTrack = session.EndTrack; Sessions.Add(session); - DicConsole.DebugWriteLine("DiscJuggler plugin", "session.StartTrack = {0}", session.StartTrack); + DicConsole.DebugWriteLine("DiscJuggler plugin", "session.StartTrack = {0}", session.StartTrack); DicConsole.DebugWriteLine("DiscJuggler plugin", "session.StartSector = {0}", session.StartSector); - DicConsole.DebugWriteLine("DiscJuggler plugin", "session.EndTrack = {0}", session.EndTrack); - DicConsole.DebugWriteLine("DiscJuggler plugin", "session.EndSector = {0}", session.EndSector); + DicConsole.DebugWriteLine("DiscJuggler plugin", "session.EndTrack = {0}", session.EndTrack); + DicConsole.DebugWriteLine("DiscJuggler plugin", "session.EndSector = {0}", session.EndSector); + DicConsole.DebugWriteLine("DiscJuggler plugin", "session.SessionSequence = {0}", session.SessionSequence); } @@ -509,6 +611,7 @@ namespace DiscImageChef.DiscImages uint cdtextLen = BitConverter.ToUInt32(descriptor, position); DicConsole.DebugWriteLine("DiscJuggler plugin", "cdtextLen = {0}", cdtextLen); position += 4; + if(cdtextLen > 0) { cdtext = new byte[cdtextLen]; @@ -550,15 +653,25 @@ namespace DiscImageChef.DiscImages case TrackType.CdMode2Form2: case TrackType.CdMode2Formless: mode2 = true; + break; } } - 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; + 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; } imageInfo.Application = "DiscJuggler"; @@ -576,7 +689,9 @@ namespace DiscImageChef.DiscImages { case MediaTagType.CD_TEXT: { - if(cdtext != null && cdtext.Length > 0) return cdtext; + if(cdtext != null && + cdtext.Length > 0) + return cdtext; throw new FeatureNotPresentImageException("Image does not contain CD-TEXT information."); } @@ -596,12 +711,10 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectors(ulong sectorAddress, uint length) { - foreach(KeyValuePair kvp in from kvp in offsetmap - where sectorAddress >= kvp.Value - from track in Tracks - where track.TrackSequence == kvp.Key - where sectorAddress < track.TrackEndSector - select kvp) + foreach(KeyValuePair kvp in from kvp in offsetmap where sectorAddress >= kvp.Value + from track in Tracks where track.TrackSequence == kvp.Key + where sectorAddress < + track.TrackEndSector select kvp) return ReadSectors(sectorAddress - kvp.Value, length, kvp.Key); throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found"); @@ -609,11 +722,11 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) { - foreach(KeyValuePair kvp in offsetmap - .Where(kvp => sectorAddress >= kvp.Value) - .Where(kvp => Tracks - .Where(track => track.TrackSequence == kvp.Key) - .Any(track => sectorAddress < + foreach(KeyValuePair kvp in offsetmap. + Where(kvp => sectorAddress >= kvp.Value). + Where(kvp => Tracks. + Where(track => track.TrackSequence == kvp.Key). + Any(track => sectorAddress < track.TrackEndSector))) return ReadSectorsTag(sectorAddress - kvp.Value, length, kvp.Key, tag); @@ -622,11 +735,15 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectors(ulong sectorAddress, uint length, uint track) { - Track dicTrack = new Track {TrackSequence = 0}; + var dicTrack = new Track + { + TrackSequence = 0 + }; foreach(Track linqTrack in Tracks.Where(linqTrack => linqTrack.TrackSequence == track)) { dicTrack = linqTrack; + break; } @@ -640,6 +757,7 @@ namespace DiscImageChef.DiscImages uint sectorOffset; uint sectorSize; uint sectorSkip; + bool mode2 = true; switch(dicTrack.TrackType) { @@ -648,6 +766,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 2352; sectorSkip = 0; + break; } case TrackType.CdMode1: @@ -666,18 +785,12 @@ namespace DiscImageChef.DiscImages break; case TrackType.CdMode2Formless: - if(dicTrack.TrackRawBytesPerSector == 2352) - { - sectorOffset = 16; - sectorSize = 2336; - sectorSkip = 0; - } - else - { - sectorOffset = 0; - sectorSize = 2336; - sectorSkip = 0; - } + { + mode2 = true; + sectorOffset = 0; + sectorSize = (uint)dicTrack.TrackRawBytesPerSector; + sectorSkip = 0; + } break; default: throw new FeatureSupportedButNotImplementedImageException("Unsupported track type"); @@ -687,21 +800,44 @@ namespace DiscImageChef.DiscImages { case TrackSubchannelType.None: sectorSkip += 0; + break; case TrackSubchannelType.Q16Interleaved: sectorSkip += 16; + break; case TrackSubchannelType.PackedInterleaved: sectorSkip += 96; + break; default: throw new FeatureSupportedButNotImplementedImageException("Unsupported subchannel type"); } byte[] buffer = new byte[sectorSize * length]; - imageStream.Seek((long)(dicTrack.TrackFileOffset + sectorAddress * (ulong)dicTrack.TrackRawBytesPerSector), - SeekOrigin.Begin); - if(sectorOffset == 0 && sectorSkip == 0) imageStream.Read(buffer, 0, buffer.Length); + imageStream. + Seek((long)(dicTrack.TrackFileOffset + (sectorAddress * (ulong)dicTrack.TrackRawBytesPerSector)), + SeekOrigin.Begin); + + if(mode2) + { + var mode2Ms = new MemoryStream((int)(sectorSize * length)); + + imageStream.Read(buffer, 0, buffer.Length); + + for(int i = 0; i < length; i++) + { + byte[] sector = new byte[sectorSize]; + Array.Copy(buffer, sectorSize * i, sector, 0, sectorSize); + sector = Sector.GetUserDataFromMode2(sector); + mode2Ms.Write(sector, 0, sector.Length); + } + + buffer = mode2Ms.ToArray(); + } + else if(sectorOffset == 0 && + sectorSkip == 0) + imageStream.Read(buffer, 0, buffer.Length); else for(int i = 0; i < length; i++) { @@ -717,11 +853,15 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) { - Track dicTrack = new Track {TrackSequence = 0}; + var dicTrack = new Track + { + TrackSequence = 0 + }; foreach(Track linqTrack in Tracks.Where(linqTrack => linqTrack.TrackSequence == track)) { dicTrack = linqTrack; + break; } @@ -746,7 +886,11 @@ namespace DiscImageChef.DiscImages case SectorTagType.CdSectorSubHeader: case SectorTagType.CdSectorSync: break; case SectorTagType.CdTrackFlags: - if(trackFlags.TryGetValue(track, out byte flag)) return new[] {flag}; + if(trackFlags.TryGetValue(track, out byte flag)) + return new[] + { + flag + }; throw new ArgumentException("Unsupported tag requested", nameof(tag)); default: throw new ArgumentException("Unsupported tag requested", nameof(tag)); @@ -769,6 +913,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 12; sectorSkip = 2340; + break; } case SectorTagType.CdSectorHeader: @@ -776,6 +921,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 12; sectorSize = 4; sectorSkip = 2336; + break; } case SectorTagType.CdSectorSubHeader: @@ -785,6 +931,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2076; sectorSize = 276; sectorSkip = 0; + break; } case SectorTagType.CdSectorEccP: @@ -792,6 +939,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2076; sectorSize = 172; sectorSkip = 104; + break; } case SectorTagType.CdSectorEccQ: @@ -799,6 +947,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2248; sectorSize = 104; sectorSkip = 0; + break; } case SectorTagType.CdSectorEdc: @@ -806,6 +955,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2064; sectorSize = 4; sectorSkip = 284; + break; } case SectorTagType.CdSectorSubchannel: @@ -821,6 +971,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2352; sectorSize = 96; sectorSkip = 0; + break; default: throw new ArgumentException("Unsupported tag requested", nameof(tag)); } @@ -844,6 +995,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 8; sectorSkip = 2328; + break; } case SectorTagType.CdSectorEdc: @@ -851,6 +1003,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2332; sectorSize = 4; sectorSkip = 0; + break; } case SectorTagType.CdSectorSubchannel: @@ -866,6 +1019,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2352; sectorSize = 96; sectorSkip = 0; + break; default: throw new ArgumentException("Unsupported tag requested", nameof(tag)); } @@ -889,6 +1043,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2352; sectorSize = 96; sectorSkip = 0; + break; default: throw new ArgumentException("Unsupported tag requested", nameof(tag)); } @@ -902,21 +1057,28 @@ namespace DiscImageChef.DiscImages { case TrackSubchannelType.None: sectorSkip += 0; + break; case TrackSubchannelType.Q16Interleaved: sectorSkip += 16; + break; case TrackSubchannelType.PackedInterleaved: sectorSkip += 96; + break; default: throw new FeatureSupportedButNotImplementedImageException("Unsupported subchannel type"); } byte[] buffer = new byte[sectorSize * length]; - imageStream.Seek((long)(dicTrack.TrackFileOffset + sectorAddress * (ulong)dicTrack.TrackRawBytesPerSector), - SeekOrigin.Begin); - if(sectorOffset == 0 && sectorSkip == 0) imageStream.Read(buffer, 0, buffer.Length); + imageStream. + Seek((long)(dicTrack.TrackFileOffset + (sectorAddress * (ulong)dicTrack.TrackRawBytesPerSector)), + SeekOrigin.Begin); + + if(sectorOffset == 0 && + sectorSkip == 0) + imageStream.Read(buffer, 0, buffer.Length); else for(int i = 0; i < length; i++) { @@ -936,13 +1098,10 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectorsLong(ulong sectorAddress, uint length) { - foreach(KeyValuePair kvp in from kvp in offsetmap - where sectorAddress >= kvp.Value - from track in Tracks - where track.TrackSequence == kvp.Key + foreach(KeyValuePair kvp in from kvp in offsetmap where sectorAddress >= kvp.Value + from track in Tracks where track.TrackSequence == kvp.Key where sectorAddress - kvp.Value < - track.TrackEndSector - track.TrackStartSector - select kvp) + track.TrackEndSector - track.TrackStartSector select kvp) return ReadSectorsLong(sectorAddress - kvp.Value, length, kvp.Key); throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found"); @@ -950,11 +1109,15 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) { - Track dicTrack = new Track {TrackSequence = 0}; + var dicTrack = new Track + { + TrackSequence = 0 + }; foreach(Track linqTrack in Tracks.Where(linqTrack => linqTrack.TrackSequence == track)) { dicTrack = linqTrack; + break; } @@ -972,21 +1135,27 @@ namespace DiscImageChef.DiscImages { case TrackSubchannelType.None: sectorSkip += 0; + break; case TrackSubchannelType.Q16Interleaved: sectorSkip += 16; + break; case TrackSubchannelType.PackedInterleaved: sectorSkip += 96; + break; default: throw new FeatureSupportedButNotImplementedImageException("Unsupported subchannel type"); } byte[] buffer = new byte[sectorSize * length]; - imageStream.Seek((long)(dicTrack.TrackFileOffset + sectorAddress * (ulong)dicTrack.TrackRawBytesPerSector), - SeekOrigin.Begin); - if(sectorSkip == 0) imageStream.Read(buffer, 0, buffer.Length); + imageStream. + Seek((long)(dicTrack.TrackFileOffset + (sectorAddress * (ulong)dicTrack.TrackRawBytesPerSector)), + SeekOrigin.Begin); + + if(sectorSkip == 0) + imageStream.Read(buffer, 0, buffer.Length); else for(int i = 0; i < length; i++) { @@ -1001,14 +1170,13 @@ namespace DiscImageChef.DiscImages public List 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 GetSessionTracks(ushort session) - { - return Tracks.Where(track => track.TrackSession == session).ToList(); - } + public List GetSessionTracks(ushort session) => + Tracks.Where(track => track.TrackSession == session).ToList(); } } \ No newline at end of file diff --git a/DiscImageChef.DiscImages/Nero/Read.cs b/DiscImageChef.DiscImages/Nero/Read.cs index 3cec96c3b..da96cde99 100644 --- a/DiscImageChef.DiscImages/Nero/Read.cs +++ b/DiscImageChef.DiscImages/Nero/Read.cs @@ -41,6 +41,8 @@ using DiscImageChef.CommonTypes.Exceptions; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Structs; using DiscImageChef.Console; +using DiscImageChef.Decoders.CD; +using Session = DiscImageChef.CommonTypes.Structs.Session; namespace DiscImageChef.DiscImages { @@ -51,8 +53,8 @@ namespace DiscImageChef.DiscImages try { imageStream = imageFilter.GetDataForkStream(); - NeroV1Footer footerV1 = new NeroV1Footer(); - NeroV2Footer footerV2 = new NeroV2Footer(); + var footerV1 = new NeroV1Footer(); + var footerV2 = new NeroV2Footer(); imageStream.Seek(-8, SeekOrigin.End); byte[] buffer = new byte[8]; @@ -67,25 +69,34 @@ namespace DiscImageChef.DiscImages footerV2.FirstChunkOffset = BigEndianBitConverter.ToUInt64(buffer, 4); DicConsole.DebugWriteLine("Nero plugin", "imageStream.Length = {0}", imageStream.Length); + DicConsole.DebugWriteLine("Nero plugin", "footerV1.ChunkID = 0x{0:X8} (\"{1}\")", footerV1.ChunkId, Encoding.ASCII.GetString(BigEndianBitConverter.GetBytes(footerV1.ChunkId))); + DicConsole.DebugWriteLine("Nero plugin", "footerV1.FirstChunkOffset = {0}", footerV1.FirstChunkOffset); + DicConsole.DebugWriteLine("Nero plugin", "footerV2.ChunkID = 0x{0:X8} (\"{1}\")", footerV2.ChunkId, Encoding.ASCII.GetString(BigEndianBitConverter.GetBytes(footerV2.ChunkId))); + DicConsole.DebugWriteLine("Nero plugin", "footerV2.FirstChunkOffset = {0}", footerV2.FirstChunkOffset); - if(footerV1.ChunkId == NERO_FOOTER_V1 && footerV1.FirstChunkOffset < (ulong)imageStream.Length) + if(footerV1.ChunkId == NERO_FOOTER_V1 && + footerV1.FirstChunkOffset < (ulong)imageStream.Length) imageNewFormat = false; - else if(footerV2.ChunkId == NERO_FOOTER_V2 && footerV2.FirstChunkOffset < (ulong)imageStream.Length) + else if(footerV2.ChunkId == NERO_FOOTER_V2 && + footerV2.FirstChunkOffset < (ulong)imageStream.Length) imageNewFormat = true; else { DicConsole.DebugWrite("Nero plugin", "Nero version not recognized."); + return false; } - if(imageNewFormat) imageStream.Seek((long)footerV2.FirstChunkOffset, SeekOrigin.Begin); - else imageStream.Seek(footerV1.FirstChunkOffset, SeekOrigin.Begin); + if(imageNewFormat) + imageStream.Seek((long)footerV2.FirstChunkOffset, SeekOrigin.Begin); + else + imageStream.Seek(footerV1.FirstChunkOffset, SeekOrigin.Begin); bool parsing = true; ushort currentsession = 1; @@ -108,6 +119,7 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("Nero plugin", "ChunkID = 0x{0:X8} (\"{1}\")", chunkId, Encoding.ASCII.GetString(BigEndianBitConverter.GetBytes(chunkId))); + DicConsole.DebugWriteLine("Nero plugin", "ChunkLength = {0}", chunkLength); switch(chunkId) @@ -123,9 +135,10 @@ namespace DiscImageChef.DiscImages }; byte[] tmpbuffer = new byte[8]; + for(int i = 0; i < neroCuesheetV1.ChunkSize; i += 8) { - NeroV1CueEntry entry = new NeroV1CueEntry(); + var entry = new NeroV1CueEntry(); imageStream.Read(tmpbuffer, 0, 8); entry.Mode = tmpbuffer[0]; entry.TrackNumber = tmpbuffer[1]; @@ -135,20 +148,27 @@ namespace DiscImageChef.DiscImages entry.Second = tmpbuffer[6]; entry.Frame = tmpbuffer[7]; - DicConsole.DebugWriteLine("Nero plugin", "Cuesheet entry {0}", i / 8 + 1); - DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Mode = {1:X2}", i / 8 + 1, + DicConsole.DebugWriteLine("Nero plugin", "Cuesheet entry {0}", (i / 8) + 1); + + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Mode = {1:X2}", (i / 8) + 1, entry.Mode); + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].TrackNumber = {1:X2}", - i / 8 + 1, entry.TrackNumber); + (i / 8) + 1, entry.TrackNumber); + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].IndexNumber = {1:X2}", - i / 8 + 1, entry.IndexNumber); - DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Dummy = {1:X4}", i / 8 + 1, + (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, + + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Minute = {1:X2}", (i / 8) + 1, entry.Minute); - DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Second = {1:X2}", i / 8 + 1, + + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Second = {1:X2}", (i / 8) + 1, entry.Second); - DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Frame = {1:X2}", i / 8 + 1, + + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Frame = {1:X2}", (i / 8) + 1, entry.Frame); neroCuesheetV1.Entries.Add(entry); @@ -168,9 +188,10 @@ namespace DiscImageChef.DiscImages }; byte[] tmpbuffer = new byte[8]; + for(int i = 0; i < neroCuesheetV2.ChunkSize; i += 8) { - NeroV2CueEntry entry = new NeroV2CueEntry(); + var entry = new NeroV2CueEntry(); imageStream.Read(tmpbuffer, 0, 8); entry.Mode = tmpbuffer[0]; entry.TrackNumber = tmpbuffer[1]; @@ -178,16 +199,21 @@ namespace DiscImageChef.DiscImages entry.Dummy = tmpbuffer[3]; entry.LbaStart = BigEndianBitConverter.ToInt32(tmpbuffer, 4); - DicConsole.DebugWriteLine("Nero plugin", "Cuesheet entry {0}", i / 8 + 1); - DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Mode = 0x{1:X2}", i / 8 + 1, + DicConsole.DebugWriteLine("Nero plugin", "Cuesheet entry {0}", (i / 8) + 1); + + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Mode = 0x{1:X2}", (i / 8) + 1, entry.Mode); + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].TrackNumber = {1:X2}", - i / 8 + 1, entry.TrackNumber); + (i / 8) + 1, entry.TrackNumber); + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].IndexNumber = {1:X2}", - i / 8 + 1, entry.IndexNumber); - DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Dummy = {1:X2}", i / 8 + 1, + (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, + + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].LBAStart = {1}", (i / 8) + 1, entry.LbaStart); neroCuesheetV2.Entries.Add(entry); @@ -201,7 +227,10 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("Nero plugin", "Found \"DAOI\" chunk, parsing {0} bytes", chunkLength); - neroDaov1 = new NeroV1Dao {ChunkId = chunkId, ChunkSizeBe = chunkLength}; + neroDaov1 = new NeroV1Dao + { + ChunkId = chunkId, ChunkSizeBe = chunkLength + }; byte[] tmpbuffer = new byte[22]; imageStream.Read(tmpbuffer, 0, 22); @@ -221,19 +250,24 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("Nero plugin", "neroDAOV1.ChunkSizeLe = {0} bytes", neroDaov1.ChunkSizeLe); + DicConsole.DebugWriteLine("Nero plugin", "neroDAOV1.UPC = \"{0}\"", StringHandlers.CToString(neroDaov1.Upc)); + DicConsole.DebugWriteLine("Nero plugin", "neroDAOV1.TocType = 0x{0:X4}", neroDaov1.TocType); + DicConsole.DebugWriteLine("Nero plugin", "neroDAOV1.FirstTrack = {0}", neroDaov1.FirstTrack); + DicConsole.DebugWriteLine("Nero plugin", "neroDAOV1.LastTrack = {0}", neroDaov1.LastTrack); upc = neroDaov1.Upc; tmpbuffer = new byte[30]; + for(int i = 0; i < neroDaov1.ChunkSizeBe - 22; i += 30) { - NeroV1DaoEntry entry = new NeroV1DaoEntry(); + var entry = new NeroV1DaoEntry(); imageStream.Read(tmpbuffer, 0, 30); entry.Isrc = new byte[12]; Array.Copy(tmpbuffer, 4, entry.Isrc, 0, 12); @@ -244,42 +278,49 @@ namespace DiscImageChef.DiscImages entry.Index1 = BigEndianBitConverter.ToUInt32(tmpbuffer, 22); entry.EndOfTrack = BigEndianBitConverter.ToUInt32(tmpbuffer, 26); - DicConsole.DebugWriteLine("Nero plugin", "Disc-At-Once entry {0}", i / 32 + 1); - DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].ISRC = \"{1}\"", i / 32 + 1, + DicConsole.DebugWriteLine("Nero plugin", "Disc-At-Once entry {0}", (i / 32) + 1); + + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].ISRC = \"{1}\"", (i / 32) + 1, StringHandlers.CToString(entry.Isrc)); - DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].SectorSize = {1}", i / 32 + 1, - entry.SectorSize); + + 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 = 0x{1:X4}", - i / 32 + 1, entry.Unknown); - DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Index0 = {1}", i / 32 + 1, + (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, + + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Index1 = {1}", (i / 32) + 1, entry.Index1); - DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].EndOfTrack = {1}", i / 32 + 1, - entry.EndOfTrack); + + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].EndOfTrack = {1}", + (i / 32) + 1, entry.EndOfTrack); neroDaov1.Tracks.Add(entry); - if(entry.SectorSize > imageInfo.SectorSize) imageInfo.SectorSize = entry.SectorSize; + if(entry.SectorSize > imageInfo.SectorSize) + imageInfo.SectorSize = entry.SectorSize; trackIsrCs.Add(currenttrack, entry.Isrc); - if(currenttrack == 1) entry.Index0 = entry.Index1; - NeroTrack neroTrack = new NeroTrack + if(currenttrack == 1) + entry.Index0 = entry.Index1; + + var neroTrack = new NeroTrack { - EndOfTrack = entry.EndOfTrack, - Isrc = entry.Isrc, - Length = entry.EndOfTrack - entry.Index0, - Mode = entry.Mode, + EndOfTrack = entry.EndOfTrack, Isrc = entry.Isrc, + Length = entry.EndOfTrack - entry.Index0, Mode = entry.Mode, Offset = entry.Index0, - SectorSize = entry.SectorSize, - StartLba = imageInfo.Sectors, + SectorSize = entry.SectorSize, StartLba = imageInfo.Sectors, Index0 = entry.Index0, - Index1 = entry.Index1, - Sequence = currenttrack + Index1 = entry.Index1, Sequence = currenttrack }; + neroTrack.Sectors = neroTrack.Length / entry.SectorSize; neroTracks.Add(currenttrack, neroTrack); @@ -296,7 +337,10 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("Nero plugin", "Found \"DAOX\" chunk, parsing {0} bytes", chunkLength); - neroDaov2 = new NeroV2Dao {ChunkId = chunkId, ChunkSizeBe = chunkLength}; + neroDaov2 = new NeroV2Dao + { + ChunkId = chunkId, ChunkSizeBe = chunkLength + }; byte[] tmpbuffer = new byte[22]; imageStream.Read(tmpbuffer, 0, 22); @@ -318,17 +362,22 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("Nero plugin", "neroDAOV2.ChunkSizeLe = {0} bytes", neroDaov2.ChunkSizeLe); + DicConsole.DebugWriteLine("Nero plugin", "neroDAOV2.UPC = \"{0}\"", StringHandlers.CToString(neroDaov2.Upc)); + DicConsole.DebugWriteLine("Nero plugin", "neroDAOV2.TocType = 0x{0:X4}", neroDaov2.TocType); + DicConsole.DebugWriteLine("Nero plugin", "neroDAOV2.FirstTrack = {0}", neroDaov2.FirstTrack); + DicConsole.DebugWriteLine("Nero plugin", "neroDAOV2.LastTrack = {0}", neroDaov2.LastTrack); tmpbuffer = new byte[42]; + for(int i = 0; i < neroDaov2.ChunkSizeBe - 22; i += 42) { - NeroV2DaoEntry entry = new NeroV2DaoEntry(); + var entry = new NeroV2DaoEntry(); imageStream.Read(tmpbuffer, 0, 42); entry.Isrc = new byte[12]; Array.Copy(tmpbuffer, 4, entry.Isrc, 0, 12); @@ -339,43 +388,49 @@ namespace DiscImageChef.DiscImages entry.Index1 = BigEndianBitConverter.ToUInt64(tmpbuffer, 26); entry.EndOfTrack = BigEndianBitConverter.ToUInt64(tmpbuffer, 34); - DicConsole.DebugWriteLine("Nero plugin", "Disc-At-Once entry {0}", i / 32 + 1); - DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].ISRC = \"{1}\"", i / 32 + 1, + DicConsole.DebugWriteLine("Nero plugin", "Disc-At-Once entry {0}", (i / 32) + 1); + + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].ISRC = \"{1}\"", (i / 32) + 1, StringHandlers.CToString(entry.Isrc)); - DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].SectorSize = {1}", i / 32 + 1, - entry.SectorSize); + + 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); - 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, + (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, entry.Index0); - DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Index1 = {1}", i / 32 + 1, + + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Index1 = {1}", (i / 32) + 1, entry.Index1); - DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].EndOfTrack = {1}", i / 32 + 1, - entry.EndOfTrack); + + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].EndOfTrack = {1}", + (i / 32) + 1, entry.EndOfTrack); neroDaov2.Tracks.Add(entry); - if(entry.SectorSize > imageInfo.SectorSize) imageInfo.SectorSize = entry.SectorSize; + if(entry.SectorSize > imageInfo.SectorSize) + imageInfo.SectorSize = entry.SectorSize; trackIsrCs.Add(currenttrack, entry.Isrc); - if(currenttrack == 1) entry.Index0 = entry.Index1; + if(currenttrack == 1) + entry.Index0 = entry.Index1; - NeroTrack neroTrack = new NeroTrack + var neroTrack = new NeroTrack { - EndOfTrack = entry.EndOfTrack, - Isrc = entry.Isrc, - Length = entry.EndOfTrack - entry.Index0, - Mode = entry.Mode, + EndOfTrack = entry.EndOfTrack, Isrc = entry.Isrc, + Length = entry.EndOfTrack - entry.Index0, Mode = entry.Mode, Offset = entry.Index0, - SectorSize = entry.SectorSize, - StartLba = imageInfo.Sectors, + SectorSize = entry.SectorSize, StartLba = imageInfo.Sectors, Index0 = entry.Index0, - Index1 = entry.Index1, - Sequence = currenttrack + Index1 = entry.Index1, Sequence = currenttrack }; + neroTrack.Sectors = neroTrack.Length / entry.SectorSize; neroTracks.Add(currenttrack, neroTrack); @@ -398,9 +453,10 @@ namespace DiscImageChef.DiscImages }; byte[] tmpbuffer = new byte[18]; + for(int i = 0; i < neroCdtxt.ChunkSize; i += 18) { - NeroCdTextPack entry = new NeroCdTextPack(); + var entry = new NeroCdTextPack(); imageStream.Read(tmpbuffer, 0, 18); entry.PackType = tmpbuffer[0]; @@ -411,18 +467,24 @@ namespace DiscImageChef.DiscImages Array.Copy(tmpbuffer, 4, entry.Text, 0, 12); entry.Crc = BigEndianBitConverter.ToUInt16(tmpbuffer, 16); - DicConsole.DebugWriteLine("Nero plugin", "CD-TEXT entry {0}", i / 18 + 1); + DicConsole.DebugWriteLine("Nero plugin", "CD-TEXT entry {0}", (i / 18) + 1); + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].PackType = 0x{1:X2}", - i / 18 + 1, entry.PackType); + (i / 18) + 1, entry.PackType); + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].TrackNumber = 0x{1:X2}", - i / 18 + 1, entry.TrackNumber); + (i / 18) + 1, entry.TrackNumber); + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].PackNumber = 0x{1:X2}", - i / 18 + 1, entry.PackNumber); + (i / 18) + 1, entry.PackNumber); + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].BlockNumber = 0x{1:X2}", - i / 18 + 1, entry.BlockNumber); - DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Text = \"{1}\"", i / 18 + 1, + (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, + + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].CRC = 0x{1:X4}", (i / 18) + 1, entry.Crc); neroCdtxt.Packs.Add(entry); @@ -442,9 +504,10 @@ namespace DiscImageChef.DiscImages }; byte[] tmpbuffer = new byte[20]; + for(int i = 0; i < neroTaov1.ChunkSize; i += 20) { - NeroV1TaoEntry entry = new NeroV1TaoEntry(); + var entry = new NeroV1TaoEntry(); imageStream.Read(tmpbuffer, 0, 20); entry.Offset = BigEndianBitConverter.ToUInt32(tmpbuffer, 0); @@ -453,38 +516,40 @@ namespace DiscImageChef.DiscImages entry.StartLba = BigEndianBitConverter.ToUInt32(tmpbuffer, 12); entry.Unknown = BigEndianBitConverter.ToUInt32(tmpbuffer, 16); - DicConsole.DebugWriteLine("Nero plugin", "Track-at-Once entry {0}", i / 20 + 1); - DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Offset = {1}", i / 20 + 1, + DicConsole.DebugWriteLine("Nero plugin", "Track-at-Once entry {0}", (i / 20) + 1); + + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Offset = {1}", (i / 20) + 1, entry.Offset); + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Length = {1} bytes", - i / 20 + 1, entry.Length); + (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); - DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].StartLBA = {1}", i / 20 + 1, + (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}", - i / 20 + 1, entry.Unknown); + (i / 20) + 1, entry.Unknown); neroTaov1.Tracks.Add(entry); if(NeroTrackModeToBytesPerSector((DaoMode)entry.Mode) > imageInfo.SectorSize) imageInfo.SectorSize = NeroTrackModeToBytesPerSector((DaoMode)entry.Mode); - NeroTrack neroTrack = new NeroTrack + var neroTrack = new NeroTrack { - EndOfTrack = entry.Offset + entry.Length, - Isrc = new byte[12], - Length = entry.Length, - Mode = entry.Mode, - Offset = entry.Offset, + EndOfTrack = entry.Offset + entry.Length, Isrc = new byte[12], + Length = entry.Length, Mode = entry.Mode, Offset = entry.Offset, SectorSize = NeroTrackModeToBytesPerSector((DaoMode)entry.Mode), - StartLba = imageInfo.Sectors, - Index0 = entry.Offset, - Index1 = entry.Offset, + StartLba = imageInfo.Sectors, Index0 = entry.Offset, Index1 = entry.Offset, Sequence = currenttrack }; + neroTrack.Sectors = neroTrack.Length / NeroTrackModeToBytesPerSector((DaoMode)entry.Mode); + neroTracks.Add(currenttrack, neroTrack); imageInfo.Sectors += neroTrack.Sectors; @@ -506,9 +571,10 @@ namespace DiscImageChef.DiscImages }; byte[] tmpbuffer = new byte[32]; + for(int i = 0; i < neroTaov2.ChunkSize; i += 32) { - NeroV2TaoEntry entry = new NeroV2TaoEntry(); + var entry = new NeroV2TaoEntry(); imageStream.Read(tmpbuffer, 0, 32); entry.Offset = BigEndianBitConverter.ToUInt64(tmpbuffer, 0); @@ -518,18 +584,24 @@ namespace DiscImageChef.DiscImages entry.Unknown = BigEndianBitConverter.ToUInt32(tmpbuffer, 24); entry.Sectors = BigEndianBitConverter.ToUInt32(tmpbuffer, 28); - DicConsole.DebugWriteLine("Nero plugin", "Track-at-Once entry {0}", i / 32 + 1); - DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Offset = {1}", i / 32 + 1, + DicConsole.DebugWriteLine("Nero plugin", "Track-at-Once entry {0}", (i / 32) + 1); + + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Offset = {1}", (i / 32) + 1, entry.Offset); + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Length = {1} bytes", - i / 32 + 1, entry.Length); + (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); - DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].StartLBA = {1}", i / 32 + 1, + (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); - DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Sectors = {1}", i / 32 + 1, + (i / 32) + 1, entry.Unknown); + + DicConsole.DebugWriteLine("Nero plugin", "\t _entry[{0}].Sectors = {1}", (i / 32) + 1, entry.Sectors); neroTaov2.Tracks.Add(entry); @@ -537,16 +609,15 @@ namespace DiscImageChef.DiscImages if(NeroTrackModeToBytesPerSector((DaoMode)entry.Mode) > imageInfo.SectorSize) imageInfo.SectorSize = NeroTrackModeToBytesPerSector((DaoMode)entry.Mode); - NeroTrack neroTrack = new NeroTrack + var neroTrack = new NeroTrack { - EndOfTrack = entry.Offset + entry.Length, - Isrc = new byte[12], - Length = entry.Length, - Mode = entry.Mode, - Offset = entry.Offset + EndOfTrack = entry.Offset + entry.Length, Isrc = new byte[12], + Length = entry.Length, Mode = entry.Mode, Offset = entry.Offset }; + neroTrack.Sectors = neroTrack.Length / NeroTrackModeToBytesPerSector((DaoMode)entry.Mode); + neroTrack.SectorSize = NeroTrackModeToBytesPerSector((DaoMode)entry.Mode); neroTrack.StartLba = imageInfo.Sectors; neroTrack.Index0 = entry.Offset; @@ -576,6 +647,7 @@ namespace DiscImageChef.DiscImages sessionTracks); currentsession++; + break; } @@ -584,7 +656,10 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("Nero plugin", "Found \"MTYP\" chunk, parsing {0} bytes", chunkLength); - neroMediaTyp = new NeroMediaType {ChunkId = chunkId, ChunkSize = chunkLength}; + neroMediaTyp = new NeroMediaType + { + ChunkId = chunkId, ChunkSize = chunkLength + }; byte[] tmpbuffer = new byte[4]; imageStream.Read(tmpbuffer, 0, 4); @@ -603,7 +678,11 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("Nero plugin", "Found \"DINF\" chunk, parsing {0} bytes", chunkLength); - neroDiscInfo = new NeroDiscInformation {ChunkId = chunkId, ChunkSize = chunkLength}; + neroDiscInfo = new NeroDiscInformation + { + ChunkId = chunkId, ChunkSize = chunkLength + }; + byte[] tmpbuffer = new byte[4]; imageStream.Read(tmpbuffer, 0, 4); neroDiscInfo.Unknown = BigEndianBitConverter.ToUInt32(tmpbuffer, 0); @@ -619,7 +698,11 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("Nero plugin", "Found \"RELO\" chunk, parsing {0} bytes", chunkLength); - neroRelo = new NeroReloChunk {ChunkId = chunkId, ChunkSize = chunkLength}; + neroRelo = new NeroReloChunk + { + ChunkId = chunkId, ChunkSize = chunkLength + }; + byte[] tmpbuffer = new byte[4]; imageStream.Read(tmpbuffer, 0, 4); neroRelo.Unknown = BigEndianBitConverter.ToUInt32(tmpbuffer, 0); @@ -635,7 +718,11 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("Nero plugin", "Found \"TOCT\" chunk, parsing {0} bytes", chunkLength); - neroToc = new NeroTocChunk {ChunkId = chunkId, ChunkSize = chunkLength}; + neroToc = new NeroTocChunk + { + ChunkId = chunkId, ChunkSize = chunkLength + }; + byte[] tmpbuffer = new byte[2]; imageStream.Read(tmpbuffer, 0, 2); neroToc.Unknown = BigEndianBitConverter.ToUInt16(tmpbuffer, 0); @@ -650,15 +737,18 @@ namespace DiscImageChef.DiscImages { DicConsole.DebugWriteLine("Nero plugin", "Found \"END!\" chunk, finishing parse"); parsing = false; + break; } default: { DicConsole.DebugWriteLine("Nero plugin", "Unknown chunk ID \"{0}\", skipping...", - Encoding.ASCII.GetString(BigEndianBitConverter - .GetBytes(chunkId))); + Encoding.ASCII.GetString(BigEndianBitConverter. + GetBytes(chunkId))); + imageStream.Seek(chunkLength, SeekOrigin.Current); + break; } } @@ -682,6 +772,7 @@ namespace DiscImageChef.DiscImages imageInfo.DriveFirmwareRevision = null; imageInfo.MediaSequence = 0; imageInfo.LastMediaSequence = 0; + if(imageNewFormat) { imageInfo.ImageSize = footerV2.FirstChunkOffset; @@ -697,35 +788,46 @@ namespace DiscImageChef.DiscImages imageInfo.ApplicationVersion = "<= 5.0"; } - if(neroSessions.Count == 0) neroSessions.Add(1, currenttrack); + if(neroSessions.Count == 0) + neroSessions.Add(1, currenttrack); DicConsole.DebugWriteLine("Nero plugin", "Building offset, track and session maps"); currentsession = 1; neroSessions.TryGetValue(1, out uint currentsessionmaxtrack); - uint currentsessioncurrenttrack = 1; - Session currentsessionstruct = new Session(); - ulong partitionSequence = 0; - ulong partitionStartByte = 0; + uint currentsessioncurrenttrack = 1; + var currentsessionstruct = new Session(); + ulong partitionSequence = 0; + ulong partitionStartByte = 0; + for(uint i = 1; i <= neroTracks.Count; i++) { - if(!neroTracks.TryGetValue(i, out NeroTrack neroTrack)) continue; + if(!neroTracks.TryGetValue(i, out NeroTrack neroTrack)) + continue; - DicConsole.DebugWriteLine("Nero plugin", "\tcurrentsession = {0}", currentsession); + DicConsole.DebugWriteLine("Nero plugin", "\tcurrentsession = {0}", currentsession); DicConsole.DebugWriteLine("Nero plugin", "\tcurrentsessionmaxtrack = {0}", currentsessionmaxtrack); + DicConsole.DebugWriteLine("Nero plugin", "\tcurrentsessioncurrenttrack = {0}", currentsessioncurrenttrack); - Track track = new Track(); - if(neroTrack.Sequence == 1) neroTrack.Index0 = neroTrack.Index1; + var track = new Track(); + + if(neroTrack.Sequence == 1) + neroTrack.Index0 = neroTrack.Index1; track.Indexes = new Dictionary(); + if(neroTrack.Index0 < neroTrack.Index1) track.Indexes.Add(0, neroTrack.Index0 / neroTrack.SectorSize); + 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.TrackDescription = StringHandlers.CToString(neroTrack.Isrc); + track.TrackEndSector = ((neroTrack.Length / neroTrack.SectorSize) + neroTrack.StartLba) - 1; + + track.TrackPregap = (neroTrack.Index1 - neroTrack.Index0) / + neroTrack.SectorSize; + track.TrackSequence = neroTrack.Sequence; track.TrackSession = currentsession; track.TrackStartSector = neroTrack.StartLba; @@ -735,43 +837,52 @@ namespace DiscImageChef.DiscImages track.TrackFileOffset = neroTrack.Offset; track.TrackFileType = "BINARY"; track.TrackSubchannelType = TrackSubchannelType.None; + switch((DaoMode)neroTrack.Mode) { case DaoMode.Audio: track.TrackBytesPerSector = 2352; track.TrackRawBytesPerSector = 2352; + break; case DaoMode.AudioSub: track.TrackBytesPerSector = 2352; track.TrackRawBytesPerSector = 2448; track.TrackSubchannelType = TrackSubchannelType.RawInterleaved; + break; case DaoMode.Data: case DaoMode.DataM2F1: track.TrackBytesPerSector = 2048; track.TrackRawBytesPerSector = 2048; + break; case DaoMode.DataM2F2: track.TrackBytesPerSector = 2336; track.TrackRawBytesPerSector = 2336; + break; case DaoMode.DataM2Raw: track.TrackBytesPerSector = 2352; track.TrackRawBytesPerSector = 2352; + break; case DaoMode.DataM2RawSub: track.TrackBytesPerSector = 2352; track.TrackRawBytesPerSector = 2448; track.TrackSubchannelType = TrackSubchannelType.RawInterleaved; + break; case DaoMode.DataRaw: track.TrackBytesPerSector = 2048; track.TrackRawBytesPerSector = 2352; + break; case DaoMode.DataRawSub: track.TrackBytesPerSector = 2048; track.TrackRawBytesPerSector = 2448; track.TrackSubchannelType = TrackSubchannelType.RawInterleaved; + break; } @@ -786,22 +897,26 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("Nero plugin", "\t\t _track.TrackDescription = {0}", track.TrackDescription); + DicConsole.DebugWriteLine("Nero plugin", "\t\t _track.TrackEndSector = {0}", track.TrackEndSector); - DicConsole.DebugWriteLine("Nero plugin", "\t\t _track.TrackPregap = {0}", track.TrackPregap); - DicConsole.DebugWriteLine("Nero plugin", "\t\t _track.TrackSequence = {0}", track.TrackSequence); - DicConsole.DebugWriteLine("Nero plugin", "\t\t _track.TrackSession = {0}", track.TrackSession); + DicConsole.DebugWriteLine("Nero plugin", "\t\t _track.TrackPregap = {0}", track.TrackPregap); + DicConsole.DebugWriteLine("Nero plugin", "\t\t _track.TrackSequence = {0}", track.TrackSequence); + DicConsole.DebugWriteLine("Nero plugin", "\t\t _track.TrackSession = {0}", track.TrackSession); + DicConsole.DebugWriteLine("Nero plugin", "\t\t _track.TrackStartSector = {0}", track.TrackStartSector); + DicConsole.DebugWriteLine("Nero plugin", "\t\t _track.TrackType = {0}", track.TrackType); if(currentsessioncurrenttrack == 1) currentsessionstruct = new Session { - SessionSequence = currentsession, - StartSector = track.TrackStartSector, + SessionSequence = currentsession, StartSector = track.TrackStartSector, StartTrack = track.TrackSequence }; + currentsessioncurrenttrack++; + if(currentsessioncurrenttrack > currentsessionmaxtrack) { currentsession++; @@ -822,6 +937,7 @@ namespace DiscImageChef.DiscImages } offsetmap.Add(track.TrackSequence, track.TrackStartSector); + DicConsole.DebugWriteLine("Nero plugin", "\t\t Offset[{0}]: {1}", track.TrackSequence, track.TrackStartSector); @@ -840,16 +956,17 @@ namespace DiscImageChef.DiscImages PartitionSequence++; }*/ - Partition partition = new Partition + var partition = new Partition { Description = $"Track {track.TrackSequence} Index 1", Size = neroTrack.EndOfTrack - neroTrack.Index1, Name = StringHandlers.CToString(neroTrack.Isrc), - Sequence = partitionSequence, - Offset = partitionStartByte, - Start = neroTrack.StartLba + (neroTrack.Index1 - neroTrack.Index0) / neroTrack.SectorSize, - Type = NeroTrackModeToTrackType((DaoMode)neroTrack.Mode).ToString() + Sequence = partitionSequence, Offset = partitionStartByte, + Start = neroTrack.StartLba + + ((neroTrack.Index1 - neroTrack.Index0) / neroTrack.SectorSize), + Type = NeroTrackModeToTrackType((DaoMode)neroTrack.Mode).ToString() }; + partition.Length = partition.Size / neroTrack.SectorSize; Partitions.Add(partition); partitionSequence++; @@ -858,7 +975,8 @@ namespace DiscImageChef.DiscImages neroFilter = imageFilter; - if(imageInfo.MediaType == MediaType.Unknown || imageInfo.MediaType == MediaType.CD) + if(imageInfo.MediaType == MediaType.Unknown || + imageInfo.MediaType == MediaType.CD) { bool data = false; bool mode2 = false; @@ -893,19 +1011,25 @@ namespace DiscImageChef.DiscImages case DaoMode.DataM2Raw: case DaoMode.DataM2RawSub: mode2 = true; + break; } } - if(!data && !firstdata) + if(!data && + !firstdata) imageInfo.MediaType = MediaType.CDDA; - else if(firstaudio && data && Sessions.Count > 1 && mode2) + else if(firstaudio && + data && + Sessions.Count > 1 && + mode2) imageInfo.MediaType = MediaType.CDPLUS; - else if(firstdata && audio || mode2) + else if((firstdata && audio) || mode2) imageInfo.MediaType = MediaType.CDROMXA; else if(!audio) - imageInfo.MediaType = MediaType.CDROM; - else imageInfo.MediaType = MediaType.CD; + imageInfo.MediaType = MediaType.CDROM; + else + imageInfo.MediaType = MediaType.CD; } imageInfo.XmlMediaType = XmlMediaType.OpticalDisc; @@ -916,6 +1040,7 @@ namespace DiscImageChef.DiscImages catch { DicConsole.DebugWrite("Nero plugin", "Exception ocurred opening file."); + return false; } } @@ -942,13 +1067,10 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectors(ulong sectorAddress, uint length) { - foreach(KeyValuePair kvp in from kvp in offsetmap - where sectorAddress >= kvp.Value - from track in Tracks - where track.TrackSequence == kvp.Key + foreach(KeyValuePair kvp in from kvp in offsetmap where sectorAddress >= kvp.Value + from track in Tracks where track.TrackSequence == kvp.Key where sectorAddress - kvp.Value < - track.TrackEndSector - track.TrackStartSector - select kvp) + track.TrackEndSector - track.TrackStartSector select kvp) return ReadSectors(sectorAddress - kvp.Value, length, kvp.Key); throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found"); @@ -956,13 +1078,10 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) { - foreach(KeyValuePair kvp in from kvp in offsetmap - where sectorAddress >= kvp.Value - from track in Tracks - where track.TrackSequence == kvp.Key + foreach(KeyValuePair kvp in from kvp in offsetmap where sectorAddress >= kvp.Value + from track in Tracks where track.TrackSequence == kvp.Key where sectorAddress - kvp.Value < - track.TrackEndSector - track.TrackStartSector - select kvp) + track.TrackEndSector - track.TrackStartSector select kvp) return ReadSectorsTag(sectorAddress - kvp.Value, length, kvp.Key, tag); throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found"); @@ -980,6 +1099,7 @@ namespace DiscImageChef.DiscImages uint sectorOffset; uint sectorSize; uint sectorSkip; + bool mode2 = false; switch((DaoMode)dicTrack.Mode) { @@ -989,14 +1109,17 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 2048; sectorSkip = 0; + break; } case DaoMode.DataM2F2: { - sectorOffset = 8; - sectorSize = 2324; - sectorSkip = 4; + mode2 = true; + sectorOffset = 0; + sectorSize = 2336; + sectorSkip = 0; + break; } @@ -1005,6 +1128,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 2352; sectorSkip = 0; + break; } @@ -1013,14 +1137,17 @@ namespace DiscImageChef.DiscImages sectorOffset = 16; sectorSize = 2048; sectorSkip = 288; + break; } case DaoMode.DataM2Raw: { - sectorOffset = 16; - sectorSize = 2336; + mode2 = true; + sectorOffset = 0; + sectorSize = 2352; sectorSkip = 0; + break; } @@ -1030,14 +1157,17 @@ namespace DiscImageChef.DiscImages sectorOffset = 16; sectorSize = 2048; sectorSkip = 288 + 96; + break; } case DaoMode.DataM2RawSub: { - sectorOffset = 16; - sectorSize = 2336; + mode2 = true; + sectorOffset = 0; + sectorSize = 2352; sectorSkip = 96; + break; } @@ -1046,6 +1176,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 2352; sectorSkip = 96; + break; } @@ -1055,10 +1186,30 @@ namespace DiscImageChef.DiscImages byte[] buffer = new byte[sectorSize * length]; imageStream = neroFilter.GetDataForkStream(); - BinaryReader br = new BinaryReader(imageStream); + var br = new BinaryReader(imageStream); + br.BaseStream.Seek((long)dicTrack.Offset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), SeekOrigin.Begin); - if(sectorOffset == 0 && sectorSkip == 0) buffer = br.ReadBytes((int)(sectorSize * length)); + + if(mode2) + { + var mode2Ms = new MemoryStream((int)(sectorSize * length)); + + buffer = br.ReadBytes((int)((sectorSize + sectorSkip) * length)); + + for(int i = 0; i < length; i++) + { + byte[] sector = new byte[sectorSize]; + Array.Copy(buffer, (sectorSize + sectorSkip) * i, sector, 0, sectorSize); + sector = Sector.GetUserDataFromMode2(sector); + mode2Ms.Write(sector, 0, sector.Length); + } + + buffer = mode2Ms.ToArray(); + } + else if(sectorOffset == 0 && + sectorSkip == 0) + buffer = br.ReadBytes((int)(sectorSize * length)); else for(int i = 0; i < length; i++) { @@ -1099,7 +1250,8 @@ namespace DiscImageChef.DiscImages byte[] flags = new byte[1]; flags[0] = 0x00; - if((DaoMode)dicTrack.Mode != DaoMode.Audio && (DaoMode)dicTrack.Mode != DaoMode.AudioSub) + if((DaoMode)dicTrack.Mode != DaoMode.Audio && + (DaoMode)dicTrack.Mode != DaoMode.AudioSub) flags[0] += 0x4; return flags; @@ -1131,6 +1283,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 8; sectorSkip = 2328; + break; } @@ -1139,6 +1292,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2332; sectorSize = 4; sectorSkip = 0; + break; } @@ -1158,6 +1312,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 12; sectorSkip = 2340; + break; } @@ -1166,6 +1321,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 12; sectorSize = 4; sectorSkip = 2336; + break; } @@ -1177,6 +1333,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2076; sectorSize = 276; sectorSkip = 0; + break; } @@ -1185,6 +1342,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2076; sectorSize = 172; sectorSkip = 104; + break; } @@ -1193,6 +1351,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2248; sectorSize = 104; sectorSkip = 0; + break; } @@ -1201,6 +1360,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2064; sectorSize = 4; sectorSkip = 284; + break; } @@ -1222,6 +1382,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 12; sectorSkip = 2340 + 96; + break; } @@ -1230,6 +1391,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 12; sectorSize = 4; sectorSkip = 2336 + 96; + break; } @@ -1238,6 +1400,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2352; sectorSize = 96; sectorSkip = 0; + break; } @@ -1248,6 +1411,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2076; sectorSize = 276; sectorSkip = 0 + 96; + break; } @@ -1256,6 +1420,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2076; sectorSize = 172; sectorSkip = 104 + 96; + break; } @@ -1264,6 +1429,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2248; sectorSize = 104; sectorSkip = 0 + 96; + break; } @@ -1272,6 +1438,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2064; sectorSize = 4; sectorSkip = 284 + 96; + break; } @@ -1289,6 +1456,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2352; sectorSize = 96; sectorSkip = 0; + break; } @@ -1298,10 +1466,14 @@ namespace DiscImageChef.DiscImages byte[] buffer = new byte[sectorSize * length]; imageStream = neroFilter.GetDataForkStream(); - BinaryReader br = new BinaryReader(imageStream); + var br = new BinaryReader(imageStream); + br.BaseStream.Seek((long)dicTrack.Offset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), SeekOrigin.Begin); - if(sectorOffset == 0 && sectorSkip == 0) buffer = br.ReadBytes((int)(sectorSize * length)); + + if(sectorOffset == 0 && + sectorSkip == 0) + buffer = br.ReadBytes((int)(sectorSize * length)); else for(int i = 0; i < length; i++) { @@ -1320,13 +1492,10 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectorsLong(ulong sectorAddress, uint length) { - foreach(KeyValuePair kvp in from kvp in offsetmap - where sectorAddress >= kvp.Value - from track in Tracks - where track.TrackSequence == kvp.Key + foreach(KeyValuePair kvp in from kvp in offsetmap where sectorAddress >= kvp.Value + from track in Tracks where track.TrackSequence == kvp.Key where sectorAddress - kvp.Value < - track.TrackEndSector - track.TrackStartSector - select kvp) + track.TrackEndSector - track.TrackStartSector select kvp) return ReadSectorsLong(sectorAddress - kvp.Value, length, kvp.Key); throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found"); @@ -1353,6 +1522,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 2048; sectorSkip = 0; + break; } @@ -1361,6 +1531,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 2336; sectorSkip = 0; + break; } @@ -1371,6 +1542,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 2352; sectorSkip = 0; + break; } @@ -1381,6 +1553,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 2448; sectorSkip = 0; + break; } @@ -1390,12 +1563,14 @@ namespace DiscImageChef.DiscImages byte[] buffer = new byte[sectorSize * length]; imageStream = neroFilter.GetDataForkStream(); - BinaryReader br = new BinaryReader(imageStream); + var br = new BinaryReader(imageStream); br.BaseStream.Seek((long)dicTrack.Offset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), SeekOrigin.Begin); - if(sectorOffset == 0 && sectorSkip == 0) buffer = br.ReadBytes((int)(sectorSize * length)); + if(sectorOffset == 0 && + sectorSkip == 0) + buffer = br.ReadBytes((int)(sectorSize * length)); else for(int i = 0; i < length; i++) { @@ -1411,9 +1586,7 @@ namespace DiscImageChef.DiscImages public List GetSessionTracks(Session session) => GetSessionTracks(session.SessionSequence); - public List GetSessionTracks(ushort session) - { - return Tracks.Where(track => track.TrackSession == session).ToList(); - } + public List GetSessionTracks(ushort session) => + Tracks.Where(track => track.TrackSession == session).ToList(); } } \ No newline at end of file diff --git a/DiscImageChef.DiscImages/ZZZRawImage/Read.cs b/DiscImageChef.DiscImages/ZZZRawImage/Read.cs index 1acca74c5..aa9ba0231 100644 --- a/DiscImageChef.DiscImages/ZZZRawImage/Read.cs +++ b/DiscImageChef.DiscImages/ZZZRawImage/Read.cs @@ -40,6 +40,7 @@ using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Exceptions; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Structs; +using DiscImageChef.CommonTypes.Structs.Devices.ATA; using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Console; using DiscImageChef.Decoders.CD; @@ -57,26 +58,31 @@ namespace DiscImageChef.DiscImages { public bool Open(IFilter imageFilter) { - var stream = imageFilter.GetDataForkStream(); + Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); extension = Path.GetExtension(imageFilter.GetFilename())?.ToLower(); - switch (extension) + + switch(extension) { - case ".iso" when imageFilter.GetDataForkLength() % 2048 == 0: + case".iso" when imageFilter.GetDataForkLength() % 2048 == 0: imageInfo.SectorSize = 2048; + break; - case ".d81" when imageFilter.GetDataForkLength() == 819200: + case".d81" when imageFilter.GetDataForkLength() == 819200: imageInfo.SectorSize = 256; + break; default: - if ((extension == ".adf" || extension == ".adl" || extension == ".ssd" || extension == ".dsd") && - (imageFilter.GetDataForkLength() == 163840 || imageFilter.GetDataForkLength() == 327680 || - imageFilter.GetDataForkLength() == 655360)) imageInfo.SectorSize = 256; - else if ((extension == ".adf" || extension == ".adl") && imageFilter.GetDataForkLength() == 819200) + if((extension == ".adf" || extension == ".adl" || extension == ".ssd" || extension == ".dsd") && + (imageFilter.GetDataForkLength() == 163840 || imageFilter.GetDataForkLength() == 327680 || + imageFilter.GetDataForkLength() == 655360)) + imageInfo.SectorSize = 256; + else if((extension == ".adf" || extension == ".adl") && + imageFilter.GetDataForkLength() == 819200) imageInfo.SectorSize = 1024; else - switch (imageFilter.GetDataForkLength()) + switch(imageFilter.GetDataForkLength()) { case 242944: case 256256: @@ -84,11 +90,12 @@ namespace DiscImageChef.DiscImages case 92160: case 133120: imageInfo.SectorSize = 128; + break; case 116480: - case 287488: // T0S0 = 128bps - case 988416: // T0S0 = 128bps - case 995072: // T0S0 = 128bps, T0S1 = 256bps + case 287488: // T0S0 = 128bps + case 988416: // T0S0 = 128bps + case 995072: // T0S0 = 128bps, T0S1 = 256bps case 1021696: // T0S0 = 128bps, T0S1 = 256bps case 232960: case 143360: @@ -97,12 +104,11 @@ namespace DiscImageChef.DiscImages case 102400: case 204800: case 655360: - case 80384: // T0S0 = 128bps + case 80384: // T0S0 = 128bps case 325632: // T0S0 = 128bps, T0S1 = 256bps case 653312: // T0S0 = 128bps, T0S1 = 256bps #region Commodore - case 174848: case 175531: case 196608: @@ -110,18 +116,20 @@ namespace DiscImageChef.DiscImages case 349696: case 351062: case 822400: - #endregion Commodore imageInfo.SectorSize = 256; + break; case 81664: imageInfo.SectorSize = 319; + break; - case 306432: // T0S0 = 128bps + case 306432: // T0S0 = 128bps case 1146624: // T0S0 = 128bps, T0S1 = 256bps case 1177344: // T0S0 = 128bps, T0S1 = 256bps imageInfo.SectorSize = 512; + break; case 1222400: // T0S0 = 128bps, T0S1 = 256bps case 1304320: // T0S0 = 128bps, T0S1 = 256bps @@ -129,193 +137,224 @@ namespace DiscImageChef.DiscImages case 1261568: case 1638400: imageInfo.SectorSize = 1024; + break; case 35002122240: imageInfo.SectorSize = 2048; + break; default: imageInfo.SectorSize = 512; + break; } break; } - imageInfo.ImageSize = (ulong) imageFilter.GetDataForkLength(); - imageInfo.CreationTime = imageFilter.GetCreationTime(); + imageInfo.ImageSize = (ulong)imageFilter.GetDataForkLength(); + imageInfo.CreationTime = imageFilter.GetCreationTime(); imageInfo.LastModificationTime = imageFilter.GetLastWriteTime(); - imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename()); - differentTrackZeroSize = false; - rawImageFilter = imageFilter; + imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename()); + differentTrackZeroSize = false; + rawImageFilter = imageFilter; - switch (imageFilter.GetDataForkLength()) + switch(imageFilter.GetDataForkLength()) { case 242944: imageInfo.Sectors = 1898; + break; case 256256: imageInfo.Sectors = 2002; + break; case 495872: imageInfo.Sectors = 3874; + break; case 116480: imageInfo.Sectors = 455; + break; case 287488: // T0S0 = 128bps - imageInfo.Sectors = 1136; + imageInfo.Sectors = 1136; differentTrackZeroSize = true; + break; case 988416: // T0S0 = 128bps - imageInfo.Sectors = 3874; + imageInfo.Sectors = 3874; differentTrackZeroSize = true; + break; case 995072: // T0S0 = 128bps, T0S1 = 256bps - imageInfo.Sectors = 3900; + imageInfo.Sectors = 3900; differentTrackZeroSize = true; + break; case 1021696: // T0S0 = 128bps, T0S1 = 256bps - imageInfo.Sectors = 4004; + imageInfo.Sectors = 4004; differentTrackZeroSize = true; + break; case 81664: imageInfo.Sectors = 256; + break; case 306432: // T0S0 = 128bps - imageInfo.Sectors = 618; + imageInfo.Sectors = 618; differentTrackZeroSize = true; + break; case 1146624: // T0S0 = 128bps, T0S1 = 256bps - imageInfo.Sectors = 2272; + imageInfo.Sectors = 2272; differentTrackZeroSize = true; + break; case 1177344: // T0S0 = 128bps, T0S1 = 256bps - imageInfo.Sectors = 2332; + imageInfo.Sectors = 2332; differentTrackZeroSize = true; + break; case 1222400: // T0S0 = 128bps, T0S1 = 256bps - imageInfo.Sectors = 1236; + imageInfo.Sectors = 1236; differentTrackZeroSize = true; + break; case 1304320: // T0S0 = 128bps, T0S1 = 256bps - imageInfo.Sectors = 1316; + imageInfo.Sectors = 1316; differentTrackZeroSize = true; + break; case 1255168: // T0S0 = 128bps, T0S1 = 256bps - imageInfo.Sectors = 1268; + imageInfo.Sectors = 1268; differentTrackZeroSize = true; + break; case 80384: // T0S0 = 128bps - imageInfo.Sectors = 322; + imageInfo.Sectors = 322; differentTrackZeroSize = true; + break; case 325632: // T0S0 = 128bps, T0S1 = 256bps - imageInfo.Sectors = 1280; + imageInfo.Sectors = 1280; differentTrackZeroSize = true; + break; case 653312: // T0S0 = 128bps, T0S1 = 256bps - imageInfo.Sectors = 2560; + imageInfo.Sectors = 2560; differentTrackZeroSize = true; + break; case 1880064: // IBM XDF, 3,5", real number of sectors - imageInfo.Sectors = 670; - imageInfo.SectorSize = 8192; // Biggest sector size + imageInfo.Sectors = 670; + imageInfo.SectorSize = 8192; // Biggest sector size differentTrackZeroSize = true; + break; case 175531: imageInfo.Sectors = 683; + break; case 197375: imageInfo.Sectors = 768; + break; case 351062: imageInfo.Sectors = 1366; + break; case 822400: imageInfo.Sectors = 3200; + break; default: imageInfo.Sectors = imageInfo.ImageSize / imageInfo.SectorSize; + break; } imageInfo.MediaType = CalculateDiskType(); - if (imageInfo.ImageSize % 2352 == 0 || imageInfo.ImageSize % 2448 == 0) + if(imageInfo.ImageSize % 2352 == 0 || + imageInfo.ImageSize % 2448 == 0) { - var sync = new byte[12]; - var header = new byte[4]; + byte[] sync = new byte[12]; + byte[] header = new byte[4]; stream.Seek(0, SeekOrigin.Begin); stream.Read(sync, 0, 12); stream.Read(header, 0, 4); - if (cdSync.SequenceEqual(sync)) + + if(cdSync.SequenceEqual(sync)) { - rawCompactDisc = true; - hasSubchannel = imageInfo.ImageSize % 2448 == 0; - imageInfo.Sectors = imageInfo.ImageSize / (ulong) (hasSubchannel ? 2448 : 2352); - imageInfo.MediaType = MediaType.CD; - mode2 = header[3] == 0x02; - imageInfo.SectorSize = (uint) (mode2 ? 2336 : 2048); + rawCompactDisc = true; + hasSubchannel = imageInfo.ImageSize % 2448 == 0; + imageInfo.Sectors = imageInfo.ImageSize / (ulong)(hasSubchannel ? 2448 : 2352); + imageInfo.MediaType = MediaType.CD; + mode2 = header[3] == 0x02; + imageInfo.SectorSize = (uint)(mode2 ? 2336 : 2048); } } // Sharp X68000 SASI hard disks - if (extension == ".hdf") - if (imageInfo.ImageSize % 256 == 0) + if(extension == ".hdf") + if(imageInfo.ImageSize % 256 == 0) { imageInfo.SectorSize = 256; - imageInfo.Sectors = imageInfo.ImageSize / imageInfo.SectorSize; - imageInfo.MediaType = MediaType.GENERIC_HDD; + imageInfo.Sectors = imageInfo.ImageSize / imageInfo.SectorSize; + imageInfo.MediaType = MediaType.GENERIC_HDD; } // Search for known tags - var basename = imageFilter.GetBasePath(); + string basename = imageFilter.GetBasePath(); basename = basename.Substring(0, basename.Length - extension.Length); mediaTags = new Dictionary(); - foreach (var sidecar in readWriteSidecars) + + foreach((MediaTagType tag, string name) sidecar in readWriteSidecars) try { - var filters = new FiltersList(); - var filter = filters.GetFilter(basename + sidecar.name); - if (filter == null || !filter.IsOpened()) continue; + var filters = new FiltersList(); + IFilter filter = filters.GetFilter(basename + sidecar.name); + + if(filter == null || + !filter.IsOpened()) + continue; DicConsole.DebugWriteLine("ZZZRawImage Plugin", "Found media tag {0}", sidecar.tag); - var data = new byte[filter.GetDataForkLength()]; + byte[] data = new byte[filter.GetDataForkLength()]; filter.GetDataForkStream().Read(data, 0, data.Length); mediaTags.Add(sidecar.tag, data); } - catch (IOException) - { - } + catch(IOException) { } // If there are INQUIRY and IDENTIFY tags, it's ATAPI - if (mediaTags.ContainsKey(MediaTagType.SCSI_INQUIRY)) - if (mediaTags.TryGetValue(MediaTagType.ATA_IDENTIFY, out var tag)) + if(mediaTags.ContainsKey(MediaTagType.SCSI_INQUIRY)) + if(mediaTags.TryGetValue(MediaTagType.ATA_IDENTIFY, out byte[] tag)) { mediaTags.Remove(MediaTagType.ATA_IDENTIFY); mediaTags.Add(MediaTagType.ATAPI_IDENTIFY, tag); } // It is a blu-ray - if (mediaTags.ContainsKey(MediaTagType.BD_DI)) + if(mediaTags.ContainsKey(MediaTagType.BD_DI)) { imageInfo.MediaType = MediaType.BDROM; - if (mediaTags.TryGetValue(MediaTagType.DVD_BCA, out var bca)) + if(mediaTags.TryGetValue(MediaTagType.DVD_BCA, out byte[] bca)) { mediaTags.Remove(MediaTagType.DVD_BCA); mediaTags.Add(MediaTagType.BD_BCA, bca); } - if (mediaTags.TryGetValue(MediaTagType.DVDRAM_DDS, out var dds)) + if(mediaTags.TryGetValue(MediaTagType.DVDRAM_DDS, out byte[] dds)) { imageInfo.MediaType = MediaType.BDRE; mediaTags.Remove(MediaTagType.DVDRAM_DDS); mediaTags.Add(MediaTagType.BD_DDS, dds); } - if (mediaTags.TryGetValue(MediaTagType.DVDRAM_SpareArea, out var sai)) + if(mediaTags.TryGetValue(MediaTagType.DVDRAM_SpareArea, out byte[] sai)) { imageInfo.MediaType = MediaType.BDRE; mediaTags.Remove(MediaTagType.DVDRAM_SpareArea); @@ -324,105 +363,123 @@ namespace DiscImageChef.DiscImages } // It is a DVD - if (mediaTags.TryGetValue(MediaTagType.DVD_PFI, out var pfi)) + if(mediaTags.TryGetValue(MediaTagType.DVD_PFI, out byte[] pfi)) { - var decPfi = PFI.Decode(pfi).Value; - switch (decPfi.DiskCategory) + PFI.PhysicalFormatInformation decPfi = PFI.Decode(pfi).Value; + + switch(decPfi.DiskCategory) { case DiskCategory.DVDPR: imageInfo.MediaType = MediaType.DVDPR; + break; case DiskCategory.DVDPRDL: imageInfo.MediaType = MediaType.DVDPRDL; + break; case DiskCategory.DVDPRW: imageInfo.MediaType = MediaType.DVDPRW; + break; case DiskCategory.DVDPRWDL: imageInfo.MediaType = MediaType.DVDPRWDL; + break; case DiskCategory.DVDR: imageInfo.MediaType = decPfi.PartVersion == 6 ? MediaType.DVDRDL : MediaType.DVDR; + break; case DiskCategory.DVDRAM: imageInfo.MediaType = MediaType.DVDRAM; + break; default: imageInfo.MediaType = MediaType.DVDROM; + break; case DiskCategory.DVDRW: imageInfo.MediaType = decPfi.PartVersion == 3 ? MediaType.DVDRWDL : MediaType.DVDRW; + break; case DiskCategory.HDDVDR: imageInfo.MediaType = MediaType.HDDVDR; + break; case DiskCategory.HDDVDRAM: imageInfo.MediaType = MediaType.HDDVDRAM; + break; case DiskCategory.HDDVDROM: imageInfo.MediaType = MediaType.HDDVDROM; + break; case DiskCategory.HDDVDRW: imageInfo.MediaType = MediaType.HDDVDRW; + break; case DiskCategory.Nintendo: imageInfo.MediaType = decPfi.DiscSize == DVDSize.Eighty ? MediaType.GOD : MediaType.WOD; + break; case DiskCategory.UMD: imageInfo.MediaType = MediaType.UMD; + break; } - if ((imageInfo.MediaType == MediaType.DVDR || imageInfo.MediaType == MediaType.DVDRW || - imageInfo.MediaType == MediaType.HDDVDR) && - mediaTags.TryGetValue(MediaTagType.DVD_MediaIdentifier, out var mid)) + if((imageInfo.MediaType == MediaType.DVDR || imageInfo.MediaType == MediaType.DVDRW || + imageInfo.MediaType == MediaType.HDDVDR) && + mediaTags.TryGetValue(MediaTagType.DVD_MediaIdentifier, out byte[] mid)) { mediaTags.Remove(MediaTagType.DVD_MediaIdentifier); mediaTags.Add(MediaTagType.DVDR_MediaIdentifier, mid); } // Check for Xbox - if (mediaTags.TryGetValue(MediaTagType.DVD_DMI, out var dmi)) - if (DMI.IsXbox(dmi) || DMI.IsXbox360(dmi)) - if (DMI.IsXbox(dmi)) + if(mediaTags.TryGetValue(MediaTagType.DVD_DMI, out byte[] dmi)) + if(DMI.IsXbox(dmi) || + DMI.IsXbox360(dmi)) + if(DMI.IsXbox(dmi)) { imageInfo.MediaType = MediaType.XGD; } - else if (DMI.IsXbox360(dmi)) + else if(DMI.IsXbox360(dmi)) { imageInfo.MediaType = MediaType.XGD2; // All XGD3 all have the same number of blocks - if (imageInfo.Sectors == 25063 || // Locked (or non compatible drive) - imageInfo.Sectors == 4229664 || // Xtreme unlock - imageInfo.Sectors == 4246304) // Wxripper unlock + if(imageInfo.Sectors == 25063 || // Locked (or non compatible drive) + imageInfo.Sectors == 4229664 || // Xtreme unlock + imageInfo.Sectors == 4246304) // Wxripper unlock imageInfo.MediaType = MediaType.XGD3; } } // It's MultiMediaCard or SecureDigital - if (mediaTags.ContainsKey(MediaTagType.SD_CID) || mediaTags.ContainsKey(MediaTagType.SD_CSD) || - mediaTags.ContainsKey(MediaTagType.SD_OCR)) + if(mediaTags.ContainsKey(MediaTagType.SD_CID) || + mediaTags.ContainsKey(MediaTagType.SD_CSD) || + mediaTags.ContainsKey(MediaTagType.SD_OCR)) { imageInfo.MediaType = MediaType.SecureDigital; - if (mediaTags.ContainsKey(MediaTagType.MMC_ExtendedCSD) || !mediaTags.ContainsKey(MediaTagType.SD_SCR)) + if(mediaTags.ContainsKey(MediaTagType.MMC_ExtendedCSD) || + !mediaTags.ContainsKey(MediaTagType.SD_SCR)) { imageInfo.MediaType = MediaType.MMC; - if (mediaTags.TryGetValue(MediaTagType.SD_CID, out var cid)) + if(mediaTags.TryGetValue(MediaTagType.SD_CID, out byte[] cid)) { mediaTags.Remove(MediaTagType.SD_CID); mediaTags.Add(MediaTagType.MMC_CID, cid); } - if (mediaTags.TryGetValue(MediaTagType.SD_CSD, out var csd)) + if(mediaTags.TryGetValue(MediaTagType.SD_CSD, out byte[] csd)) { mediaTags.Remove(MediaTagType.SD_CSD); mediaTags.Add(MediaTagType.MMC_CSD, csd); } - if (mediaTags.TryGetValue(MediaTagType.SD_OCR, out var ocr)) + if(mediaTags.TryGetValue(MediaTagType.SD_OCR, out byte[] ocr)) { mediaTags.Remove(MediaTagType.SD_OCR); mediaTags.Add(MediaTagType.MMC_OCR, ocr); @@ -431,458 +488,544 @@ namespace DiscImageChef.DiscImages } // It's a compact disc - if (mediaTags.ContainsKey(MediaTagType.CD_FullTOC)) + if(mediaTags.ContainsKey(MediaTagType.CD_FullTOC)) { imageInfo.MediaType = imageInfo.Sectors > 360000 ? MediaType.DDCD : MediaType.CD; // Only CD-R and CD-RW have ATIP - if (mediaTags.TryGetValue(MediaTagType.CD_ATIP, out var atipBuf)) + if(mediaTags.TryGetValue(MediaTagType.CD_ATIP, out byte[] atipBuf)) { - var atip = ATIP.Decode(atipBuf); - if (atip.HasValue) imageInfo.MediaType = atip.Value.DiscType ? MediaType.CDRW : MediaType.CDR; + ATIP.CDATIP? atip = ATIP.Decode(atipBuf); + + if(atip.HasValue) + imageInfo.MediaType = atip.Value.DiscType ? MediaType.CDRW : MediaType.CDR; } - if (mediaTags.TryGetValue(MediaTagType.Floppy_LeadOut, out var leadout)) + if(mediaTags.TryGetValue(MediaTagType.Floppy_LeadOut, out byte[] leadout)) { mediaTags.Remove(MediaTagType.Floppy_LeadOut); mediaTags.Add(MediaTagType.CD_LeadOut, leadout); } } - switch (imageInfo.MediaType) + switch(imageInfo.MediaType) { case MediaType.ACORN_35_DS_DD: - imageInfo.Cylinders = 80; - imageInfo.Heads = 2; + imageInfo.Cylinders = 80; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 5; + break; case MediaType.ACORN_35_DS_HD: - imageInfo.Cylinders = 80; - imageInfo.Heads = 2; + imageInfo.Cylinders = 80; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 10; + break; case MediaType.ACORN_525_DS_DD: - imageInfo.Cylinders = 80; - imageInfo.Heads = 2; + imageInfo.Cylinders = 80; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 16; + break; case MediaType.ACORN_525_SS_DD_40: - imageInfo.Cylinders = 40; - imageInfo.Heads = 1; + imageInfo.Cylinders = 40; + imageInfo.Heads = 1; imageInfo.SectorsPerTrack = 16; + break; case MediaType.ACORN_525_SS_DD_80: - imageInfo.Cylinders = 80; - imageInfo.Heads = 1; + imageInfo.Cylinders = 80; + imageInfo.Heads = 1; imageInfo.SectorsPerTrack = 16; + break; case MediaType.ACORN_525_SS_SD_40: - imageInfo.Cylinders = 40; - imageInfo.Heads = 1; + imageInfo.Cylinders = 40; + imageInfo.Heads = 1; imageInfo.SectorsPerTrack = 10; + break; case MediaType.ACORN_525_SS_SD_80: - imageInfo.Cylinders = 80; - imageInfo.Heads = 1; + imageInfo.Cylinders = 80; + imageInfo.Heads = 1; imageInfo.SectorsPerTrack = 10; + break; case MediaType.Apple32DS: - imageInfo.Cylinders = 35; - imageInfo.Heads = 2; + imageInfo.Cylinders = 35; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 13; + break; case MediaType.Apple32SS: - imageInfo.Cylinders = 36; - imageInfo.Heads = 1; + imageInfo.Cylinders = 36; + imageInfo.Heads = 1; imageInfo.SectorsPerTrack = 13; + break; case MediaType.Apple33DS: - imageInfo.Cylinders = 35; - imageInfo.Heads = 2; + imageInfo.Cylinders = 35; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 16; + break; case MediaType.Apple33SS: - imageInfo.Cylinders = 35; - imageInfo.Heads = 2; + imageInfo.Cylinders = 35; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 16; + break; case MediaType.AppleSonyDS: - imageInfo.Cylinders = 80; - imageInfo.Heads = 2; + imageInfo.Cylinders = 80; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 10; + break; case MediaType.AppleSonySS: - imageInfo.Cylinders = 80; - imageInfo.Heads = 1; + imageInfo.Cylinders = 80; + imageInfo.Heads = 1; imageInfo.SectorsPerTrack = 10; + break; case MediaType.ATARI_35_DS_DD: - imageInfo.Cylinders = 80; - imageInfo.Heads = 2; + imageInfo.Cylinders = 80; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 10; + break; case MediaType.ATARI_35_DS_DD_11: - imageInfo.Cylinders = 80; - imageInfo.Heads = 2; + imageInfo.Cylinders = 80; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 11; + break; case MediaType.ATARI_35_SS_DD: - imageInfo.Cylinders = 80; - imageInfo.Heads = 1; + imageInfo.Cylinders = 80; + imageInfo.Heads = 1; imageInfo.SectorsPerTrack = 10; + break; case MediaType.ATARI_35_SS_DD_11: - imageInfo.Cylinders = 80; - imageInfo.Heads = 1; + imageInfo.Cylinders = 80; + imageInfo.Heads = 1; imageInfo.SectorsPerTrack = 11; + break; case MediaType.ATARI_525_ED: - imageInfo.Cylinders = 40; - imageInfo.Heads = 1; + imageInfo.Cylinders = 40; + imageInfo.Heads = 1; imageInfo.SectorsPerTrack = 26; + break; case MediaType.ATARI_525_SD: - imageInfo.Cylinders = 40; - imageInfo.Heads = 1; + imageInfo.Cylinders = 40; + imageInfo.Heads = 1; imageInfo.SectorsPerTrack = 18; + break; case MediaType.CBM_35_DD: - imageInfo.Cylinders = 80; - imageInfo.Heads = 2; + imageInfo.Cylinders = 80; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 10; + break; case MediaType.CBM_AMIGA_35_DD: - imageInfo.Cylinders = 80; - imageInfo.Heads = 2; + imageInfo.Cylinders = 80; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 11; + break; case MediaType.CBM_AMIGA_35_HD: - imageInfo.Cylinders = 80; - imageInfo.Heads = 2; + imageInfo.Cylinders = 80; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 22; + break; case MediaType.DMF: - imageInfo.Cylinders = 80; - imageInfo.Heads = 2; + imageInfo.Cylinders = 80; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 21; + break; case MediaType.DOS_35_DS_DD_9: - imageInfo.Cylinders = 80; - imageInfo.Heads = 2; + imageInfo.Cylinders = 80; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 9; + break; case MediaType.Apricot_35: - imageInfo.Cylinders = 70; - imageInfo.Heads = 2; + imageInfo.Cylinders = 70; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 9; + break; case MediaType.DOS_35_ED: - imageInfo.Cylinders = 80; - imageInfo.Heads = 2; + imageInfo.Cylinders = 80; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 36; + break; case MediaType.DOS_35_HD: - imageInfo.Cylinders = 80; - imageInfo.Heads = 2; + imageInfo.Cylinders = 80; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 18; + break; case MediaType.DOS_35_SS_DD_9: - imageInfo.Cylinders = 80; - imageInfo.Heads = 1; + imageInfo.Cylinders = 80; + imageInfo.Heads = 1; imageInfo.SectorsPerTrack = 9; + break; case MediaType.DOS_525_DS_DD_8: - imageInfo.Cylinders = 40; - imageInfo.Heads = 2; + imageInfo.Cylinders = 40; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 8; + break; case MediaType.DOS_525_DS_DD_9: - imageInfo.Cylinders = 40; - imageInfo.Heads = 2; + imageInfo.Cylinders = 40; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 9; + break; case MediaType.DOS_525_HD: - imageInfo.Cylinders = 80; - imageInfo.Heads = 2; + imageInfo.Cylinders = 80; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 15; + break; case MediaType.DOS_525_SS_DD_8: - imageInfo.Cylinders = 40; - imageInfo.Heads = 1; + imageInfo.Cylinders = 40; + imageInfo.Heads = 1; imageInfo.SectorsPerTrack = 8; + break; case MediaType.DOS_525_SS_DD_9: - imageInfo.Cylinders = 40; - imageInfo.Heads = 1; + imageInfo.Cylinders = 40; + imageInfo.Heads = 1; imageInfo.SectorsPerTrack = 9; + break; case MediaType.ECMA_54: - imageInfo.Cylinders = 77; - imageInfo.Heads = 1; + imageInfo.Cylinders = 77; + imageInfo.Heads = 1; imageInfo.SectorsPerTrack = 26; + break; case MediaType.ECMA_59: - imageInfo.Cylinders = 77; - imageInfo.Heads = 2; + imageInfo.Cylinders = 77; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 26; + break; case MediaType.ECMA_66: - imageInfo.Cylinders = 35; - imageInfo.Heads = 1; + imageInfo.Cylinders = 35; + imageInfo.Heads = 1; imageInfo.SectorsPerTrack = 9; + break; case MediaType.ECMA_69_8: - imageInfo.Cylinders = 77; - imageInfo.Heads = 2; + imageInfo.Cylinders = 77; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 8; + break; case MediaType.ECMA_70: - imageInfo.Cylinders = 40; - imageInfo.Heads = 2; + imageInfo.Cylinders = 40; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 16; + break; case MediaType.ECMA_78: - imageInfo.Cylinders = 80; - imageInfo.Heads = 2; + imageInfo.Cylinders = 80; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 16; + break; case MediaType.ECMA_99_15: - imageInfo.Cylinders = 77; - imageInfo.Heads = 2; + imageInfo.Cylinders = 77; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 15; + break; case MediaType.ECMA_99_26: - imageInfo.Cylinders = 77; - imageInfo.Heads = 2; + imageInfo.Cylinders = 77; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 26; + break; case MediaType.ECMA_99_8: - imageInfo.Cylinders = 80; - imageInfo.Heads = 2; + imageInfo.Cylinders = 80; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 8; + break; case MediaType.FDFORMAT_35_DD: - imageInfo.Cylinders = 82; - imageInfo.Heads = 2; + imageInfo.Cylinders = 82; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 10; + break; case MediaType.FDFORMAT_35_HD: - imageInfo.Cylinders = 82; - imageInfo.Heads = 2; + imageInfo.Cylinders = 82; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 21; + break; case MediaType.FDFORMAT_525_HD: - imageInfo.Cylinders = 82; - imageInfo.Heads = 2; + imageInfo.Cylinders = 82; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 17; + break; case MediaType.IBM23FD: - imageInfo.Cylinders = 32; - imageInfo.Heads = 1; + imageInfo.Cylinders = 32; + imageInfo.Heads = 1; imageInfo.SectorsPerTrack = 8; + break; case MediaType.IBM33FD_128: - imageInfo.Cylinders = 73; - imageInfo.Heads = 1; + imageInfo.Cylinders = 73; + imageInfo.Heads = 1; imageInfo.SectorsPerTrack = 26; + break; case MediaType.IBM33FD_256: - imageInfo.Cylinders = 74; - imageInfo.Heads = 1; + imageInfo.Cylinders = 74; + imageInfo.Heads = 1; imageInfo.SectorsPerTrack = 15; + break; case MediaType.IBM33FD_512: - imageInfo.Cylinders = 74; - imageInfo.Heads = 1; + imageInfo.Cylinders = 74; + imageInfo.Heads = 1; imageInfo.SectorsPerTrack = 8; + break; case MediaType.IBM43FD_128: - imageInfo.Cylinders = 74; - imageInfo.Heads = 2; + imageInfo.Cylinders = 74; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 26; + break; case MediaType.IBM43FD_256: - imageInfo.Cylinders = 74; - imageInfo.Heads = 2; + imageInfo.Cylinders = 74; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 15; + break; case MediaType.IBM53FD_1024: - imageInfo.Cylinders = 74; - imageInfo.Heads = 2; + imageInfo.Cylinders = 74; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 8; + break; case MediaType.IBM53FD_256: - imageInfo.Cylinders = 74; - imageInfo.Heads = 2; + imageInfo.Cylinders = 74; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 26; + break; case MediaType.IBM53FD_512: - imageInfo.Cylinders = 74; - imageInfo.Heads = 2; + imageInfo.Cylinders = 74; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 15; + break; case MediaType.NEC_35_TD: - imageInfo.Cylinders = 240; - imageInfo.Heads = 2; + imageInfo.Cylinders = 240; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 38; + break; case MediaType.NEC_525_HD: - imageInfo.Cylinders = 77; - imageInfo.Heads = 2; + imageInfo.Cylinders = 77; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 8; + break; case MediaType.XDF_35: - imageInfo.Cylinders = 80; - imageInfo.Heads = 2; + imageInfo.Cylinders = 80; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 23; + break; + // Following ones are what the device itself report, not the physical geometry case MediaType.Jaz: - imageInfo.Cylinders = 1021; - imageInfo.Heads = 64; + imageInfo.Cylinders = 1021; + imageInfo.Heads = 64; imageInfo.SectorsPerTrack = 32; + break; case MediaType.PocketZip: - imageInfo.Cylinders = 154; - imageInfo.Heads = 16; + imageInfo.Cylinders = 154; + imageInfo.Heads = 16; imageInfo.SectorsPerTrack = 32; + break; case MediaType.LS120: - imageInfo.Cylinders = 963; - imageInfo.Heads = 8; + imageInfo.Cylinders = 963; + imageInfo.Heads = 8; imageInfo.SectorsPerTrack = 32; + break; case MediaType.LS240: - imageInfo.Cylinders = 262; - imageInfo.Heads = 32; + imageInfo.Cylinders = 262; + imageInfo.Heads = 32; imageInfo.SectorsPerTrack = 56; + break; case MediaType.FD32MB: - imageInfo.Cylinders = 1024; - imageInfo.Heads = 2; + imageInfo.Cylinders = 1024; + imageInfo.Heads = 2; imageInfo.SectorsPerTrack = 32; + break; case MediaType.ZIP100: - imageInfo.Cylinders = 96; - imageInfo.Heads = 64; + imageInfo.Cylinders = 96; + imageInfo.Heads = 64; imageInfo.SectorsPerTrack = 32; + break; case MediaType.ZIP250: - imageInfo.Cylinders = 239; - imageInfo.Heads = 64; + imageInfo.Cylinders = 239; + imageInfo.Heads = 64; imageInfo.SectorsPerTrack = 32; + break; default: - imageInfo.Cylinders = (uint) (imageInfo.Sectors / 16 / 63); - imageInfo.Heads = 16; + imageInfo.Cylinders = (uint)(imageInfo.Sectors / 16 / 63); + imageInfo.Heads = 16; imageInfo.SectorsPerTrack = 63; + break; } // It's SCSI, check tags - if (mediaTags.ContainsKey(MediaTagType.SCSI_INQUIRY)) + if(mediaTags.ContainsKey(MediaTagType.SCSI_INQUIRY)) { - var devType = PeripheralDeviceTypes.DirectAccess; - Inquiry? scsiInq = null; - if (mediaTags.TryGetValue(MediaTagType.SCSI_INQUIRY, out var inq)) + PeripheralDeviceTypes devType = PeripheralDeviceTypes.DirectAccess; + Inquiry? scsiInq = null; + + if(mediaTags.TryGetValue(MediaTagType.SCSI_INQUIRY, out byte[] inq)) { scsiInq = Inquiry.Decode(inq); - devType = (PeripheralDeviceTypes) (inq[0] & 0x1F); + devType = (PeripheralDeviceTypes)(inq[0] & 0x1F); } Modes.DecodedMode? decMode = null; - if (mediaTags.TryGetValue(MediaTagType.SCSI_MODESENSE_6, out var mode6)) + if(mediaTags.TryGetValue(MediaTagType.SCSI_MODESENSE_6, out byte[] mode6)) decMode = Modes.DecodeMode6(mode6, devType); - else if (mediaTags.TryGetValue(MediaTagType.SCSI_MODESENSE_10, out var mode10)) + else if(mediaTags.TryGetValue(MediaTagType.SCSI_MODESENSE_10, out byte[] mode10)) decMode = Modes.DecodeMode10(mode10, devType); - byte mediumType = 0; + byte mediumType = 0; byte densityCode = 0; - if (decMode.HasValue) + if(decMode.HasValue) { - mediumType = (byte) decMode.Value.Header.MediumType; - if (decMode.Value.Header.BlockDescriptors != null && - decMode.Value.Header.BlockDescriptors.Length >= 1) - densityCode = (byte) decMode.Value.Header.BlockDescriptors[0].Density; + mediumType = (byte)decMode.Value.Header.MediumType; + + if(decMode.Value.Header.BlockDescriptors != null && + decMode.Value.Header.BlockDescriptors.Length >= 1) + densityCode = (byte)decMode.Value.Header.BlockDescriptors[0].Density; + + if(decMode.Value.Pages != null) + foreach(Modes.ModePage page in decMode.Value.Pages) - if (decMode.Value.Pages != null) - foreach (var page in decMode.Value.Pages) // CD-ROM page - if (page.Page == 0x2A && page.Subpage == 0) + if(page.Page == 0x2A && + page.Subpage == 0) { - if (mediaTags.ContainsKey(MediaTagType.SCSI_MODEPAGE_2A)) + if(mediaTags.ContainsKey(MediaTagType.SCSI_MODEPAGE_2A)) mediaTags.Remove(MediaTagType.SCSI_MODEPAGE_2A); + mediaTags.Add(MediaTagType.SCSI_MODEPAGE_2A, page.PageResponse); } + // Rigid Disk page - else if (page.Page == 0x04 && page.Subpage == 0) + else if(page.Page == 0x04 && + page.Subpage == 0) { - var mode04 = Modes.DecodeModePage_04(page.PageResponse); - if (!mode04.HasValue) continue; + Modes.ModePage_04? mode04 = Modes.DecodeModePage_04(page.PageResponse); + + if(!mode04.HasValue) + continue; imageInfo.Cylinders = mode04.Value.Cylinders; - imageInfo.Heads = mode04.Value.Heads; - imageInfo.SectorsPerTrack = - (uint) (imageInfo.Sectors / (mode04.Value.Cylinders * mode04.Value.Heads)); - } - // Flexible Disk Page - else if (page.Page == 0x05 && page.Subpage == 0) - { - var mode05 = Modes.DecodeModePage_05(page.PageResponse); - if (!mode05.HasValue) continue; + imageInfo.Heads = mode04.Value.Heads; - imageInfo.Cylinders = mode05.Value.Cylinders; - imageInfo.Heads = mode05.Value.Heads; + imageInfo.SectorsPerTrack = + (uint)(imageInfo.Sectors / (mode04.Value.Cylinders * mode04.Value.Heads)); + } + + // Flexible Disk Page + else if(page.Page == 0x05 && + page.Subpage == 0) + { + Modes.ModePage_05? mode05 = Modes.DecodeModePage_05(page.PageResponse); + + if(!mode05.HasValue) + continue; + + imageInfo.Cylinders = mode05.Value.Cylinders; + imageInfo.Heads = mode05.Value.Heads; imageInfo.SectorsPerTrack = mode05.Value.SectorsPerTrack; } } - if (scsiInq.HasValue) + if(scsiInq.HasValue) { imageInfo.DriveManufacturer = VendorString.Prettify(StringHandlers.CToString(scsiInq.Value.VendorIdentification).Trim()); + imageInfo.DriveModel = StringHandlers.CToString(scsiInq.Value.ProductIdentification).Trim(); + imageInfo.DriveFirmwareRevision = StringHandlers.CToString(scsiInq.Value.ProductRevisionLevel).Trim(); - imageInfo.MediaType = MediaTypeFromScsi.Get((byte) devType, imageInfo.DriveManufacturer, - imageInfo.DriveModel, mediumType, densityCode, - imageInfo.Sectors, imageInfo.SectorSize); + + imageInfo.MediaType = MediaTypeFromScsi.Get((byte)devType, imageInfo.DriveManufacturer, + imageInfo.DriveModel, mediumType, densityCode, + imageInfo.Sectors, imageInfo.SectorSize); } - if (imageInfo.MediaType == MediaType.Unknown) - imageInfo.MediaType = devType == PeripheralDeviceTypes.OpticalDevice - ? MediaType.UnknownMO - : MediaType.GENERIC_HDD; + if(imageInfo.MediaType == MediaType.Unknown) + imageInfo.MediaType = devType == PeripheralDeviceTypes.OpticalDevice ? MediaType.UnknownMO + : MediaType.GENERIC_HDD; } // It's ATA, check tags - if (mediaTags.TryGetValue(MediaTagType.ATA_IDENTIFY, out var identifyBuf)) + if(mediaTags.TryGetValue(MediaTagType.ATA_IDENTIFY, out byte[] identifyBuf)) { - var ataId = CommonTypes.Structs.Devices.ATA.Identify.Decode(identifyBuf); - if (ataId.HasValue) - { - imageInfo.MediaType = (ushort) ataId.Value.GeneralConfiguration == 0x848A - ? MediaType.CompactFlash - : MediaType.GENERIC_HDD; + Identify.IdentifyDevice? ataId = CommonTypes.Structs.Devices.ATA.Identify.Decode(identifyBuf); - if (ataId.Value.Cylinders == 0 || ataId.Value.Heads == 0 || ataId.Value.SectorsPerTrack == 0) + if(ataId.HasValue) + { + imageInfo.MediaType = (ushort)ataId.Value.GeneralConfiguration == 0x848A ? MediaType.CompactFlash + : MediaType.GENERIC_HDD; + + if(ataId.Value.Cylinders == 0 || + ataId.Value.Heads == 0 || + ataId.Value.SectorsPerTrack == 0) { - imageInfo.Cylinders = ataId.Value.CurrentCylinders; - imageInfo.Heads = ataId.Value.CurrentHeads; + imageInfo.Cylinders = ataId.Value.CurrentCylinders; + imageInfo.Heads = ataId.Value.CurrentHeads; imageInfo.SectorsPerTrack = ataId.Value.CurrentSectorsPerTrack; } else { - imageInfo.Cylinders = ataId.Value.Cylinders; - imageInfo.Heads = ataId.Value.Heads; + imageInfo.Cylinders = ataId.Value.Cylinders; + imageInfo.Heads = ataId.Value.Heads; imageInfo.SectorsPerTrack = ataId.Value.SectorsPerTrack; } } } - switch (imageInfo.MediaType) + switch(imageInfo.MediaType) { case MediaType.CD: case MediaType.CDRW: @@ -914,26 +1057,29 @@ namespace DiscImageChef.DiscImages case MediaType.PD650: case MediaType.PD650_WORM: imageInfo.XmlMediaType = XmlMediaType.OpticalDisc; + break; default: imageInfo.XmlMediaType = XmlMediaType.BlockMedia; + break; } - if (imageInfo.XmlMediaType == XmlMediaType.OpticalDisc) + if(imageInfo.XmlMediaType == XmlMediaType.OpticalDisc) { - imageInfo.HasSessions = true; + imageInfo.HasSessions = true; imageInfo.HasPartitions = true; } DicConsole.VerboseWriteLine("Raw disk image contains a disk of type {0}", imageInfo.MediaType); var sidecarXs = new XmlSerializer(typeof(CICMMetadataType)); - if (File.Exists(basename + "cicm.xml")) + + if(File.Exists(basename + "cicm.xml")) try { var sr = new StreamReader(basename + "cicm.xml"); - CicmMetadata = (CICMMetadataType) sidecarXs.Deserialize(sr); + CicmMetadata = (CICMMetadataType)sidecarXs.Deserialize(sr); sr.Close(); } catch @@ -943,84 +1089,112 @@ namespace DiscImageChef.DiscImages imageInfo.ReadableMediaTags = new List(mediaTags.Keys); - if (!rawCompactDisc) return true; + if(!rawCompactDisc) + return true; - if (hasSubchannel) - if (!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel)) + if(hasSubchannel) + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel); - if (mode2) + if(mode2) { - if (!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); - if (!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) + + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); - if (!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) + + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); - if (!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) + + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); } else { - if (!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); - if (!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) + + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); - if (!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) + + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); - if (!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc)) + + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc); - if (!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP)) + + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP); - if (!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ)) + + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ); - if (!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) + + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); } return true; } - public byte[] ReadSector(ulong sectorAddress) - { - return ReadSectors(sectorAddress, 1); - } + public byte[] ReadSector(ulong sectorAddress) => ReadSectors(sectorAddress, 1); public byte[] ReadSectors(ulong sectorAddress, uint length) { - if (differentTrackZeroSize) throw new NotImplementedException("Not yet implemented"); + if(differentTrackZeroSize) + throw new NotImplementedException("Not yet implemented"); - if (sectorAddress > imageInfo.Sectors - 1) + if(sectorAddress > imageInfo.Sectors - 1) throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found"); - if (sectorAddress + length > imageInfo.Sectors) + if(sectorAddress + length > imageInfo.Sectors) throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available"); - var stream = rawImageFilter.GetDataForkStream(); + Stream stream = rawImageFilter.GetDataForkStream(); uint sectorOffset = 0; - var sectorSize = imageInfo.SectorSize; - uint sectorSkip = 0; + uint sectorSize = imageInfo.SectorSize; + uint sectorSkip = 0; - if (rawCompactDisc) + if(rawCompactDisc) { - sectorOffset = 16; - sectorSize = (uint) (mode2 ? 2336 : 2048); - sectorSkip = (uint) (mode2 ? 0 : 288); + sectorOffset = (uint)(mode2 ? 0 : 16); + sectorSize = (uint)(mode2 ? 2352 : 2048); + sectorSkip = (uint)(mode2 ? 0 : 288); } - if (hasSubchannel) sectorSkip += 96; + if(hasSubchannel) + sectorSkip += 96; - var buffer = new byte[sectorSize * length]; + byte[] buffer = new byte[sectorSize * length]; var br = new BinaryReader(stream); - br.BaseStream.Seek((long) (sectorAddress * (sectorOffset + sectorSize + sectorSkip)), SeekOrigin.Begin); - if (sectorOffset == 0 && sectorSkip == 0) buffer = br.ReadBytes((int) (sectorSize * length)); + br.BaseStream.Seek((long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), SeekOrigin.Begin); + + if(mode2) + { + var mode2Ms = new MemoryStream((int)(sectorSize * length)); + + buffer = br.ReadBytes((int)((sectorSize + sectorSkip) * length)); + + for(int i = 0; i < length; i++) + { + byte[] sector = new byte[sectorSize]; + Array.Copy(buffer, (sectorSize + sectorSkip) * i, sector, 0, sectorSize); + sector = Sector.GetUserDataFromMode2(sector); + mode2Ms.Write(sector, 0, sector.Length); + } + + buffer = mode2Ms.ToArray(); + } + else if(sectorOffset == 0 && + sectorSkip == 0) + buffer = br.ReadBytes((int)(sectorSize * length)); else - for (var i = 0; i < length; i++) + for(int i = 0; i < length; i++) { br.BaseStream.Seek(sectorOffset, SeekOrigin.Current); - var sector = br.ReadBytes((int) sectorSize); + byte[] sector = br.ReadBytes((int)sectorSize); br.BaseStream.Seek(sectorSkip, SeekOrigin.Current); Array.Copy(sector, 0, buffer, i * sectorSize, sectorSize); } @@ -1030,101 +1204,108 @@ namespace DiscImageChef.DiscImages public List GetSessionTracks(Session session) { - if (imageInfo.XmlMediaType != XmlMediaType.OpticalDisc) + if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc) throw new FeatureUnsupportedImageException("Feature not supported by image format"); - if (session.SessionSequence != 1) + if(session.SessionSequence != 1) throw new ArgumentOutOfRangeException(nameof(session), "Only a single session is supported"); var trk = new Track { - TrackBytesPerSector = (int) imageInfo.SectorSize, - TrackEndSector = imageInfo.Sectors - 1, - TrackFilter = rawImageFilter, - TrackFile = rawImageFilter.GetFilename(), - TrackFileOffset = 0, - TrackFileType = "BINARY", - TrackRawBytesPerSector = (int) imageInfo.SectorSize, - TrackSequence = 1, - TrackStartSector = 0, - TrackSubchannelType = TrackSubchannelType.None, - TrackType = TrackType.Data, - TrackSession = 1 + TrackBytesPerSector = (int)imageInfo.SectorSize, TrackEndSector = imageInfo.Sectors - 1, + TrackFilter = rawImageFilter, TrackFile = rawImageFilter.GetFilename(), + TrackFileOffset = 0, + TrackFileType = "BINARY", TrackRawBytesPerSector = (int)imageInfo.SectorSize, + TrackSequence = 1, + TrackStartSector = 0, TrackSubchannelType = TrackSubchannelType.None, + TrackType = TrackType.Data, + TrackSession = 1 }; - var lst = new List {trk}; + + List lst = new List + { + trk + }; + return lst; } public List GetSessionTracks(ushort session) { - if (imageInfo.XmlMediaType != XmlMediaType.OpticalDisc) + if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc) throw new FeatureUnsupportedImageException("Feature not supported by image format"); - if (session != 1) + if(session != 1) throw new ArgumentOutOfRangeException(nameof(session), "Only a single session is supported"); var trk = new Track { - TrackBytesPerSector = (int) imageInfo.SectorSize, - TrackEndSector = imageInfo.Sectors - 1, - TrackFilter = rawImageFilter, - TrackFile = rawImageFilter.GetFilename(), - TrackFileOffset = 0, - TrackFileType = "BINARY", - TrackRawBytesPerSector = (int) imageInfo.SectorSize, - TrackSequence = 1, - TrackStartSector = 0, - TrackSubchannelType = TrackSubchannelType.None, - TrackType = TrackType.Data, - TrackSession = 1 + TrackBytesPerSector = (int)imageInfo.SectorSize, TrackEndSector = imageInfo.Sectors - 1, + TrackFilter = rawImageFilter, TrackFile = rawImageFilter.GetFilename(), + TrackFileOffset = 0, + TrackFileType = "BINARY", TrackRawBytesPerSector = (int)imageInfo.SectorSize, + TrackSequence = 1, + TrackStartSector = 0, TrackSubchannelType = TrackSubchannelType.None, + TrackType = TrackType.Data, + TrackSession = 1 }; - var lst = new List {trk}; + + List lst = new List + { + trk + }; + return lst; } public byte[] ReadSector(ulong sectorAddress, uint track) { - if (imageInfo.XmlMediaType != XmlMediaType.OpticalDisc) + if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc) throw new FeatureUnsupportedImageException("Feature not supported by image format"); - if (track != 1) throw new ArgumentOutOfRangeException(nameof(track), "Only a single track is supported"); + if(track != 1) + throw new ArgumentOutOfRangeException(nameof(track), "Only a single track is supported"); return ReadSector(sectorAddress); } public byte[] ReadSectors(ulong sectorAddress, uint length, uint track) { - if (imageInfo.XmlMediaType != XmlMediaType.OpticalDisc) + if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc) throw new FeatureUnsupportedImageException("Feature not supported by image format"); - if (track != 1) throw new ArgumentOutOfRangeException(nameof(track), "Only a single track is supported"); + if(track != 1) + throw new ArgumentOutOfRangeException(nameof(track), "Only a single track is supported"); return ReadSectors(sectorAddress, length); } public byte[] ReadSectorLong(ulong sectorAddress, uint track) { - if (imageInfo.XmlMediaType != XmlMediaType.OpticalDisc) + if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc) throw new FeatureUnsupportedImageException("Feature not supported by image format"); - if (track != 1) throw new ArgumentOutOfRangeException(nameof(track), "Only a single track is supported"); + if(track != 1) + throw new ArgumentOutOfRangeException(nameof(track), "Only a single track is supported"); return ReadSectorsLong(sectorAddress, 1); } public byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) { - if (imageInfo.XmlMediaType != XmlMediaType.OpticalDisc) + if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc) throw new FeatureUnsupportedImageException("Feature not supported by image format"); - if (track != 1) throw new ArgumentOutOfRangeException(nameof(track), "Only a single track is supported"); + if(track != 1) + throw new ArgumentOutOfRangeException(nameof(track), "Only a single track is supported"); return ReadSectorsLong(sectorAddress, length); } public byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag) { - if (imageInfo.XmlMediaType != XmlMediaType.OpticalDisc || !rawCompactDisc) + if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc || + !rawCompactDisc) throw new FeatureUnsupportedImageException("Feature not supported by image format"); return ReadSectorsTag(sectorAddress, 1, tag); @@ -1132,55 +1313,60 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) { - if (imageInfo.XmlMediaType != XmlMediaType.OpticalDisc || !rawCompactDisc) + if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc || + !rawCompactDisc) throw new FeatureUnsupportedImageException("Feature not supported by image format"); - if (sectorAddress > imageInfo.Sectors - 1) + if(sectorAddress > imageInfo.Sectors - 1) throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found"); - if (sectorAddress + length > imageInfo.Sectors) + if(sectorAddress + length > imageInfo.Sectors) throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available"); uint sectorOffset; uint sectorSize; uint sectorSkip = 0; - if (!hasSubchannel && tag == SectorTagType.CdSectorSubchannel) + if(!hasSubchannel && + tag == SectorTagType.CdSectorSubchannel) throw new ArgumentException("No tags in image for requested track", nameof(tag)); // Requires reading sector - if (mode2) + if(mode2) { - if (tag != SectorTagType.CdSectorSubchannel) + if(tag != SectorTagType.CdSectorSubchannel) throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented"); sectorOffset = 2352; - sectorSize = 96; + sectorSize = 96; } else { - switch (tag) + switch(tag) { case SectorTagType.CdSectorSync: { sectorOffset = 0; - sectorSize = 12; - sectorSkip = 2340; + sectorSize = 12; + sectorSkip = 2340; + break; } case SectorTagType.CdSectorHeader: { sectorOffset = 12; - sectorSize = 4; - sectorSkip = 2336; + sectorSize = 4; + sectorSkip = 2336; + break; } case SectorTagType.CdSectorSubchannel: { sectorOffset = 2352; - sectorSize = 96; + sectorSize = 96; + break; } @@ -1189,32 +1375,36 @@ namespace DiscImageChef.DiscImages case SectorTagType.CdSectorEcc: { sectorOffset = 2076; - sectorSize = 276; - sectorSkip = 0; + sectorSize = 276; + sectorSkip = 0; + break; } case SectorTagType.CdSectorEccP: { sectorOffset = 2076; - sectorSize = 172; - sectorSkip = 104; + sectorSize = 172; + sectorSkip = 104; + break; } case SectorTagType.CdSectorEccQ: { sectorOffset = 2248; - sectorSize = 104; - sectorSkip = 0; + sectorSize = 104; + sectorSkip = 0; + break; } case SectorTagType.CdSectorEdc: { sectorOffset = 2064; - sectorSize = 4; - sectorSkip = 284; + sectorSize = 4; + sectorSkip = 284; + break; } @@ -1222,17 +1412,20 @@ namespace DiscImageChef.DiscImages } } - var buffer = new byte[sectorSize * length]; + byte[] buffer = new byte[sectorSize * length]; - var stream = rawImageFilter.GetDataForkStream(); - var br = new BinaryReader(stream); - br.BaseStream.Seek((long) (sectorAddress * (sectorOffset + sectorSize + sectorSkip)), SeekOrigin.Begin); - if (sectorOffset == 0 && sectorSkip == 0) buffer = br.ReadBytes((int) (sectorSize * length)); + Stream stream = rawImageFilter.GetDataForkStream(); + var br = new BinaryReader(stream); + br.BaseStream.Seek((long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), SeekOrigin.Begin); + + if(sectorOffset == 0 && + sectorSkip == 0) + buffer = br.ReadBytes((int)(sectorSize * length)); else - for (var i = 0; i < length; i++) + for(int i = 0; i < length; i++) { br.BaseStream.Seek(sectorOffset, SeekOrigin.Current); - var sector = br.ReadBytes((int) sectorSize); + byte[] sector = br.ReadBytes((int)sectorSize); br.BaseStream.Seek(sectorSkip, SeekOrigin.Current); Array.Copy(sector, 0, buffer, i * sectorSize, sectorSize); } @@ -1240,39 +1433,39 @@ namespace DiscImageChef.DiscImages return buffer; } - public byte[] ReadSectorLong(ulong sectorAddress) - { - return ReadSectorsLong(sectorAddress, 1); - } + public byte[] ReadSectorLong(ulong sectorAddress) => ReadSectorsLong(sectorAddress, 1); public byte[] ReadSectorsLong(ulong sectorAddress, uint length) { - if (imageInfo.XmlMediaType != XmlMediaType.OpticalDisc || !rawCompactDisc) + if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc || + !rawCompactDisc) throw new FeatureUnsupportedImageException("Feature not supported by image format"); - if (sectorAddress > imageInfo.Sectors - 1) + if(sectorAddress > imageInfo.Sectors - 1) throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found"); - if (sectorAddress + length > imageInfo.Sectors) + if(sectorAddress + length > imageInfo.Sectors) throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available"); const uint SECTOR_SIZE = 2352; - uint sectorSkip = 0; + uint sectorSkip = 0; - if (hasSubchannel) sectorSkip += 96; + if(hasSubchannel) + sectorSkip += 96; - var buffer = new byte[SECTOR_SIZE * length]; + byte[] buffer = new byte[SECTOR_SIZE * length]; - var stream = rawImageFilter.GetDataForkStream(); - var br = new BinaryReader(stream); + Stream stream = rawImageFilter.GetDataForkStream(); + var br = new BinaryReader(stream); - br.BaseStream.Seek((long) (sectorAddress * (SECTOR_SIZE + sectorSkip)), SeekOrigin.Begin); + br.BaseStream.Seek((long)(sectorAddress * (SECTOR_SIZE + sectorSkip)), SeekOrigin.Begin); - if (sectorSkip == 0) buffer = br.ReadBytes((int) (SECTOR_SIZE * length)); + if(sectorSkip == 0) + buffer = br.ReadBytes((int)(SECTOR_SIZE * length)); else - for (var i = 0; i < length; i++) + for(int i = 0; i < length; i++) { - var sector = br.ReadBytes((int) SECTOR_SIZE); + byte[] sector = br.ReadBytes((int)SECTOR_SIZE); br.BaseStream.Seek(sectorSkip, SeekOrigin.Current); Array.Copy(sector, 0, buffer, i * SECTOR_SIZE, SECTOR_SIZE); @@ -1283,27 +1476,32 @@ namespace DiscImageChef.DiscImages public byte[] ReadDiskTag(MediaTagType tag) { - if (mediaTags.TryGetValue(tag, out var data)) return data; + if(mediaTags.TryGetValue(tag, out byte[] data)) + return data; throw new FeatureNotPresentImageException("Requested tag is not present in image"); } public byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag) { - if (imageInfo.XmlMediaType != XmlMediaType.OpticalDisc || !rawCompactDisc) + if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc || + !rawCompactDisc) throw new FeatureUnsupportedImageException("Feature not supported by image format"); - if (track != 1) throw new ArgumentOutOfRangeException(nameof(track), "Only a single track is supported"); + if(track != 1) + throw new ArgumentOutOfRangeException(nameof(track), "Only a single track is supported"); return ReadSectorsTag(sectorAddress, 1, track, tag); } public byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) { - if (imageInfo.XmlMediaType != XmlMediaType.OpticalDisc || !rawCompactDisc) + if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc || + !rawCompactDisc) throw new FeatureUnsupportedImageException("Feature not supported by image format"); - if (track != 1) throw new ArgumentOutOfRangeException(nameof(track), "Only a single track is supported"); + if(track != 1) + throw new ArgumentOutOfRangeException(nameof(track), "Only a single track is supported"); return ReadSectorsTag(sectorAddress, length, tag); }