diff --git a/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs b/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs index 23452c534..7fb941e73 100644 --- a/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs +++ b/DiscImageChef.Core/Devices/Dumping/CompactDisc.cs @@ -71,17 +71,17 @@ namespace DiscImageChef.Core.Devices.Dumping { /// Dumps a compact disc /// Disc type as detected in MMC layer - internal void CompactDisc(ref MediaType dskType) + void CompactDisc(out MediaType dskType) { DicContext ctx; // Master database context Device dbDev; // Device database entry CdOffset cdOffset; // Read offset from database bool readcd; // Device supports READ CD - bool read6 = false; // Device supports READ(6) - bool read10 = false; // Device supports READ(10) - bool read12 = false; // Device supports READ(12) - bool read16 = false; // Device supports READ(16) - const uint SECTOR_SIZE = 2352; // Full sector size + bool read6 = false; // Device supports READ(6) + bool read10 = false; // Device supports READ(10) + bool read12 = false; // Device supports READ(12) + bool read16 = false; // Device supports READ(16) + const uint sectorSize = 2352; // Full sector size MmcSubchannel supportedSubchannel; // Drive's maximum supported subchannel uint subSize; // Subchannel size in bytes bool sense; // Sense indicator @@ -104,13 +104,13 @@ namespace DiscImageChef.Core.Devices.Dumping bool supportsLongSectors = true; DumpHardwareType currentTry = null; ExtentsULong extents = null; - DateTime timeSpeedStart = DateTime.UtcNow; - ulong sectorSpeedStart = 0; - double totalDuration = 0; - double currentSpeed = 0; - double maxSpeed = double.MinValue; - double minSpeed = double.MaxValue; - uint blocksToRead = 64; + DateTime timeSpeedStart; + ulong sectorSpeedStart = 0; + double totalDuration = 0; + double currentSpeed = 0; + double maxSpeed = double.MinValue; + double minSpeed = double.MaxValue; + uint blocksToRead = 64; bool ret; double imageWriteDuration = 0; bool newTrim = false; @@ -119,6 +119,7 @@ namespace DiscImageChef.Core.Devices.Dumping DateTime start; DateTime dumpStart = DateTime.UtcNow; DateTime end; + double cmdDuration = 0; Dictionary mediaTags = new Dictionary(); // Media tags @@ -173,9 +174,9 @@ namespace DiscImageChef.Core.Devices.Dumping dumpLog.WriteLine("Checking if drive supports full raw subchannel reading..."); UpdateStatus?.Invoke("Checking if drive supports full raw subchannel reading..."); - readcd = !dev.ReadCd(out cmdBuf, out senseBuf, 0, SECTOR_SIZE + 96, 1, MmcSectorTypes.AllTypes, false, - false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, - supportedSubchannel, dev.Timeout, out _); + readcd = !dev.ReadCd(out cmdBuf, out senseBuf, 0, sectorSize + 96, 1, MmcSectorTypes.AllTypes, false, false, + true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, supportedSubchannel, + dev.Timeout, out _); if(readcd) { @@ -189,7 +190,7 @@ namespace DiscImageChef.Core.Devices.Dumping dumpLog.WriteLine("Checking if drive supports PQ subchannel reading..."); UpdateStatus?.Invoke("Checking if drive supports PQ subchannel reading..."); - readcd = !dev.ReadCd(out cmdBuf, out senseBuf, 0, SECTOR_SIZE + 16, 1, MmcSectorTypes.AllTypes, false, + readcd = !dev.ReadCd(out cmdBuf, out senseBuf, 0, sectorSize + 16, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, supportedSubchannel, dev.Timeout, out _); @@ -210,7 +211,7 @@ namespace DiscImageChef.Core.Devices.Dumping dumpLog.WriteLine("Checking if drive supports reading without subchannel..."); UpdateStatus?.Invoke("Checking if drive supports reading without subchannel..."); - readcd = !dev.ReadCd(out cmdBuf, out senseBuf, 0, SECTOR_SIZE, 1, MmcSectorTypes.AllTypes, false, + readcd = !dev.ReadCd(out cmdBuf, out senseBuf, 0, sectorSize, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, supportedSubchannel, dev.Timeout, out _); @@ -308,7 +309,7 @@ namespace DiscImageChef.Core.Devices.Dumping subSize = 0; } - blockSize = SECTOR_SIZE + subSize; + blockSize = sectorSize + subSize; switch(supportedSubchannel) { @@ -372,8 +373,8 @@ namespace DiscImageChef.Core.Devices.Dumping TrackStartSector = (ulong)(((trk.PHOUR * 3600 * 75) + (trk.PMIN * 60 * 75) + (trk.PSEC * 75) + trk.PFRAME) - 150), - TrackBytesPerSector = (int)SECTOR_SIZE, - TrackRawBytesPerSector = (int)SECTOR_SIZE, + TrackBytesPerSector = (int)sectorSize, + TrackRawBytesPerSector = (int)sectorSize, TrackSubchannelType = subType }); @@ -474,8 +475,8 @@ namespace DiscImageChef.Core.Devices.Dumping TrackType = (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrack || (TocControl)(trk.CONTROL & 0x0D) == TocControl.DataTrackIncremental ? TrackType.Data : TrackType.Audio, - TrackStartSector = trk.TrackStartAddress, TrackBytesPerSector = (int)SECTOR_SIZE, - TrackRawBytesPerSector = (int)SECTOR_SIZE, TrackSubchannelType = subType + TrackStartSector = trk.TrackStartAddress, TrackBytesPerSector = (int)sectorSize, + TrackRawBytesPerSector = (int)sectorSize, TrackSubchannelType = subType }); trackFlags.Add(trk.TrackNumber, trk.CONTROL); @@ -500,7 +501,7 @@ namespace DiscImageChef.Core.Devices.Dumping { TrackSequence = 1, TrackSession = 1, TrackType = firstTrackType, TrackStartSector = 0, - TrackBytesPerSector = (int)SECTOR_SIZE, TrackRawBytesPerSector = (int)SECTOR_SIZE, + TrackBytesPerSector = (int)sectorSize, TrackRawBytesPerSector = (int)sectorSize, TrackSubchannelType = subType }); @@ -764,8 +765,8 @@ namespace DiscImageChef.Core.Devices.Dumping TrackSession = 1, TrackType = hiddenData ? TrackType.Data : TrackType.Audio, TrackStartSector = 0, - TrackBytesPerSector = (int)SECTOR_SIZE, - TrackRawBytesPerSector = (int)SECTOR_SIZE, + TrackBytesPerSector = (int)sectorSize, + TrackRawBytesPerSector = (int)sectorSize, TrackSubchannelType = subType, TrackEndSector = tracks.First(t => t.TrackSequence == 1).TrackStartSector - 1 } @@ -1043,8 +1044,7 @@ namespace DiscImageChef.Core.Devices.Dumping sense = dev.ReadCd(out cmdBuf, out senseBuf, (uint)firstTrackPregapBlock, blockSize, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, - true, MmcErrorField.None, supportedSubchannel, dev.Timeout, - out double cmdDuration); + true, MmcErrorField.None, supportedSubchannel, dev.Timeout, out cmdDuration); if(!sense && !dev.Error) @@ -1052,6 +1052,7 @@ namespace DiscImageChef.Core.Devices.Dumping firstTrackPregapMs.Write(cmdBuf, 0, (int)blockSize); gotFirstTrackPregap = true; firstTrackPregapSectorsGood++; + totalDuration += cmdDuration; } else { @@ -1164,7 +1165,7 @@ namespace DiscImageChef.Core.Devices.Dumping outputPlugin.ErrorMessage); } - // Send tracklist to output plugin. This may fail if subchannel is set but unsupported. + // Send track list to output plugin. This may fail if subchannel is set but unsupported. ret = (outputPlugin as IWritableOpticalImage).SetTracks(tracks.ToList()); if(!ret && @@ -1188,7 +1189,7 @@ namespace DiscImageChef.Core.Devices.Dumping out _); tmpBuf = new byte[subSize]; - Array.Copy(cmdBuf, SECTOR_SIZE, tmpBuf, 0, subSize); + Array.Copy(cmdBuf, sectorSize, tmpBuf, 0, subSize); ret = outputPlugin.WriteSectorTag(tmpBuf, 0, SectorTagType.CdSectorSubchannel); @@ -1216,7 +1217,7 @@ namespace DiscImageChef.Core.Devices.Dumping supportedSubchannel = MmcSubchannel.None; subSize = 0; - blockSize = SECTOR_SIZE + subSize; + blockSize = sectorSize + subSize; for(int t = 0; t < tracks.Length; t++) tracks[t].TrackSubchannelType = TrackSubchannelType.None; @@ -1328,13 +1329,14 @@ namespace DiscImageChef.Core.Devices.Dumping break; } - ulong ui = (ulong)i; - double cmdDuration = 0; + ulong ui = (ulong)i; if((lastSector + 1) - i < blocksToRead) blocksToRead = (uint)((lastSector + 1) - i); #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator + + // ReSharper disable CompareOfFloatsByEqualityOperator if(currentSpeed > maxSpeed && currentSpeed != 0) maxSpeed = currentSpeed; @@ -1344,9 +1346,9 @@ namespace DiscImageChef.Core.Devices.Dumping minSpeed = currentSpeed; #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator - UpdateProgress?. - Invoke(string.Format("Reading sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed), i, - (long)blocks); + // ReSharper restore CompareOfFloatsByEqualityOperator + + UpdateProgress?.Invoke($"Reading sector {i} of {blocks} ({currentSpeed:F3} MiB/sec.)", i, (long)blocks); if(readcd) { @@ -1387,14 +1389,14 @@ namespace DiscImageChef.Core.Devices.Dumping if(supportedSubchannel != MmcSubchannel.None) { - byte[] data = new byte[SECTOR_SIZE * blocksToRead]; - byte[] sub = new byte[subSize * blocksToRead]; + byte[] data = new byte[sectorSize * blocksToRead]; + byte[] sub = new byte[subSize * blocksToRead]; for(int b = 0; b < blocksToRead; b++) { - Array.Copy(cmdBuf, (int)(0 + (b * blockSize)), data, SECTOR_SIZE * b, SECTOR_SIZE); + Array.Copy(cmdBuf, (int)(0 + (b * blockSize)), data, sectorSize * b, sectorSize); - Array.Copy(cmdBuf, (int)(SECTOR_SIZE + (b * blockSize)), sub, subSize * b, subSize); + Array.Copy(cmdBuf, (int)(sectorSize + (b * blockSize)), sub, subSize * b, subSize); } outputPlugin.WriteSectorsLong(data, ui, blocksToRead); @@ -1440,7 +1442,7 @@ namespace DiscImageChef.Core.Devices.Dumping if(supportedSubchannel != MmcSubchannel.None) { - outputPlugin.WriteSectorsLong(new byte[SECTOR_SIZE * skip], ui, skip); + outputPlugin.WriteSectorsLong(new byte[sectorSize * skip], ui, skip); outputPlugin.WriteSectorsTag(new byte[subSize * skip], ui, skip, SectorTagType.CdSectorSubchannel); @@ -1646,8 +1648,6 @@ namespace DiscImageChef.Core.Devices.Dumping PulseProgress?.Invoke($"Trimming sector {badSector}"); - double cmdDuration = 0; - if(readcd) sense = dev.ReadCd(out cmdBuf, out senseBuf, (uint)badSector, blockSize, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, @@ -1679,10 +1679,10 @@ namespace DiscImageChef.Core.Devices.Dumping if(supportedSubchannel != MmcSubchannel.None) { - byte[] data = new byte[SECTOR_SIZE]; + byte[] data = new byte[sectorSize]; byte[] sub = new byte[subSize]; - Array.Copy(cmdBuf, 0, data, 0, SECTOR_SIZE); - Array.Copy(cmdBuf, SECTOR_SIZE, sub, 0, subSize); + Array.Copy(cmdBuf, 0, data, 0, sectorSize); + Array.Copy(cmdBuf, sectorSize, sub, 0, subSize); outputPlugin.WriteSectorLong(data, badSector); outputPlugin.WriteSectorTag(sub, badSector, SectorTagType.CdSectorSubchannel); } @@ -1713,8 +1713,8 @@ namespace DiscImageChef.Core.Devices.Dumping EndProgress?.Invoke(); end = DateTime.UtcNow; - UpdateStatus?.Invoke($"Trimmming finished in {(end - start).TotalSeconds} seconds."); - dumpLog.WriteLine("Trimmming finished in {0} seconds.", (end - start).TotalSeconds); + UpdateStatus?.Invoke($"Trimming finished in {(end - start).TotalSeconds} seconds."); + dumpLog.WriteLine("Trimming finished in {0} seconds.", (end - start).TotalSeconds); } #endregion Compact Disc Error trimming @@ -1748,8 +1748,7 @@ namespace DiscImageChef.Core.Devices.Dumping Modes.DecodedMode? dcMode10 = Modes.DecodeMode10(cmdBuf, PeripheralDeviceTypes.MultiMediaDevice); - if(dcMode10.HasValue && - dcMode10.Value.Pages != null) + if(dcMode10?.Pages != null) foreach(Modes.ModePage modePage in dcMode10.Value.Pages) if(modePage.Page == 0x01 && modePage.Subpage == 0x00) @@ -1760,8 +1759,7 @@ namespace DiscImageChef.Core.Devices.Dumping { Modes.DecodedMode? dcMode6 = Modes.DecodeMode6(cmdBuf, PeripheralDeviceTypes.MultiMediaDevice); - if(dcMode6.HasValue && - dcMode6.Value.Pages != null) + if(dcMode6?.Pages != null) foreach(Modes.ModePage modePage in dcMode6.Value.Pages) if(modePage.Page == 0x01 && modePage.Subpage == 0x00) @@ -1846,8 +1844,7 @@ namespace DiscImageChef.Core.Devices.Dumping { sense = dev.ReadCd(out cmdBuf, out senseBuf, (uint)badSector, blockSize, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, - true, MmcErrorField.None, supportedSubchannel, dev.Timeout, - out double cmdDuration); + true, MmcErrorField.None, supportedSubchannel, dev.Timeout, out cmdDuration); totalDuration += cmdDuration; } @@ -1878,10 +1875,10 @@ namespace DiscImageChef.Core.Devices.Dumping if(supportedSubchannel != MmcSubchannel.None) { - byte[] data = new byte[SECTOR_SIZE]; + byte[] data = new byte[sectorSize]; byte[] sub = new byte[subSize]; - Array.Copy(cmdBuf, 0, data, 0, SECTOR_SIZE); - Array.Copy(cmdBuf, SECTOR_SIZE, sub, 0, subSize); + Array.Copy(cmdBuf, 0, data, 0, sectorSize); + Array.Copy(cmdBuf, sectorSize, sub, 0, subSize); outputPlugin.WriteSectorLong(data, badSector); outputPlugin.WriteSectorTag(sub, badSector, SectorTagType.CdSectorSubchannel); } @@ -1956,7 +1953,7 @@ namespace DiscImageChef.Core.Devices.Dumping sense = dev.ReadCd(out cmdBuf, out senseBuf, (uint)badSector, blockSize, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, - supportedSubchannel, dev.Timeout, out double cmdDuration); + supportedSubchannel, dev.Timeout, out cmdDuration); totalDuration += cmdDuration; } @@ -1968,10 +1965,10 @@ namespace DiscImageChef.Core.Devices.Dumping if(supportedSubchannel != MmcSubchannel.None) { - byte[] data = new byte[SECTOR_SIZE]; + byte[] data = new byte[sectorSize]; byte[] sub = new byte[subSize]; - Array.Copy(cmdBuf, 0, data, 0, SECTOR_SIZE); - Array.Copy(cmdBuf, SECTOR_SIZE, sub, 0, subSize); + Array.Copy(cmdBuf, 0, data, 0, sectorSize); + Array.Copy(cmdBuf, sectorSize, sub, 0, subSize); outputPlugin.WriteSectorLong(data, badSector); outputPlugin.WriteSectorTag(sub, badSector, SectorTagType.CdSectorSubchannel); } @@ -2179,6 +2176,8 @@ namespace DiscImageChef.Core.Devices.Dumping } DateTime chkStart = DateTime.UtcNow; + + // ReSharper disable once UseObjectOrCollectionInitializer sidecarClass = new Sidecar(inputPlugin, outputPath, filter.Id, encoding); sidecarClass.InitProgressEvent += InitProgress; sidecarClass.UpdateProgressEvent += UpdateProgress; @@ -2241,7 +2240,7 @@ namespace DiscImageChef.Core.Devices.Dumping UpdateStatus?.Invoke(""); UpdateStatus?. - Invoke($"Took a total of {(end - start).TotalSeconds:F3} seconds ({totalDuration / 1000:F3} processing commands, {totalChkDuration / 1000:F3} checksumming, {imageWriteDuration:F3} writing, {(closeEnd - closeStart).TotalSeconds:F3} closing)."); + Invoke($"Took a total of {(end - dumpStart).TotalSeconds:F3} seconds ({totalDuration / 1000:F3} processing commands, {totalChkDuration / 1000:F3} checksumming, {imageWriteDuration:F3} writing, {(closeEnd - closeStart).TotalSeconds:F3} closing)."); UpdateStatus?. Invoke($"Average speed: {((double)blockSize * (double)(blocks + 1)) / 1048576 / (totalDuration / 1000):F3} MiB/sec."); diff --git a/DiscImageChef.Core/Devices/Dumping/MMC.cs b/DiscImageChef.Core/Devices/Dumping/MMC.cs index 436eb3069..fe1f49617 100644 --- a/DiscImageChef.Core/Devices/Dumping/MMC.cs +++ b/DiscImageChef.Core/Devices/Dumping/MMC.cs @@ -46,30 +46,27 @@ using Spare = DiscImageChef.Decoders.DVD.Spare; namespace DiscImageChef.Core.Devices.Dumping { - /// - /// Implement dumping optical discs from MultiMedia devices - /// + /// Implement dumping optical discs from MultiMedia devices partial class Dump { - /// - /// Dumps an optical disc - /// - internal void Mmc(ref MediaType dskType) + /// Dumps an optical disc + void Mmc(ref MediaType dskType) { - bool sense; + bool sense; byte[] tmpBuf; - var compactDisc = true; - var isXbox = false; + bool compactDisc = true; + bool isXbox = false; // TODO: Log not only what is it reading, but if it was read correctly or not. - sense = dev.GetConfiguration(out var cmdBuf, out _, 0, MmcGetConfigurationRt.Current, dev.Timeout, - out _); - if (!sense) + sense = dev.GetConfiguration(out byte[] cmdBuf, out _, 0, MmcGetConfigurationRt.Current, dev.Timeout, + out _); + + if(!sense) { - var ftr = Features.Separate(cmdBuf); + Features.SeparatedFeatures ftr = Features.Separate(cmdBuf); dumpLog.WriteLine("Device reports current profile is 0x{0:X4}", ftr.CurrentProfile); - switch (ftr.CurrentProfile) + switch(ftr.CurrentProfile) { case 0x0001: dskType = MediaType.GENERIC_HDD; @@ -79,15 +76,19 @@ namespace DiscImageChef.Core.Devices.Dumping goto default; case 0x0005: dskType = MediaType.CDMO; + break; case 0x0008: dskType = MediaType.CD; + break; case 0x0009: dskType = MediaType.CDR; + break; case 0x000A: dskType = MediaType.CDRW; + break; case 0x0010: dskType = MediaType.DVDROM; @@ -163,57 +164,68 @@ namespace DiscImageChef.Core.Devices.Dumping goto default; default: compactDisc = false; + break; } } - if (compactDisc) + if(compactDisc) { - CompactDisc(ref dskType); + CompactDisc(out dskType); + return; } - var scsiReader = new Reader(dev, dev.Timeout, null, dumpRaw); - var blocks = scsiReader.GetDeviceBlocks(); + var scsiReader = new Reader(dev, dev.Timeout, null, dumpRaw); + ulong blocks = scsiReader.GetDeviceBlocks(); dumpLog.WriteLine("Device reports disc has {0} blocks", blocks); - var mediaTags = new Dictionary(); + Dictionary mediaTags = new Dictionary(); - if (dskType == MediaType.PD650) - switch (blocks + 1) + if(dskType == MediaType.PD650) + switch(blocks + 1) { case 1281856: dskType = MediaType.PD650_WORM; + break; case 58620544: dskType = MediaType.REV120; + break; case 17090880: dskType = MediaType.REV35; + break; + // TODO: Unknown value default: dskType = MediaType.REV70; + break; } #region Nintendo - - switch (dskType) + switch(dskType) { case MediaType.Unknown when blocks > 0: dumpLog.WriteLine("Reading Physical Format Information"); + sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out _); - if (!sense) + MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out _); + + if(!sense) { - var nintendoPfi = PFI.Decode(cmdBuf); - if (nintendoPfi != null) - if (nintendoPfi.Value.DiskCategory == DiskCategory.Nintendo && - nintendoPfi.Value.PartVersion == 15) + PFI.PhysicalFormatInformation? nintendoPfi = PFI.Decode(cmdBuf); + + if(nintendoPfi != null) + if(nintendoPfi.Value.DiskCategory == DiskCategory.Nintendo && + nintendoPfi.Value.PartVersion == 15) { dumpLog.WriteLine("Dumping Nintendo GameCube or Wii discs is not yet implemented."); - StoppingErrorMessage - ?.Invoke("Dumping Nintendo GameCube or Wii discs is not yet implemented."); + + StoppingErrorMessage?. + Invoke("Dumping Nintendo GameCube or Wii discs is not yet implemented."); + return; } } @@ -237,106 +249,128 @@ namespace DiscImageChef.Core.Devices.Dumping case MediaType.HDDVDRW: case MediaType.HDDVDRWDL: dumpLog.WriteLine("Reading Physical Format Information"); + sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out _); - if (!sense) - if (PFI.Decode(cmdBuf).HasValue) + MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out _); + + if(!sense) + if(PFI.Decode(cmdBuf).HasValue) { tmpBuf = new byte[cmdBuf.Length - 4]; Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); mediaTags.Add(MediaTagType.DVD_PFI, tmpBuf); - var decPfi = PFI.Decode(cmdBuf).Value; + PFI.PhysicalFormatInformation decPfi = PFI.Decode(cmdBuf).Value; UpdateStatus?.Invoke($"PFI:\n{PFI.Prettify(decPfi)}"); // False book types - if (dskType == MediaType.DVDROM) - switch (decPfi.DiskCategory) + if(dskType == MediaType.DVDROM) + switch(decPfi.DiskCategory) { case DiskCategory.DVDPR: dskType = MediaType.DVDPR; + break; case DiskCategory.DVDPRDL: dskType = MediaType.DVDPRDL; + break; case DiskCategory.DVDPRW: dskType = MediaType.DVDPRW; + break; case DiskCategory.DVDPRWDL: dskType = MediaType.DVDPRWDL; + break; case DiskCategory.DVDR: dskType = decPfi.PartVersion == 6 ? MediaType.DVDRDL : MediaType.DVDR; + break; case DiskCategory.DVDRAM: dskType = MediaType.DVDRAM; + break; default: dskType = MediaType.DVDROM; + break; case DiskCategory.DVDRW: dskType = decPfi.PartVersion == 3 ? MediaType.DVDRWDL : MediaType.DVDRW; + break; case DiskCategory.HDDVDR: dskType = MediaType.HDDVDR; + break; case DiskCategory.HDDVDRAM: dskType = MediaType.HDDVDRAM; + break; case DiskCategory.HDDVDROM: dskType = MediaType.HDDVDROM; + break; case DiskCategory.HDDVDRW: dskType = MediaType.HDDVDRW; + break; case DiskCategory.Nintendo: dskType = decPfi.DiscSize == DVDSize.Eighty ? MediaType.GOD : MediaType.WOD; + break; case DiskCategory.UMD: dskType = MediaType.UMD; + break; } } dumpLog.WriteLine("Reading Disc Manufacturing Information"); + sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.DiscManufacturingInformation, 0, dev.Timeout, - out _); - if (!sense) + MmcDiscStructureFormat.DiscManufacturingInformation, 0, dev.Timeout, + out _); + + if(!sense) { - if (DMI.IsXbox(cmdBuf) || DMI.IsXbox360(cmdBuf)) + if(DMI.IsXbox(cmdBuf) || + DMI.IsXbox360(cmdBuf)) { - if (DMI.IsXbox(cmdBuf)) + if(DMI.IsXbox(cmdBuf)) { dskType = MediaType.XGD; } - else if (DMI.IsXbox360(cmdBuf)) + else if(DMI.IsXbox360(cmdBuf)) { dskType = MediaType.XGD2; // All XGD3 all have the same number of blocks - if (blocks == 25063 || // Locked (or non compatible drive) - blocks == 4229664 || // Xtreme unlock - blocks == 4246304) // Wxripper unlock + if(blocks == 25063 || // Locked (or non compatible drive) + blocks == 4229664 || // Xtreme unlock + blocks == 4246304) // Wxripper unlock dskType = MediaType.XGD3; } - sense = dev.ScsiInquiry(out var inqBuf, out _); + sense = dev.ScsiInquiry(out byte[] inqBuf, out _); - if (sense || !Inquiry.Decode(inqBuf).HasValue || Inquiry.Decode(inqBuf).HasValue && - !Inquiry.Decode(inqBuf).Value.KreonPresent) + if(sense || + !Inquiry.Decode(inqBuf).HasValue || + (Inquiry.Decode(inqBuf).HasValue && !Inquiry.Decode(inqBuf).Value.KreonPresent)) { dumpLog.WriteLine("Dumping Xbox Game Discs requires a drive with Kreon firmware."); - StoppingErrorMessage - ?.Invoke("Dumping Xbox Game Discs requires a drive with Kreon firmware."); + + StoppingErrorMessage?. + Invoke("Dumping Xbox Game Discs requires a drive with Kreon firmware."); + return; } - if (dumpRaw && !force) + if(dumpRaw && !force) { - StoppingErrorMessage - ?.Invoke( - "Not continuing. If you want to continue reading cooked data when raw is not available use the force option."); + StoppingErrorMessage?. + Invoke("Not continuing. If you want to continue reading cooked data when raw is not available use the force option."); + // TODO: Exit more gracefully return; } @@ -344,7 +378,7 @@ namespace DiscImageChef.Core.Devices.Dumping isXbox = true; } - if (cmdBuf.Length == 2052) + if(cmdBuf.Length == 2052) { tmpBuf = new byte[cmdBuf.Length - 4]; Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); @@ -354,42 +388,42 @@ namespace DiscImageChef.Core.Devices.Dumping break; } - #endregion Nintendo #region All DVD and HD DVD types - #endregion All DVD and HD DVD types #region DVD-ROM - - if (dskType == MediaType.DVDDownload || dskType == MediaType.DVDROM) + if(dskType == MediaType.DVDDownload || + dskType == MediaType.DVDROM) { dumpLog.WriteLine("Reading Lead-in Copyright Information."); + sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.CopyrightInformation, 0, dev.Timeout, out _); - if (!sense) - if (CSS_CPRM.DecodeLeadInCopyright(cmdBuf).HasValue) + MmcDiscStructureFormat.CopyrightInformation, 0, dev.Timeout, out _); + + if(!sense) + if(CSS_CPRM.DecodeLeadInCopyright(cmdBuf).HasValue) { tmpBuf = new byte[cmdBuf.Length - 4]; Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); mediaTags.Add(MediaTagType.DVD_CMI, tmpBuf); } } - #endregion DVD-ROM - switch (dskType) + switch(dskType) { #region DVD-ROM and HD DVD-ROM - case MediaType.DVDDownload: case MediaType.DVDROM: case MediaType.HDDVDROM: dumpLog.WriteLine("Reading Burst Cutting Area."); + sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.BurstCuttingArea, 0, dev.Timeout, out _); - if (!sense) + MmcDiscStructureFormat.BurstCuttingArea, 0, dev.Timeout, out _); + + if(!sense) { tmpBuf = new byte[cmdBuf.Length - 4]; Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); @@ -397,18 +431,18 @@ namespace DiscImageChef.Core.Devices.Dumping } break; - #endregion DVD-ROM and HD DVD-ROM #region DVD-RAM and HD DVD-RAM - case MediaType.DVDRAM: case MediaType.HDDVDRAM: dumpLog.WriteLine("Reading Disc Description Structure."); + sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.DvdramDds, 0, dev.Timeout, out _); - if (!sense) - if (DDS.Decode(cmdBuf).HasValue) + MmcDiscStructureFormat.DvdramDds, 0, dev.Timeout, out _); + + if(!sense) + if(DDS.Decode(cmdBuf).HasValue) { tmpBuf = new byte[cmdBuf.Length - 4]; Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); @@ -416,11 +450,13 @@ namespace DiscImageChef.Core.Devices.Dumping } dumpLog.WriteLine("Reading Spare Area Information."); + sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.DvdramSpareAreaInformation, 0, dev.Timeout, - out _); - if (!sense) - if (Spare.Decode(cmdBuf).HasValue) + MmcDiscStructureFormat.DvdramSpareAreaInformation, 0, dev.Timeout, + out _); + + if(!sense) + if(Spare.Decode(cmdBuf).HasValue) { tmpBuf = new byte[cmdBuf.Length - 4]; Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); @@ -428,17 +464,17 @@ namespace DiscImageChef.Core.Devices.Dumping } break; - #endregion DVD-RAM and HD DVD-RAM #region DVD-R and DVD-RW - case MediaType.DVDR: case MediaType.DVDRW: dumpLog.WriteLine("Reading Pre-Recorded Information."); + sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.PreRecordedInfo, 0, dev.Timeout, out _); - if (!sense) + MmcDiscStructureFormat.PreRecordedInfo, 0, dev.Timeout, out _); + + if(!sense) { tmpBuf = new byte[cmdBuf.Length - 4]; Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); @@ -446,21 +482,21 @@ namespace DiscImageChef.Core.Devices.Dumping } break; - #endregion DVD-R and DVD-RW } - switch (dskType) + switch(dskType) { #region DVD-R, DVD-RW and HD DVD-R - case MediaType.DVDR: case MediaType.DVDRW: case MediaType.HDDVDR: dumpLog.WriteLine("Reading Media Identifier."); + sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.DvdrMediaIdentifier, 0, dev.Timeout, out _); - if (!sense) + MmcDiscStructureFormat.DvdrMediaIdentifier, 0, dev.Timeout, out _); + + if(!sense) { tmpBuf = new byte[cmdBuf.Length - 4]; Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); @@ -468,10 +504,12 @@ namespace DiscImageChef.Core.Devices.Dumping } dumpLog.WriteLine("Reading Recordable Physical Information."); + sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.DvdrPhysicalInformation, 0, dev.Timeout, - out _); - if (!sense) + MmcDiscStructureFormat.DvdrPhysicalInformation, 0, dev.Timeout, + out _); + + if(!sense) { tmpBuf = new byte[cmdBuf.Length - 4]; Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); @@ -479,19 +517,19 @@ namespace DiscImageChef.Core.Devices.Dumping } break; - #endregion DVD-R, DVD-RW and HD DVD-R #region All DVD+ - case MediaType.DVDPR: case MediaType.DVDPRDL: case MediaType.DVDPRW: case MediaType.DVDPRWDL: dumpLog.WriteLine("Reading ADdress In Pregroove."); + sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.Adip, 0, dev.Timeout, out _); - if (!sense) + MmcDiscStructureFormat.Adip, 0, dev.Timeout, out _); + + if(!sense) { tmpBuf = new byte[cmdBuf.Length - 4]; Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); @@ -499,9 +537,11 @@ namespace DiscImageChef.Core.Devices.Dumping } dumpLog.WriteLine("Reading Disc Control Blocks."); + sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.Dcb, 0, dev.Timeout, out _); - if (!sense) + MmcDiscStructureFormat.Dcb, 0, dev.Timeout, out _); + + if(!sense) { tmpBuf = new byte[cmdBuf.Length - 4]; Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); @@ -509,17 +549,17 @@ namespace DiscImageChef.Core.Devices.Dumping } break; - #endregion All DVD+ #region HD DVD-ROM - case MediaType.HDDVDROM: dumpLog.WriteLine("Reading Lead-in Copyright Information."); + sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Dvd, 0, 0, - MmcDiscStructureFormat.HddvdCopyrightInformation, 0, dev.Timeout, - out _); - if (!sense) + MmcDiscStructureFormat.HddvdCopyrightInformation, 0, dev.Timeout, + out _); + + if(!sense) { tmpBuf = new byte[cmdBuf.Length - 4]; Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); @@ -527,21 +567,21 @@ namespace DiscImageChef.Core.Devices.Dumping } break; - #endregion HD DVD-ROM #region All Blu-ray - case MediaType.BDR: case MediaType.BDRE: case MediaType.BDROM: case MediaType.BDRXL: case MediaType.BDREXL: dumpLog.WriteLine("Reading Disc Information."); + sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Bd, 0, 0, - MmcDiscStructureFormat.DiscInformation, 0, dev.Timeout, out _); - if (!sense) - if (DI.Decode(cmdBuf).HasValue) + MmcDiscStructureFormat.DiscInformation, 0, dev.Timeout, out _); + + if(!sense) + if(DI.Decode(cmdBuf).HasValue) { tmpBuf = new byte[cmdBuf.Length - 4]; Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); @@ -560,19 +600,19 @@ namespace DiscImageChef.Core.Devices.Dumping mediaTags.Add(MediaTagType.PAC, tmpBuf); }*/ break; - #endregion All Blu-ray } - switch (dskType) + switch(dskType) { #region BD-ROM only - case MediaType.BDROM: dumpLog.WriteLine("Reading Burst Cutting Area."); + sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Bd, 0, 0, - MmcDiscStructureFormat.BdBurstCuttingArea, 0, dev.Timeout, out _); - if (!sense) + MmcDiscStructureFormat.BdBurstCuttingArea, 0, dev.Timeout, out _); + + if(!sense) { tmpBuf = new byte[cmdBuf.Length - 4]; Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); @@ -580,19 +620,19 @@ namespace DiscImageChef.Core.Devices.Dumping } break; - #endregion BD-ROM only #region Writable Blu-ray only - case MediaType.BDR: case MediaType.BDRE: case MediaType.BDRXL: case MediaType.BDREXL: dumpLog.WriteLine("Reading Disc Definition Structure."); + sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Bd, 0, 0, - MmcDiscStructureFormat.BdDds, 0, dev.Timeout, out _); - if (!sense) + MmcDiscStructureFormat.BdDds, 0, dev.Timeout, out _); + + if(!sense) { tmpBuf = new byte[cmdBuf.Length - 4]; Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); @@ -600,9 +640,11 @@ namespace DiscImageChef.Core.Devices.Dumping } dumpLog.WriteLine("Reading Spare Area Information."); + sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Bd, 0, 0, - MmcDiscStructureFormat.BdSpareAreaInformation, 0, dev.Timeout, out _); - if (!sense) + MmcDiscStructureFormat.BdSpareAreaInformation, 0, dev.Timeout, out _); + + if(!sense) { tmpBuf = new byte[cmdBuf.Length - 4]; Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); @@ -610,57 +652,57 @@ namespace DiscImageChef.Core.Devices.Dumping } break; - #endregion Writable Blu-ray only } - if (isXbox) + if(isXbox) { Xgd(mediaTags, ref dskType); + return; } Sbc(mediaTags, ref dskType, true); } - internal static void AddMediaTagToSidecar(string outputPath, - KeyValuePair tag, - ref CICMMetadataType sidecar) + static void AddMediaTagToSidecar(string outputPath, KeyValuePair tag, + ref CICMMetadataType sidecar) { - switch (tag.Key) + switch(tag.Key) { case MediaTagType.DVD_PFI: sidecar.OpticalDisc[0].PFI = new DumpType { - Image = outputPath, - Size = (ulong) tag.Value.Length, + Image = outputPath, Size = (ulong)tag.Value.Length, Checksums = Checksum.GetChecksums(tag.Value).ToArray() }; + break; case MediaTagType.DVD_DMI: sidecar.OpticalDisc[0].DMI = new DumpType { - Image = outputPath, - Size = (ulong) tag.Value.Length, + Image = outputPath, Size = (ulong)tag.Value.Length, Checksums = Checksum.GetChecksums(tag.Value).ToArray() }; + break; case MediaTagType.DVD_CMI: case MediaTagType.HDDVD_CPI: sidecar.OpticalDisc[0].CMI = new DumpType { - Image = outputPath, - Size = (ulong) tag.Value.Length, + Image = outputPath, Size = (ulong)tag.Value.Length, Checksums = Checksum.GetChecksums(tag.Value).ToArray() }; - var tmp = new byte[tag.Value.Length + 4]; + byte[] tmp = new byte[tag.Value.Length + 4]; Array.Copy(tag.Value, 0, tmp, 4, tag.Value.Length); - tmp[0] = (byte) ((tag.Value.Length & 0xFF00) >> 8); - tmp[1] = (byte) (tag.Value.Length & 0xFF); + tmp[0] = (byte)((tag.Value.Length & 0xFF00) >> 8); + tmp[1] = (byte)(tag.Value.Length & 0xFF); - var cpy = CSS_CPRM.DecodeLeadInCopyright(tmp); - if (cpy.HasValue && cpy.Value.CopyrightType != CopyrightType.NoProtection) + CSS_CPRM.LeadInCopyright? cpy = CSS_CPRM.DecodeLeadInCopyright(tmp); + + if(cpy.HasValue && + cpy.Value.CopyrightType != CopyrightType.NoProtection) sidecar.OpticalDisc[0].CopyProtection = cpy.Value.CopyrightType.ToString(); break; @@ -668,90 +710,88 @@ namespace DiscImageChef.Core.Devices.Dumping case MediaTagType.BD_BCA: sidecar.OpticalDisc[0].BCA = new DumpType { - Image = outputPath, - Size = (ulong) tag.Value.Length, + Image = outputPath, Size = (ulong)tag.Value.Length, Checksums = Checksum.GetChecksums(tag.Value).ToArray() }; + break; case MediaTagType.BD_DDS: case MediaTagType.DVDRAM_DDS: sidecar.OpticalDisc[0].DDS = new DumpType { - Image = outputPath, - Size = (ulong) tag.Value.Length, + Image = outputPath, Size = (ulong)tag.Value.Length, Checksums = Checksum.GetChecksums(tag.Value).ToArray() }; + break; case MediaTagType.DVDRAM_SpareArea: case MediaTagType.BD_SpareArea: sidecar.OpticalDisc[0].SAI = new DumpType { - Image = outputPath, - Size = (ulong) tag.Value.Length, + Image = outputPath, Size = (ulong)tag.Value.Length, Checksums = Checksum.GetChecksums(tag.Value).ToArray() }; + break; case MediaTagType.DVDR_PreRecordedInfo: sidecar.OpticalDisc[0].PRI = new DumpType { - Image = outputPath, - Size = (ulong) tag.Value.Length, + Image = outputPath, Size = (ulong)tag.Value.Length, Checksums = Checksum.GetChecksums(tag.Value).ToArray() }; + break; case MediaTagType.DVD_MediaIdentifier: sidecar.OpticalDisc[0].MediaID = new DumpType { - Image = outputPath, - Size = (ulong) tag.Value.Length, + Image = outputPath, Size = (ulong)tag.Value.Length, Checksums = Checksum.GetChecksums(tag.Value).ToArray() }; + break; case MediaTagType.DVDR_PFI: sidecar.OpticalDisc[0].PFIR = new DumpType { - Image = outputPath, - Size = (ulong) tag.Value.Length, + Image = outputPath, Size = (ulong)tag.Value.Length, Checksums = Checksum.GetChecksums(tag.Value).ToArray() }; + break; case MediaTagType.DVD_ADIP: sidecar.OpticalDisc[0].ADIP = new DumpType { - Image = outputPath, - Size = (ulong) tag.Value.Length, + Image = outputPath, Size = (ulong)tag.Value.Length, Checksums = Checksum.GetChecksums(tag.Value).ToArray() }; + break; case MediaTagType.DCB: sidecar.OpticalDisc[0].DCB = new DumpType { - Image = outputPath, - Size = (ulong) tag.Value.Length, + Image = outputPath, Size = (ulong)tag.Value.Length, Checksums = Checksum.GetChecksums(tag.Value).ToArray() }; + break; case MediaTagType.BD_DI: sidecar.OpticalDisc[0].DI = new DumpType { - Image = outputPath, - Size = (ulong) tag.Value.Length, + Image = outputPath, Size = (ulong)tag.Value.Length, Checksums = Checksum.GetChecksums(tag.Value).ToArray() }; + break; case MediaTagType.Xbox_SecuritySector: - if (sidecar.OpticalDisc[0].Xbox == null) sidecar.OpticalDisc[0].Xbox = new XboxType(); + if(sidecar.OpticalDisc[0].Xbox == null) + sidecar.OpticalDisc[0].Xbox = new XboxType(); sidecar.OpticalDisc[0].Xbox.SecuritySectors = new[] { new XboxSecuritySectorsType { - RequestNumber = 0, - RequestVersion = 1, - SecuritySectors = new DumpType + RequestNumber = 0, RequestVersion = 1, SecuritySectors = new DumpType { - Image = outputPath, - Size = (ulong) tag.Value.Length, + Image = outputPath, Size = (ulong)tag.Value.Length, Checksums = Checksum.GetChecksums(tag.Value).ToArray() } } @@ -759,78 +799,80 @@ namespace DiscImageChef.Core.Devices.Dumping break; case MediaTagType.Xbox_PFI: - if (sidecar.OpticalDisc[0].Xbox == null) sidecar.OpticalDisc[0].Xbox = new XboxType(); + if(sidecar.OpticalDisc[0].Xbox == null) + sidecar.OpticalDisc[0].Xbox = new XboxType(); sidecar.OpticalDisc[0].Xbox.PFI = new DumpType { - Image = outputPath, - Size = (ulong) tag.Value.Length, + Image = outputPath, Size = (ulong)tag.Value.Length, Checksums = Checksum.GetChecksums(tag.Value).ToArray() }; + break; case MediaTagType.Xbox_DMI: - if (sidecar.OpticalDisc[0].Xbox == null) sidecar.OpticalDisc[0].Xbox = new XboxType(); + if(sidecar.OpticalDisc[0].Xbox == null) + sidecar.OpticalDisc[0].Xbox = new XboxType(); sidecar.OpticalDisc[0].Xbox.DMI = new DumpType { - Image = outputPath, - Size = (ulong) tag.Value.Length, + Image = outputPath, Size = (ulong)tag.Value.Length, Checksums = Checksum.GetChecksums(tag.Value).ToArray() }; + break; case MediaTagType.CD_FullTOC: sidecar.OpticalDisc[0].TOC = new DumpType { - Image = outputPath, - Size = (ulong) tag.Value.Length, + Image = outputPath, Size = (ulong)tag.Value.Length, Checksums = Checksum.GetChecksums(tag.Value).ToArray() }; + break; case MediaTagType.CD_ATIP: sidecar.OpticalDisc[0].ATIP = new DumpType { - Image = outputPath, - Size = (ulong) tag.Value.Length, + Image = outputPath, Size = (ulong)tag.Value.Length, Checksums = Checksum.GetChecksums(tag.Value).ToArray() }; + break; case MediaTagType.CD_PMA: sidecar.OpticalDisc[0].PMA = new DumpType { - Image = outputPath, - Size = (ulong) tag.Value.Length, + Image = outputPath, Size = (ulong)tag.Value.Length, Checksums = Checksum.GetChecksums(tag.Value).ToArray() }; + break; case MediaTagType.CD_TEXT: sidecar.OpticalDisc[0].LeadInCdText = new DumpType { - Image = outputPath, - Size = (ulong) tag.Value.Length, + Image = outputPath, Size = (ulong)tag.Value.Length, Checksums = Checksum.GetChecksums(tag.Value).ToArray() }; + break; case MediaTagType.CD_FirstTrackPregap: sidecar.OpticalDisc[0].FirstTrackPregrap = new[] { new BorderType { - Image = outputPath, - Size = (ulong) tag.Value.Length, + Image = outputPath, Size = (ulong)tag.Value.Length, Checksums = Checksum.GetChecksums(tag.Value).ToArray() } }; + break; case MediaTagType.CD_LeadIn: sidecar.OpticalDisc[0].LeadIn = new[] { new BorderType { - Image = outputPath, - Size = (ulong) tag.Value.Length, + Image = outputPath, Size = (ulong)tag.Value.Length, Checksums = Checksum.GetChecksums(tag.Value).ToArray() } }; + break; } }