diff --git a/Aaru.CommonTypes b/Aaru.CommonTypes index 7455b48f8..5e162d61f 160000 --- a/Aaru.CommonTypes +++ b/Aaru.CommonTypes @@ -1 +1 @@ -Subproject commit 7455b48f8f33cb3d201165fb975c3dbb86284f09 +Subproject commit 5e162d61ff94854134501d301284b0ee36dbeb17 diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Data.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Data.cs index e16d869fb..00edefce6 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/Data.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/Data.cs @@ -30,8 +30,6 @@ // Copyright © 2011-2022 Natalia Portillo // ****************************************************************************/ - - // ReSharper disable JoinDeclarationAndInitializer // ReSharper disable InlineOutVariableDeclaration // ReSharper disable TooWideLocalVariableScope @@ -253,8 +251,7 @@ partial class Dump _speed *= _speedMultiplier; - if(_speed == 0 || - _speed > 0xFFFF) + if(_speed is 0 or > 0xFFFF) _speed = 0xFFFF; currentReadSpeed = _speed; diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs index 0ad7052aa..8cceef1ab 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/Dump.cs @@ -30,8 +30,6 @@ // Copyright © 2011-2022 Natalia Portillo // ****************************************************************************/ - - // ReSharper disable JoinDeclarationAndInitializer // ReSharper disable InlineOutVariableDeclaration // ReSharper disable TooWideLocalVariableScope @@ -646,8 +644,7 @@ sealed partial class Dump break; case 2: case 0x62: // Scrambled - if(dskType == MediaType.CDI || - dskType == MediaType.CDIREADY) + if(dskType is MediaType.CDI or MediaType.CDIREADY) { UpdateStatus?.Invoke($"Track {trk.Sequence} is MODE2"); _dumpLog.WriteLine("Track {0} is MODE2", trk.Sequence); @@ -670,9 +667,7 @@ sealed partial class Dump trk.Type = TrackType.CdMode2Form1; // These media type specifications do not legally allow mode 2 tracks to be present - if(dskType == MediaType.CDROM || - dskType == MediaType.CDPLUS || - dskType == MediaType.CDV) + if(dskType is MediaType.CDROM or MediaType.CDPLUS or MediaType.CDV) dskType = MediaType.CD; break; @@ -925,9 +920,7 @@ sealed partial class Dump { sense = _dev.ReadIsrc((byte)trk.Sequence, out string isrc, out _, out _, _dev.Timeout, out _); - if(sense || - isrc == null || - isrc == "000000000000") + if(sense || isrc is null or "000000000000") continue; isrcs[(byte)trk.Sequence] = isrc; @@ -1097,8 +1090,7 @@ sealed partial class Dump _speed *= _speedMultiplier; - if(_speed == 0 || - _speed > 0xFFFF) + if(_speed is 0 or > 0xFFFF) _speed = 0xFFFF; _dev.SetCdSpeed(out _, RotationalControl.ClvAndImpureCav, (ushort)_speed, 0, _dev.Timeout, out _); diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Plextor.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Plextor.cs index cbfb82cff..0d2e7c12f 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/Plextor.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/Plextor.cs @@ -75,8 +75,7 @@ partial class Dump uint subSize = supportedPlextorSubchannel == PlextorSubchannel.Q16 ? 16u : 96u; - if(supportedPlextorSubchannel == PlextorSubchannel.Q16 || - supportedPlextorSubchannel == PlextorSubchannel.Pack) + if(supportedPlextorSubchannel is PlextorSubchannel.Q16 or PlextorSubchannel.Pack) { sense = _dev.PlextorReadCdDa(out cmdBuf, out senseBuf, firstSectorToRead, 2352 + subSize, blocksToRead, supportedPlextorSubchannel, _dev.Timeout, out cmdDuration); diff --git a/Aaru.Core/Devices/Dumping/CompactDisc/Tracks.cs b/Aaru.Core/Devices/Dumping/CompactDisc/Tracks.cs index 6c7f55c3c..948b08857 100644 --- a/Aaru.Core/Devices/Dumping/CompactDisc/Tracks.cs +++ b/Aaru.Core/Devices/Dumping/CompactDisc/Tracks.cs @@ -30,8 +30,6 @@ // Copyright © 2011-2022 Natalia Portillo // ****************************************************************************/ - - // ReSharper disable JoinDeclarationAndInitializer // ReSharper disable InlineOutVariableDeclaration // ReSharper disable TooWideLocalVariableScope @@ -102,7 +100,7 @@ partial class Dump FullTOC.TrackDataDescriptor[] sortedTracks = toc.Value.TrackDescriptors.OrderBy(track => track.POINT).ToArray(); - foreach(FullTOC.TrackDataDescriptor trk in sortedTracks.Where(trk => trk.ADR == 1 || trk.ADR == 4)) + foreach(FullTOC.TrackDataDescriptor trk in sortedTracks.Where(trk => trk.ADR is 1 or 4)) if(trk.POINT >= 0x01 && trk.POINT <= 0x63) { @@ -190,7 +188,7 @@ partial class Dump if(oldToc.HasValue) foreach(TOC.CDTOCTrackDataDescriptor trk in oldToc.Value.TrackDescriptors.OrderBy(t => t.TrackNumber). - Where(trk => trk.ADR == 1 || trk.ADR == 4)) + Where(trk => trk.ADR is 1 or 4)) if(trk.TrackNumber >= 0x01 && trk.TrackNumber <= 0x63) { diff --git a/Aaru.Core/Devices/Dumping/MMC.cs b/Aaru.Core/Devices/Dumping/MMC.cs index d0795045f..1c0ff5e42 100644 --- a/Aaru.Core/Devices/Dumping/MMC.cs +++ b/Aaru.Core/Devices/Dumping/MMC.cs @@ -258,9 +258,8 @@ partial class Dump if(decMode.HasValue && _dev.IsUsb && !gotConfiguration && - (decMode.Value.Header.MediumType == MediumTypes.UnknownBlockDevice || - decMode.Value.Header.MediumType == MediumTypes.ReadOnlyBlockDevice || - decMode.Value.Header.MediumType == MediumTypes.ReadWriteBlockDevice)) + decMode.Value.Header.MediumType is MediumTypes.UnknownBlockDevice or MediumTypes.ReadOnlyBlockDevice + or MediumTypes.ReadWriteBlockDevice) { _speedMultiplier = -1; Sbc(null, MediaType.Unknown, false); @@ -495,8 +494,7 @@ partial class Dump #endregion All DVD and HD DVD types #region DVD-ROM - if(dskType == MediaType.DVDDownload || - dskType == MediaType.DVDROM) + if(dskType is MediaType.DVDDownload or MediaType.DVDROM) { _dumpLog.WriteLine("Reading Lead-in Copyright Information."); diff --git a/Aaru.Core/Devices/Dumping/SSC.cs b/Aaru.Core/Devices/Dumping/SSC.cs index b06d1f90f..7a59020d2 100644 --- a/Aaru.Core/Devices/Dumping/SSC.cs +++ b/Aaru.Core/Devices/Dumping/SSC.cs @@ -30,8 +30,6 @@ // Copyright © 2011-2022 Natalia Portillo // ****************************************************************************/ - - // ReSharper disable JoinDeclarationAndInitializer namespace Aaru.Core.Devices.Dumping; @@ -112,7 +110,7 @@ partial class Dump _dev.RequestSense(out senseBuf, _dev.Timeout, out duration); decSense = Sense.Decode(senseBuf); } while(decSense is { ASC: 0x00 } && - (decSense.Value.ASCQ == 0x1A || decSense.Value.ASCQ != 0x04 || decSense.Value.ASCQ != 0x00)); + decSense.Value.ASCQ is 0x1A or not (0x04 and 0x00)); _dev.RequestSense(out senseBuf, _dev.Timeout, out duration); decSense = Sense.Decode(senseBuf); @@ -191,7 +189,7 @@ partial class Dump _dev.RequestSense(out senseBuf, _dev.Timeout, out duration); decSense = Sense.Decode(senseBuf); } while(decSense is { ASC: 0x00 } && - (decSense.Value.ASCQ == 0x1A || decSense.Value.ASCQ == 0x19)); + decSense.Value.ASCQ is 0x1A or 0x19); // And yet, did not rewind! if(decSense.HasValue && @@ -737,7 +735,7 @@ partial class Dump _dev.RequestSense(out senseBuf, _dev.Timeout, out duration); decSense = Sense.Decode(senseBuf); } while(decSense is { ASC: 0x00 } && - (decSense.Value.ASCQ == 0x1A || decSense.Value.ASCQ == 0x19)); + decSense.Value.ASCQ is 0x1A or 0x19); // And yet, did not rewind! if(decSense.HasValue && @@ -963,7 +961,7 @@ partial class Dump // For sure this is an end-of-tape/partition case SenseKeys.BlankCheck when decSense.Value.ASC == 0x00 && - (decSense.Value.ASCQ == 0x02 || decSense.Value.ASCQ == 0x05 || eom): + (decSense.Value.ASCQ is 0x02 or 0x05 || eom): // TODO: Detect end of partition endOfMedia = true; UpdateStatus?.Invoke("Found end-of-tape/partition..."); @@ -978,9 +976,8 @@ partial class Dump continue; } - if((decSense.Value.SenseKey == SenseKeys.NoSense || - decSense.Value.SenseKey == SenseKeys.RecoveredError) && - (decSense.Value.ASCQ == 0x02 || decSense.Value.ASCQ == 0x05 || eom)) + if(decSense.Value.SenseKey is SenseKeys.NoSense or SenseKeys.RecoveredError && + (decSense.Value.ASCQ is 0x02 or 0x05 || eom)) { // TODO: Detect end of partition endOfMedia = true; @@ -990,8 +987,7 @@ partial class Dump continue; } - if((decSense.Value.SenseKey == SenseKeys.NoSense || - decSense.Value.SenseKey == SenseKeys.RecoveredError) && + if(decSense.Value.SenseKey is SenseKeys.NoSense or SenseKeys.RecoveredError && (decSense.Value.ASCQ == 0x01 || filemark)) { currentTapeFile.LastBlock = currentBlock - 1; diff --git a/Aaru.Core/Devices/Dumping/Sbc/Dump.cs b/Aaru.Core/Devices/Dumping/Sbc/Dump.cs index 02e65aed7..acf4d4e3e 100644 --- a/Aaru.Core/Devices/Dumping/Sbc/Dump.cs +++ b/Aaru.Core/Devices/Dumping/Sbc/Dump.cs @@ -682,8 +682,7 @@ partial class Dump _speed *= _speedMultiplier; - if(_speed == 0 || - _speed > 0xFFFF) + if(_speed is 0 or > 0xFFFF) _speed = 0xFFFF; _dev.SetCdSpeed(out _, RotationalControl.ClvAndImpureCav, (ushort)_speed, 0, _dev.Timeout, out _); diff --git a/Aaru.Core/Devices/Dumping/XGD.cs b/Aaru.Core/Devices/Dumping/XGD.cs index 1d002bd55..31910ac8d 100644 --- a/Aaru.Core/Devices/Dumping/XGD.cs +++ b/Aaru.Core/Devices/Dumping/XGD.cs @@ -30,8 +30,6 @@ // Copyright © 2011-2022 Natalia Portillo // ****************************************************************************/ - - // ReSharper disable JoinDeclarationAndInitializer namespace Aaru.Core.Devices.Dumping; @@ -412,8 +410,7 @@ partial class Dump _speed *= _speedMultiplier; - if(_speed == 0 || - _speed > 0xFFFF) + if(_speed is 0 or > 0xFFFF) _speed = 0xFFFF; _dev.SetCdSpeed(out _, RotationalControl.ClvAndImpureCav, (ushort)_speed, 0, _dev.Timeout, out _); diff --git a/Aaru.Core/Devices/Report/MMC.cs b/Aaru.Core/Devices/Report/MMC.cs index 62d6e9a57..dc0979c80 100644 --- a/Aaru.Core/Devices/Report/MMC.cs +++ b/Aaru.Core/Devices/Report/MMC.cs @@ -934,8 +934,7 @@ public sealed partial class DeviceReport mediaTest.BluSaiData = buffer; } - if(mediaType == "DVD-R" || - mediaType == "DVD-RW") + if(mediaType is "DVD-R" or "DVD-RW") { Spectre.ProgressSingleSpinner(ctx => { @@ -952,9 +951,7 @@ public sealed partial class DeviceReport mediaTest.PriData = buffer; } - if(mediaType == "DVD-R" || - mediaType == "DVD-RW" || - mediaType == "HD DVD-R") + if(mediaType is "DVD-R" or "DVD-RW" or "HD DVD-R") { Spectre.ProgressSingleSpinner(ctx => { @@ -1048,12 +1045,8 @@ public sealed partial class DeviceReport } if(mediaType.StartsWith("BD-R", StringComparison.Ordinal) || - mediaType == "Ultra HD Blu-ray movie" || - mediaType == "PlayStation 3 game" || - mediaType == "PlayStation 4 game" || - mediaType == "PlayStation 5 game" || - mediaType == "Xbox One game" || - mediaType == "Nintendo Wii game") + mediaType is "Ultra HD Blu-ray movie" or "PlayStation 3 game" or "PlayStation 4 game" or "PlayStation 5 game" + or "Xbox One game" or "Nintendo Wii game") { Spectre.ProgressSingleSpinner(ctx => { diff --git a/Aaru.Core/Media/CompactDisc.cs b/Aaru.Core/Media/CompactDisc.cs index a94d9d2a2..a39643d6a 100644 --- a/Aaru.Core/Media/CompactDisc.cs +++ b/Aaru.Core/Media/CompactDisc.cs @@ -332,8 +332,7 @@ public static class CompactDisc { string isrc = Subchannel.DecodeIsrc(q); - if(isrc == null || - isrc == "000000000000") + if(isrc is null or "000000000000") continue; if(!crcOk) @@ -363,8 +362,7 @@ public static class CompactDisc { string newMcn = Subchannel.DecodeMcn(q); - if(newMcn == null || - newMcn == "0000000000000") + if(newMcn is null or "0000000000000") continue; if(!crcOk) diff --git a/Aaru.Core/Media/Detection/MMC.cs b/Aaru.Core/Media/Detection/MMC.cs index f66b42395..7f855872c 100644 --- a/Aaru.Core/Media/Detection/MMC.cs +++ b/Aaru.Core/Media/Detection/MMC.cs @@ -30,8 +30,6 @@ // Copyright © 2011-2022 Natalia Portillo // ****************************************************************************/ - - // ReSharper disable JoinDeclarationAndInitializer namespace Aaru.Core.Media.Detection; @@ -444,9 +442,7 @@ public static class MMC secondSessionFirstTrack = decodedToc.Value.TrackDescriptors.Where(t => t.SessionNumber == 2). Min(t => t.POINT); - if(mediaType == MediaType.CD || - mediaType == MediaType.CDROMXA || - mediaType == MediaType.CDI) + if(mediaType is MediaType.CD or MediaType.CDROMXA or MediaType.CDI) { sense = dev.ReadAtip(out cmdBuf, out _, dev.Timeout, out _); @@ -461,8 +457,7 @@ public static class MMC } } - if(mediaType == MediaType.CD || - mediaType == MediaType.CDROMXA) + if(mediaType is MediaType.CD or MediaType.CDROMXA) { var hasDataTrack = false; var hasAudioTrack = false; @@ -560,7 +555,7 @@ public static class MMC } } - if((mediaType == MediaType.CD || mediaType == MediaType.CDROM) && hasDataTrack) + if(mediaType is MediaType.CD or MediaType.CDROM && hasDataTrack) foreach(uint startAddress in decodedToc.Value.TrackDescriptors. Where(t => t.POINT > 0 && t.POINT <= 0x99 && ((TocControl)(t.CONTROL & 0x0D) == @@ -1016,8 +1011,7 @@ public static class MMC case MediaType.BDROM: case MediaType.UHDBD: case MediaType.Unknown: - if(mediaType == MediaType.BDROM || - mediaType == MediaType.UHDBD) + if(mediaType is MediaType.BDROM or MediaType.UHDBD) { sense = dev.ReadDiscStructure(out cmdBuf, out _, MmcDiscStructureMediaType.Bd, 0, 0, MmcDiscStructureFormat.DiscInformation, 0, dev.Timeout, out _); @@ -1210,9 +1204,7 @@ public static class MMC if(DMI.IsXbox360(cmdBuf)) { // 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 is 25063 or 4229664 or 4246304) // Wxripper unlock { AaruConsole.DebugWriteLine("Media detection", "Found Xbox 360 DMI with {0} blocks, setting disc type to Xbox 360 Game Disc 3 (XGD3)."); @@ -1511,9 +1503,7 @@ public static class MMC AaruConsole.DebugWriteLine("Media-info Command", "PlayStation 2 boot sectors SHA256: {0}", ps2BootSectorsHash); - if(ps2BootSectorsHash == PS2_PAL_HASH || - ps2BootSectorsHash == PS2_NTSC_HASH || - ps2BootSectorsHash == PS2_JAPANESE_HASH) + if(ps2BootSectorsHash is PS2_PAL_HASH or PS2_NTSC_HASH or PS2_JAPANESE_HASH) { mediaType = MediaType.PS2CD; @@ -1992,8 +1982,7 @@ public static class MMC } // Third part must be bigger or equal to 1 and smaller or equal to 8 - if(split[2].Length < 1 || - split[2].Length > 8) + if(split[2].Length is < 1 or > 8) { correctNeoGeoCd = false; @@ -2071,8 +2060,7 @@ public static class MMC if(name.EndsWith(";1", StringComparison.InvariantCulture)) name = name.Substring(0, name.Length - 2); - if(name == "INFO.VCD" || - name == "INFO.SVD") + if(name is "INFO.VCD" or "INFO.SVD") { infoPos = BitConverter.ToUInt32(isoSector, vcdPos + 2); @@ -2329,9 +2317,7 @@ public static class MMC AaruConsole.DebugWriteLine("Media-info Command", "PlayStation 2 boot sectors SHA256: {0}", ps2BootSectorsHash); - if(ps2BootSectorsHash == PS2_PAL_HASH || - ps2BootSectorsHash == PS2_NTSC_HASH || - ps2BootSectorsHash == PS2_JAPANESE_HASH) + if(ps2BootSectorsHash is PS2_PAL_HASH or PS2_NTSC_HASH or PS2_JAPANESE_HASH) { AaruConsole.DebugWriteLine("Media detection", "Found Sony PlayStation 2 boot sectors, setting disc type to PS2 DVD."); diff --git a/Aaru.Core/Media/Info/ScsiInfo.cs b/Aaru.Core/Media/Info/ScsiInfo.cs index 88b2f1943..68996f869 100644 --- a/Aaru.Core/Media/Info/ScsiInfo.cs +++ b/Aaru.Core/Media/Info/ScsiInfo.cs @@ -204,9 +204,8 @@ public sealed class ScsiInfo if(!sense) ReadCapacity16 = cmdBuf; - if(ReadCapacity == null || - Blocks == 0xFFFFFFFF || - Blocks == 0) + if(ReadCapacity == null || + Blocks is 0xFFFFFFFF or 0) { if(ReadCapacity16 == null && Blocks == 0) @@ -301,7 +300,7 @@ public sealed class ScsiInfo Sense.PrettifySense(senseBuf)); if(dev.IsUsb && - (scsiMediumType == 0x40 || scsiMediumType == 0x41 || scsiMediumType == 0x42)) + scsiMediumType is 0x40 or 0x41 or 0x42) MediaType = MediaType.FlashDrive; } else @@ -496,23 +495,11 @@ public sealed class ScsiInfo */ #region All DVD and HD DVD types - if(MediaType == MediaType.DVDDownload || - MediaType == MediaType.DVDPR || - MediaType == MediaType.DVDPRDL || - MediaType == MediaType.DVDPRW || - MediaType == MediaType.DVDPRWDL || - MediaType == MediaType.DVDR || - MediaType == MediaType.DVDRAM || - MediaType == MediaType.DVDRDL || - MediaType == MediaType.DVDROM || - MediaType == MediaType.DVDRW || - MediaType == MediaType.DVDRWDL || - MediaType == MediaType.HDDVDR || - MediaType == MediaType.HDDVDRAM || - MediaType == MediaType.HDDVDRDL || - MediaType == MediaType.HDDVDROM || - MediaType == MediaType.HDDVDRW || - MediaType == MediaType.HDDVDRWDL) + if(MediaType is MediaType.DVDDownload or MediaType.DVDPR or MediaType.DVDPRDL or MediaType.DVDPRW + or MediaType.DVDPRWDL or MediaType.DVDR or MediaType.DVDRAM or MediaType.DVDRDL + or MediaType.DVDROM or MediaType.DVDRW or MediaType.DVDRWDL or MediaType.HDDVDR + or MediaType.HDDVDRAM or MediaType.HDDVDRDL or MediaType.HDDVDROM or MediaType.HDDVDRW + or MediaType.HDDVDRWDL) { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out _); @@ -608,9 +595,7 @@ public sealed class ScsiInfo MediaType = 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 is 25063 or 4229664 or 4246304) // Wxripper unlock MediaType = MediaType.XGD3; } } @@ -618,8 +603,7 @@ public sealed class ScsiInfo #endregion All DVD and HD DVD types #region DVD-ROM - if(MediaType == MediaType.DVDDownload || - MediaType == MediaType.DVDROM) + if(MediaType is MediaType.DVDDownload or MediaType.DVDROM) { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.CopyrightInformation, 0, dev.Timeout, out _); @@ -786,10 +770,7 @@ public sealed class ScsiInfo #endregion Require drive authentication, won't work #region DVD-R and DVD-RW - if(MediaType == MediaType.DVDR || - MediaType == MediaType.DVDRW || - MediaType == MediaType.DVDRDL || - MediaType == MediaType.DVDRWDL) + if(MediaType is MediaType.DVDR or MediaType.DVDRW or MediaType.DVDRDL or MediaType.DVDRWDL) { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.PreRecordedInfo, 0, dev.Timeout, out _); @@ -906,10 +887,7 @@ public sealed class ScsiInfo #endregion HD DVD-R #region DVD-R DL, DVD-RW DL, DVD+R DL, DVD+RW DL - if(MediaType == MediaType.DVDPRDL || - MediaType == MediaType.DVDRDL || - MediaType == MediaType.DVDRWDL || - MediaType == MediaType.DVDPRWDL) + if(MediaType is MediaType.DVDPRDL or MediaType.DVDRDL or MediaType.DVDRWDL or MediaType.DVDPRWDL) { sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.Dvd, 0, 0, MmcDiscStructureFormat.DvdrLayerCapacity, 0, dev.Timeout, out _); @@ -1423,7 +1401,7 @@ public sealed class ScsiInfo MediaType = MediaType.GENERIC_HDD; if(DeviceInfo.ScsiType != PeripheralDeviceTypes.MultiMediaDevice || - dev.IsUsb && (scsiMediumType == 0x40 || scsiMediumType == 0x41 || scsiMediumType == 0x42)) + dev.IsUsb && scsiMediumType is 0x40 or 0x41 or 0x42) return; sense = dev.ReadDiscInformation(out cmdBuf, out senseBuf, MmcDiscInformationDataTypes.DiscInformation, diff --git a/Aaru.Core/Sidecar/BlockMedia.cs b/Aaru.Core/Sidecar/BlockMedia.cs index bfd9f9215..c3f322014 100644 --- a/Aaru.Core/Sidecar/BlockMedia.cs +++ b/Aaru.Core/Sidecar/BlockMedia.cs @@ -1000,7 +1000,7 @@ public sealed partial class Sidecar catch(NotImplementedException) {} if(image.Info.Heads == 2 && scpImage.Header.heads == 0 || - image.Info.Heads == 1 && (scpImage.Header.heads == 1 || scpImage.Header.heads == 2)) + image.Info.Heads == 1 && scpImage.Header.heads is 1 or 2) if(scpImage.Header.end + 1 >= image.Info.Cylinders) { List scpBlockTrackTypes = new(); diff --git a/Aaru.Core/Sidecar/OpticalDisc.cs b/Aaru.Core/Sidecar/OpticalDisc.cs index 2545b189f..aeb87d2e6 100644 --- a/Aaru.Core/Sidecar/OpticalDisc.cs +++ b/Aaru.Core/Sidecar/OpticalDisc.cs @@ -778,9 +778,7 @@ public sealed partial class Sidecar { ulong blocks = sidecar.OpticalDisc[0].Track[0].EndSector - sidecar.OpticalDisc[0].Track[0].StartSector + 1; - if(blocks == 25063 || // Locked (or non compatible drive) - blocks == 4229664 || // Xtreme unlock - blocks == 4246304) // Wxripper unlock + if(blocks is 25063 or 4229664 or 4246304) // Wxripper unlock dskType = MediaType.XGD3; } diff --git a/Aaru.Decoders b/Aaru.Decoders index bd76adc35..4d4905442 160000 --- a/Aaru.Decoders +++ b/Aaru.Decoders @@ -1 +1 @@ -Subproject commit bd76adc35e1536654fead662288b0fd82b0d061f +Subproject commit 4d49054428c08f134f3e2270b26f5913306f0ba6 diff --git a/Aaru.Decryption b/Aaru.Decryption index 7d64becec..cdeb6bd0c 160000 --- a/Aaru.Decryption +++ b/Aaru.Decryption @@ -1 +1 @@ -Subproject commit 7d64becec8791e6f95cd3e62dd496f4406857795 +Subproject commit cdeb6bd0cf3e197d1e9cb78ead53dd2ff6f64373 diff --git a/Aaru.Devices/Command.cs b/Aaru.Devices/Command.cs index d54d03af4..821c45b51 100644 --- a/Aaru.Devices/Command.cs +++ b/Aaru.Devices/Command.cs @@ -30,8 +30,6 @@ // Copyright © 2011-2022 Natalia Portillo // ****************************************************************************/ - - // ReSharper disable UnusedMember.Global namespace Aaru.Devices; @@ -193,7 +191,7 @@ static class Command case PlatformID.Win32NT: { if(Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor == 1 && - (Environment.OSVersion.ServicePack == "Service Pack 1" || Environment.OSVersion.ServicePack == "") || + Environment.OSVersion.ServicePack is "Service Pack 1" or "" || Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor == 0) throw new InvalidOperationException("Windows XP or earlier is not supported."); @@ -261,7 +259,7 @@ static class Command case PlatformID.Win32NT: { if(Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor == 1 && - (Environment.OSVersion.ServicePack == "Service Pack 1" || Environment.OSVersion.ServicePack == "") || + Environment.OSVersion.ServicePack is "Service Pack 1" or "" || Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor == 0) throw new InvalidOperationException("Windows XP or earlier is not supported."); diff --git a/Aaru.Devices/Device/Constructor.cs b/Aaru.Devices/Device/Constructor.cs index 3abea867b..6853063d8 100644 --- a/Aaru.Devices/Device/Constructor.cs +++ b/Aaru.Devices/Device/Constructor.cs @@ -85,8 +85,7 @@ public sealed partial class Device aaruUri = null; } - if(aaruUri?.Scheme == "dic" || - aaruUri?.Scheme == "aaru") + if(aaruUri?.Scheme is "dic" or "aaru") { devicePath = aaruUri.AbsolutePath; @@ -128,8 +127,7 @@ public sealed partial class Device { LastError = Marshal.GetLastWin32Error(); - if(LastError == 13 || - LastError == 30) // EACCES or EROFS + if(LastError is 13 or 30) // EACCES or EROFS { FileHandle = Linux.Extern.open(devicePath, FileFlags.Readonly | FileFlags.NonBlocking); diff --git a/Aaru.Filesystems/Acorn.cs b/Aaru.Filesystems/Acorn.cs index b56305d42..b632a3cfc 100644 --- a/Aaru.Filesystems/Acorn.cs +++ b/Aaru.Filesystems/Acorn.cs @@ -271,8 +271,7 @@ public sealed class AcornADFS : IFilesystem AaruConsole.DebugWriteLine("ADFS Plugin", "IsNullOrEmpty(drSb.reserved) = {0}", ArrayHelpers.ArrayIsNullOrEmpty(drSb.reserved)); - if(drSb.log2secsize < 8 || - drSb.log2secsize > 10) + if(drSb.log2secsize is < 8 or > 10) return false; if(drSb.idlen < drSb.log2secsize + 3 || @@ -540,8 +539,7 @@ public sealed class AcornADFS : IFilesystem AaruConsole.DebugWriteLine("ADFS Plugin", "drSb.format_version = {0}", drSb.format_version); AaruConsole.DebugWriteLine("ADFS Plugin", "drSb.root_size = {0}", drSb.root_size); - if(drSb.log2secsize < 8 || - drSb.log2secsize > 10) + if(drSb.log2secsize is < 8 or > 10) return; if(drSb.idlen < drSb.log2secsize + 3 || diff --git a/Aaru.Filesystems/AppleHFS/Info.cs b/Aaru.Filesystems/AppleHFS/Info.cs index 00a1b591d..2da9ed7ad 100644 --- a/Aaru.Filesystems/AppleHFS/Info.cs +++ b/Aaru.Filesystems/AppleHFS/Info.cs @@ -55,9 +55,7 @@ public sealed partial class AppleHFS ushort drSigWord; ErrorNumber errno; - if(imagePlugin.Info.SectorSize == 2352 || - imagePlugin.Info.SectorSize == 2448 || - imagePlugin.Info.SectorSize == 2048) + if(imagePlugin.Info.SectorSize is 2352 or 2448 or 2048) { errno = imagePlugin.ReadSectors(partition.Start, 2, out mdbSector); @@ -117,9 +115,7 @@ public sealed partial class AppleHFS var apmFromHddOnCd = false; - if(imagePlugin.Info.SectorSize == 2352 || - imagePlugin.Info.SectorSize == 2448 || - imagePlugin.Info.SectorSize == 2048) + if(imagePlugin.Info.SectorSize is 2352 or 2448 or 2048) { errno = imagePlugin.ReadSectors(partition.Start, 2, out byte[] tmpSector); diff --git a/Aaru.Filesystems/AppleHFSPlus.cs b/Aaru.Filesystems/AppleHFSPlus.cs index 9af6ea1c2..8786fbc24 100644 --- a/Aaru.Filesystems/AppleHFSPlus.cs +++ b/Aaru.Filesystems/AppleHFSPlus.cs @@ -110,7 +110,7 @@ public sealed class AppleHFSPlus : IFilesystem drSigWord = BigEndianBitConverter.ToUInt16(vhSector, 0x400); - return drSigWord == AppleCommon.HFSP_MAGIC || drSigWord == AppleCommon.HFSX_MAGIC; + return drSigWord is AppleCommon.HFSP_MAGIC or AppleCommon.HFSX_MAGIC; } /// @@ -193,8 +193,7 @@ public sealed class AppleHFSPlus : IFilesystem vh = Marshal.ByteArrayToStructureBigEndian(vhSector); - if(vh.version == 4 || - vh.version == 5) + if(vh.version is 4 or 5) { sb.AppendFormat("Filesystem version is {0}.", vh.version).AppendLine(); diff --git a/Aaru.Filesystems/BFS.cs b/Aaru.Filesystems/BFS.cs index c482901fd..5847f4a94 100644 --- a/Aaru.Filesystems/BFS.cs +++ b/Aaru.Filesystems/BFS.cs @@ -132,8 +132,7 @@ public sealed class BeFS : IFilesystem besb.magic1 = BigEndianBitConverter.ToUInt32(sbSector, 0x20); - if(besb.magic1 == BEFS_MAGIC1 || - besb.magic1 == BEFS_CIGAM1) // Magic is at offset + if(besb.magic1 is BEFS_MAGIC1 or BEFS_CIGAM1) // Magic is at offset littleEndian = besb.magic1 == BEFS_CIGAM1; else { @@ -144,8 +143,7 @@ public sealed class BeFS : IFilesystem besb.magic1 = BigEndianBitConverter.ToUInt32(sbSector, 0x20); - if(besb.magic1 == BEFS_MAGIC1 || - besb.magic1 == BEFS_CIGAM1) // There is a boot sector + if(besb.magic1 is BEFS_MAGIC1 or BEFS_CIGAM1) // There is a boot sector littleEndian = besb.magic1 == BEFS_CIGAM1; else if(sbSector.Length >= 0x400) { @@ -156,8 +154,7 @@ public sealed class BeFS : IFilesystem besb.magic1 = BigEndianBitConverter.ToUInt32(temp, 0x220); - if(besb.magic1 == BEFS_MAGIC1 || - besb.magic1 == BEFS_CIGAM1) // There is a boot sector + if(besb.magic1 is BEFS_MAGIC1 or BEFS_CIGAM1) // There is a boot sector { littleEndian = besb.magic1 == BEFS_CIGAM1; sbSector = new byte[0x200]; diff --git a/Aaru.Filesystems/CBM.cs b/Aaru.Filesystems/CBM.cs index dcfadc1f2..7c08cce76 100644 --- a/Aaru.Filesystems/CBM.cs +++ b/Aaru.Filesystems/CBM.cs @@ -99,9 +99,9 @@ public sealed class CBM : IFilesystem BAM cbmBam = Marshal.ByteArrayToStructureLittleEndian(sector); - if(cbmBam.dosVersion == 0x41 && - (cbmBam.doubleSided == 0x00 || cbmBam.doubleSided == 0x80) && - cbmBam.unused1 == 0x00 && + if(cbmBam.dosVersion == 0x41 && + cbmBam.doubleSided is 0x00 or 0x80 && + cbmBam.unused1 == 0x00 && cbmBam.directoryTrack == 0x12) return true; } diff --git a/Aaru.Filesystems/Cram.cs b/Aaru.Filesystems/Cram.cs index 9b1731629..36e054853 100644 --- a/Aaru.Filesystems/Cram.cs +++ b/Aaru.Filesystems/Cram.cs @@ -30,8 +30,6 @@ // Copyright © 2011-2022 Natalia Portillo // ****************************************************************************/ - - // ReSharper disable UnusedMember.Local namespace Aaru.Filesystems; @@ -80,7 +78,7 @@ public sealed class Cram : IFilesystem var magic = BitConverter.ToUInt32(sector, 0x00); - return magic == CRAM_MAGIC || magic == CRAM_CIGAM; + return magic is CRAM_MAGIC or CRAM_CIGAM; } /// diff --git a/Aaru.Filesystems/EFS.cs b/Aaru.Filesystems/EFS.cs index 9081d8412..5744f1f92 100644 --- a/Aaru.Filesystems/EFS.cs +++ b/Aaru.Filesystems/EFS.cs @@ -93,8 +93,7 @@ public sealed class EFS : IFilesystem AaruConsole.DebugWriteLine("EFS plugin", "magic at 0x{0:X3} = 0x{1:X8} (expected 0x{2:X8} or 0x{3:X8})", 0x200, sb.sb_magic, EFS_MAGIC, EFS_MAGIC_NEW); - if(sb.sb_magic == EFS_MAGIC || - sb.sb_magic == EFS_MAGIC_NEW) + if(sb.sb_magic is EFS_MAGIC or EFS_MAGIC_NEW) return true; } else @@ -117,8 +116,7 @@ public sealed class EFS : IFilesystem AaruConsole.DebugWriteLine("EFS plugin", "magic at {0} = 0x{1:X8} (expected 0x{2:X8} or 0x{3:X8})", 1, sb.sb_magic, EFS_MAGIC, EFS_MAGIC_NEW); - if(sb.sb_magic == EFS_MAGIC || - sb.sb_magic == EFS_MAGIC_NEW) + if(sb.sb_magic is EFS_MAGIC or EFS_MAGIC_NEW) return true; } diff --git a/Aaru.Filesystems/F2FS.cs b/Aaru.Filesystems/F2FS.cs index 449142b67..d2e9c413b 100644 --- a/Aaru.Filesystems/F2FS.cs +++ b/Aaru.Filesystems/F2FS.cs @@ -71,8 +71,7 @@ public sealed class F2FS : IFilesystem /// public bool Identify(IMediaImage imagePlugin, Partition partition) { - if(imagePlugin.Info.SectorSize < F2FS_MIN_SECTOR || - imagePlugin.Info.SectorSize > F2FS_MAX_SECTOR) + if(imagePlugin.Info.SectorSize is < F2FS_MIN_SECTOR or > F2FS_MAX_SECTOR) return false; uint sbAddr = F2FS_SUPER_OFFSET / imagePlugin.Info.SectorSize; @@ -107,8 +106,7 @@ public sealed class F2FS : IFilesystem Encoding = Encoding.Unicode; information = ""; - if(imagePlugin.Info.SectorSize < F2FS_MIN_SECTOR || - imagePlugin.Info.SectorSize > F2FS_MAX_SECTOR) + if(imagePlugin.Info.SectorSize is < F2FS_MIN_SECTOR or > F2FS_MAX_SECTOR) return; uint sbAddr = F2FS_SUPER_OFFSET / imagePlugin.Info.SectorSize; diff --git a/Aaru.Filesystems/FAT/BPB.cs b/Aaru.Filesystems/FAT/BPB.cs index 054ff9cb3..d0768f520 100644 --- a/Aaru.Filesystems/FAT/BPB.cs +++ b/Aaru.Filesystems/FAT/BPB.cs @@ -145,26 +145,17 @@ public sealed partial class FAT int bitsInBpsFat32 = CountBits.Count(fat32Bpb.bps); int bitsInBpsApricot = CountBits.Count(apricotBpb.mainBPB.bps); - bool correctSpcMsx = msxBpb.spc == 1 || msxBpb.spc == 2 || msxBpb.spc == 4 || msxBpb.spc == 8 || - msxBpb.spc == 16 || msxBpb.spc == 32 || msxBpb.spc == 64; + bool correctSpcMsx = msxBpb.spc is 1 or 2 or 4 or 8 or 16 or 32 or 64; - bool correctSpcDos33 = dos33Bpb.spc == 1 || dos33Bpb.spc == 2 || dos33Bpb.spc == 4 || dos33Bpb.spc == 8 || - dos33Bpb.spc == 16 || dos33Bpb.spc == 32 || dos33Bpb.spc == 64; + bool correctSpcDos33 = dos33Bpb.spc is 1 or 2 or 4 or 8 or 16 or 32 or 64; - bool correctSpcDos40 = ebpb.spc == 1 || ebpb.spc == 2 || ebpb.spc == 4 || ebpb.spc == 8 || ebpb.spc == 16 || - ebpb.spc == 32 || ebpb.spc == 64; + bool correctSpcDos40 = ebpb.spc is 1 or 2 or 4 or 8 or 16 or 32 or 64; - bool correctSpcFat32Short = shortFat32Bpb.spc == 1 || shortFat32Bpb.spc == 2 || shortFat32Bpb.spc == 4 || - shortFat32Bpb.spc == 8 || shortFat32Bpb.spc == 16 || shortFat32Bpb.spc == 32 || - shortFat32Bpb.spc == 64; + bool correctSpcFat32Short = shortFat32Bpb.spc is 1 or 2 or 4 or 8 or 16 or 32 or 64; - bool correctSpcFat32 = fat32Bpb.spc == 1 || fat32Bpb.spc == 2 || fat32Bpb.spc == 4 || fat32Bpb.spc == 8 || - fat32Bpb.spc == 16 || fat32Bpb.spc == 32 || fat32Bpb.spc == 64; + bool correctSpcFat32 = fat32Bpb.spc is 1 or 2 or 4 or 8 or 16 or 32 or 64; - bool correctSpcApricot = apricotBpb.mainBPB.spc == 1 || apricotBpb.mainBPB.spc == 2 || - apricotBpb.mainBPB.spc == 4 || apricotBpb.mainBPB.spc == 8 || - apricotBpb.mainBPB.spc == 16 || apricotBpb.mainBPB.spc == 32 || - apricotBpb.mainBPB.spc == 64; + bool correctSpcApricot = apricotBpb.mainBPB.spc is 1 or 2 or 4 or 8 or 16 or 32 or 64; // This is to support FAT partitions on hybrid ISO/USB images if(imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc) @@ -247,7 +238,7 @@ public sealed partial class FAT ebpb.fats_no <= 2 && ebpb.root_ent > 0 && ebpb.spfat > 0 && - (ebpb.signature == 0x28 || ebpb.signature == 0x29 || andosOemCorrect)) + (ebpb.signature is 0x28 or 0x29 || andosOemCorrect)) { if(ebpb.sectors == 0) { @@ -301,8 +292,7 @@ public sealed partial class FAT if(atariBpb.jump[0] == 0x60 || atariBpb.jump[0] == 0xE9 && atariBpb.jump[1] == 0x00 && Encoding.ASCII.GetString(dos33Bpb.oem_name) != "NEXT " || - partition.Type == "GEM" || - partition.Type == "BGM") + partition.Type is "GEM" or "BGM") { AaruConsole.DebugWriteLine("FAT plugin", "Using Atari BPB"); useAtariBpb = true; diff --git a/Aaru.Filesystems/FAT/Dir.cs b/Aaru.Filesystems/FAT/Dir.cs index 6a83dd283..61c44c85d 100644 --- a/Aaru.Filesystems/FAT/Dir.cs +++ b/Aaru.Filesystems/FAT/Dir.cs @@ -224,7 +224,7 @@ public sealed partial class FAT Dirent = dirent }; - if((_namespace == Namespace.Lfn || _namespace == Namespace.Ecs) && + if(_namespace is Namespace.Lfn or Namespace.Ecs && lastLfnName != null) { byte calculatedLfnChecksum = LfnChecksum(dirent.filename, dirent.extension); @@ -316,8 +316,8 @@ public sealed partial class FAT } // Check OS/2 .LONGNAME - if(_eaCache != null && - (_namespace == Namespace.Os2 || _namespace == Namespace.Ecs) && + if(_eaCache != null && + _namespace is Namespace.Os2 or Namespace.Ecs && !_fat32) { var filesWithEas = currentDirectory.Where(t => t.Value.Dirent.ea_handle != 0).ToList(); diff --git a/Aaru.Filesystems/FAT/Info.cs b/Aaru.Filesystems/FAT/Info.cs index 77200a565..8ecfe7562 100644 --- a/Aaru.Filesystems/FAT/Info.cs +++ b/Aaru.Filesystems/FAT/Info.cs @@ -144,7 +144,7 @@ public sealed partial class FAT if(imagePlugin.Info.SectorSize >= 512) bootable = BitConverter.ToUInt16(bpbSector, 0x1FE); - bool correctSpc = spc == 1 || spc == 2 || spc == 4 || spc == 8 || spc == 16 || spc == 32 || spc == 64; + bool correctSpc = spc is 1 or 2 or 4 or 8 or 16 or 32 or 64; string msxString = Encoding.ASCII.GetString(msxId); string fat32String = Encoding.ASCII.GetString(fat32Id); @@ -185,8 +185,7 @@ public sealed partial class FAT byte apricotMediaDescriptor = bpbSector[0x5A]; var apricotFatSectors = BitConverter.ToUInt16(bpbSector, 0x5B); - bool apricotCorrectSpc = apricotSpc == 1 || apricotSpc == 2 || apricotSpc == 4 || apricotSpc == 8 || - apricotSpc == 16 || apricotSpc == 32 || apricotSpc == 64; + bool apricotCorrectSpc = apricotSpc is 1 or 2 or 4 or 8 or 16 or 32 or 64; int bitsInApricotBps = CountBits.Count(apricotBps); byte apricotPartitions = bpbSector[0x0C]; @@ -258,7 +257,7 @@ public sealed partial class FAT // EBPB case 1 when correctSpc && numberOfFats <= 2 && rootEntries > 0 && fatSectors > 0 && - (bpbSignature == 0x28 || bpbSignature == 0x29): + bpbSignature is 0x28 or 0x29: return sectors == 0 ? bigSectors <= partition.End - partition.Start + 1 : sectors <= partition.End - partition.Start + 1; @@ -905,8 +904,7 @@ public sealed partial class FAT XmlFsType.SystemIdentifier = StringHandlers.CToString(fakeBpb.oem_name, Encoding, start: 1); } - if(fakeBpb.signature == 0x28 || - fakeBpb.signature == 0x29) + if(fakeBpb.signature is 0x28 or 0x29) XmlFsType.VolumeSerial = $"{fakeBpb.serial_no:X8}"; } @@ -952,9 +950,7 @@ public sealed partial class FAT if(fakeBpb.hsectors <= partition.Start) sb.AppendFormat("{0} hidden sectors before BPB.", fakeBpb.hsectors).AppendLine(); - if(fakeBpb.signature == 0x28 || - fakeBpb.signature == 0x29 || - andosOemCorrect) + if(fakeBpb.signature is 0x28 or 0x29 || andosOemCorrect) { sb.AppendFormat("Drive number: 0x{0:X2}", fakeBpb.drive_no).AppendLine(); diff --git a/Aaru.Filesystems/FAT/Super.cs b/Aaru.Filesystems/FAT/Super.cs index 4d6cee924..2dc1520bc 100644 --- a/Aaru.Filesystems/FAT/Super.cs +++ b/Aaru.Filesystems/FAT/Super.cs @@ -466,8 +466,7 @@ public sealed partial class FAT XmlFsType.SystemIdentifier = StringHandlers.CToString(fakeBpb.oem_name, Encoding, start: 1); } - if(fakeBpb.signature == 0x28 || - fakeBpb.signature == 0x29) + if(fakeBpb.signature is 0x28 or 0x29) { XmlFsType.VolumeSerial = $"{fakeBpb.serial_no:X8}"; @@ -485,9 +484,7 @@ public sealed partial class FAT _reservedSectors = fakeBpb.rsectors; _sectorsPerFat = fakeBpb.spfat; - if(fakeBpb.signature == 0x28 || - fakeBpb.signature == 0x29 || - andosOemCorrect) + if(fakeBpb.signature is 0x28 or 0x29 || andosOemCorrect) { if((fakeBpb.flags & 0xF8) == 0x00) if((fakeBpb.flags & 0x01) == 0x01) @@ -702,7 +699,7 @@ public sealed partial class FAT Dirent = entry }; - if((_namespace == Namespace.Lfn || _namespace == Namespace.Ecs) && + if(_namespace is Namespace.Lfn or Namespace.Ecs && lastLfnName != null) { byte calculatedLfnChecksum = LfnChecksum(entry.filename, entry.extension); @@ -1004,8 +1001,8 @@ public sealed partial class FAT _eaCache = new Dictionary>(); // Check OS/2 .LONGNAME - if(_eaCache != null && - (_namespace == Namespace.Os2 || _namespace == Namespace.Ecs) && + if(_eaCache != null && + _namespace is Namespace.Os2 or Namespace.Ecs && !_fat32) { var rootFilesWithEas = _rootDirectoryCache.Where(t => t.Value.Dirent.ea_handle != 0).ToList(); diff --git a/Aaru.Filesystems/FATX/Dir.cs b/Aaru.Filesystems/FATX/Dir.cs index bf1f6bbe3..bbeefe6ef 100644 --- a/Aaru.Filesystems/FATX/Dir.cs +++ b/Aaru.Filesystems/FATX/Dir.cs @@ -132,12 +132,10 @@ public sealed partial class XboxFatPlugin pos += Marshal.SizeOf(); - if(dirent.filenameSize == UNUSED_DIRENTRY || - dirent.filenameSize == FINISHED_DIRENTRY) + if(dirent.filenameSize is UNUSED_DIRENTRY or FINISHED_DIRENTRY) break; - if(dirent.filenameSize == DELETED_DIRENTRY || - dirent.filenameSize > MAX_FILENAME) + if(dirent.filenameSize is DELETED_DIRENTRY or > MAX_FILENAME) continue; string filename = Encoding.GetString(dirent.filename, 0, dirent.filenameSize); diff --git a/Aaru.Filesystems/FATX/File.cs b/Aaru.Filesystems/FATX/File.cs index 3edadd189..b8e29ded3 100644 --- a/Aaru.Filesystems/FATX/File.cs +++ b/Aaru.Filesystems/FATX/File.cs @@ -150,7 +150,7 @@ public sealed partial class XboxFatPlugin if(!_mounted) return ErrorNumber.AccessDenied; - if(_debug && (string.IsNullOrEmpty(path) || path == "$" || path == "/")) + if(_debug && (string.IsNullOrEmpty(path) || path is "$" or "/")) { stat = new FileEntryInfo { diff --git a/Aaru.Filesystems/FATX/Info.cs b/Aaru.Filesystems/FATX/Info.cs index a02860551..6959baa93 100644 --- a/Aaru.Filesystems/FATX/Info.cs +++ b/Aaru.Filesystems/FATX/Info.cs @@ -54,7 +54,7 @@ public sealed partial class XboxFatPlugin Superblock sb = Marshal.ByteArrayToStructureBigEndian(sector); - return sb.magic == FATX_MAGIC || sb.magic == FATX_CIGAM; + return sb.magic is FATX_MAGIC or FATX_CIGAM; } /// diff --git a/Aaru.Filesystems/FATX/Super.cs b/Aaru.Filesystems/FATX/Super.cs index 0b5a59432..d063941f8 100644 --- a/Aaru.Filesystems/FATX/Super.cs +++ b/Aaru.Filesystems/FATX/Super.cs @@ -249,12 +249,10 @@ public sealed partial class XboxFatPlugin pos += Marshal.SizeOf(); - if(entry.filenameSize == UNUSED_DIRENTRY || - entry.filenameSize == FINISHED_DIRENTRY) + if(entry.filenameSize is UNUSED_DIRENTRY or FINISHED_DIRENTRY) break; - if(entry.filenameSize == DELETED_DIRENTRY || - entry.filenameSize > MAX_FILENAME) + if(entry.filenameSize is DELETED_DIRENTRY or > MAX_FILENAME) continue; string filename = Encoding.GetString(entry.filename, 0, entry.filenameSize); diff --git a/Aaru.Filesystems/FFS.cs b/Aaru.Filesystems/FFS.cs index 25424a4c2..38c789b5f 100644 --- a/Aaru.Filesystems/FFS.cs +++ b/Aaru.Filesystems/FFS.cs @@ -116,9 +116,7 @@ public sealed class FFSPlugin : IFilesystem uint sbSizeInSectors; - if(imagePlugin.Info.SectorSize == 2336 || - imagePlugin.Info.SectorSize == 2352 || - imagePlugin.Info.SectorSize == 2448) + if(imagePlugin.Info.SectorSize is 2336 or 2352 or 2448) sbSizeInSectors = block_size / 2048; else sbSizeInSectors = block_size / imagePlugin.Info.SectorSize; @@ -143,14 +141,8 @@ public sealed class FFSPlugin : IFilesystem var magic = BitConverter.ToUInt32(ufsSbSectors, 0x055C); - if(magic == UFS_MAGIC || - magic == UFS_CIGAM || - magic == UFS_MAGIC_BW || - magic == UFS_CIGAM_BW || - magic == UFS2_MAGIC || - magic == UFS2_CIGAM || - magic == UFS_BAD_MAGIC || - magic == UFS_BAD_CIGAM) + if(magic is UFS_MAGIC or UFS_CIGAM or UFS_MAGIC_BW or UFS_CIGAM_BW or UFS2_MAGIC or UFS2_CIGAM + or UFS_BAD_MAGIC or UFS_BAD_CIGAM) return true; } @@ -181,9 +173,7 @@ public sealed class FFSPlugin : IFilesystem var fs_type_sun = false; var fs_type_sun86 = false; - if(imagePlugin.Info.SectorSize == 2336 || - imagePlugin.Info.SectorSize == 2352 || - imagePlugin.Info.SectorSize == 2448) + if(imagePlugin.Info.SectorSize is 2336 or 2352 or 2448) sb_size_in_sectors = block_size / 2048; else sb_size_in_sectors = block_size / imagePlugin.Info.SectorSize; @@ -206,14 +196,8 @@ public sealed class FFSPlugin : IFilesystem magic = BitConverter.ToUInt32(ufs_sb_sectors, 0x055C); - if(magic == UFS_MAGIC || - magic == UFS_CIGAM || - magic == UFS_MAGIC_BW || - magic == UFS_CIGAM_BW || - magic == UFS2_MAGIC || - magic == UFS2_CIGAM || - magic == UFS_BAD_MAGIC || - magic == UFS_BAD_CIGAM) + if(magic is UFS_MAGIC or UFS_CIGAM or UFS_MAGIC_BW or UFS_CIGAM_BW or UFS2_MAGIC or UFS2_CIGAM + or UFS_BAD_MAGIC or UFS_BAD_CIGAM) { sb_offset = partition.Start + loc; diff --git a/Aaru.Filesystems/HAMMER.cs b/Aaru.Filesystems/HAMMER.cs index 9e929f3a4..fcf6245d5 100644 --- a/Aaru.Filesystems/HAMMER.cs +++ b/Aaru.Filesystems/HAMMER.cs @@ -87,7 +87,7 @@ public sealed class HAMMER : IFilesystem var magic = BitConverter.ToUInt64(sbSector, 0); - return magic == HAMMER_FSBUF_VOLUME || magic == HAMMER_FSBUF_VOLUME_REV; + return magic is HAMMER_FSBUF_VOLUME or HAMMER_FSBUF_VOLUME_REV; } /// diff --git a/Aaru.Filesystems/ISO9660/Dir.cs b/Aaru.Filesystems/ISO9660/Dir.cs index 7ba18727a..c700afb43 100644 --- a/Aaru.Filesystems/ISO9660/Dir.cs +++ b/Aaru.Filesystems/ISO9660/Dir.cs @@ -1014,8 +1014,7 @@ public sealed partial class ISO9660 IEnumerable tableEntries; List pathTableList = new(_pathTable); - if(path == "" || - path == "/") + if(path is "" or "/") tableEntries = _pathTable.Where(p => p.Parent == 1 && p != _pathTable[0]); else { diff --git a/Aaru.Filesystems/ISO9660/Info.cs b/Aaru.Filesystems/ISO9660/Info.cs index 56742e911..5e6bb03bf 100644 --- a/Aaru.Filesystems/ISO9660/Info.cs +++ b/Aaru.Filesystems/ISO9660/Info.cs @@ -426,11 +426,9 @@ public sealed partial class ISO9660 break; } - rrip |= nextSignature == RRIP_MAGIC || nextSignature == RRIP_POSIX_ATTRIBUTES || - nextSignature == RRIP_POSIX_DEV_NO || nextSignature == RRIP_SYMLINK || - nextSignature == RRIP_NAME || nextSignature == RRIP_CHILDLINK || - nextSignature == RRIP_PARENTLINK || nextSignature == RRIP_RELOCATED_DIR || - nextSignature == RRIP_TIMESTAMPS || nextSignature == RRIP_SPARSE; + rrip |= nextSignature is RRIP_MAGIC or RRIP_POSIX_ATTRIBUTES or RRIP_POSIX_DEV_NO + or RRIP_SYMLINK or RRIP_NAME or RRIP_CHILDLINK or RRIP_PARENTLINK + or RRIP_RELOCATED_DIR or RRIP_TIMESTAMPS or RRIP_SPARSE; ziso |= nextSignature == ZISO_MAGIC; amiga |= nextSignature == AMIGA_MAGIC; @@ -499,11 +497,9 @@ public sealed partial class ISO9660 break; } - rrip |= nextSignature == RRIP_MAGIC || nextSignature == RRIP_POSIX_ATTRIBUTES || - nextSignature == RRIP_POSIX_DEV_NO || nextSignature == RRIP_SYMLINK || - nextSignature == RRIP_NAME || nextSignature == RRIP_CHILDLINK || - nextSignature == RRIP_PARENTLINK || nextSignature == RRIP_RELOCATED_DIR || - nextSignature == RRIP_TIMESTAMPS || nextSignature == RRIP_SPARSE; + rrip |= nextSignature is RRIP_MAGIC or RRIP_POSIX_ATTRIBUTES or RRIP_POSIX_DEV_NO or RRIP_SYMLINK + or RRIP_NAME or RRIP_CHILDLINK or RRIP_PARENTLINK or RRIP_RELOCATED_DIR + or RRIP_TIMESTAMPS or RRIP_SPARSE; ziso |= nextSignature == ZISO_MAGIC; amiga |= nextSignature == AMIGA_MAGIC; diff --git a/Aaru.Filesystems/ISO9660/Super.cs b/Aaru.Filesystems/ISO9660/Super.cs index c92d9d3ed..fcb83ea85 100644 --- a/Aaru.Filesystems/ISO9660/Super.cs +++ b/Aaru.Filesystems/ISO9660/Super.cs @@ -488,8 +488,7 @@ public sealed partial class ISO9660 Saturn.IPBin? saturn = Saturn.DecodeIPBin(ipbinSector); Dreamcast.IPBin? dreamcast = Dreamcast.DecodeIPBin(ipbinSector); - if(_namespace == Namespace.Joliet || - _namespace == Namespace.Rrip) + if(_namespace is Namespace.Joliet or Namespace.Rrip) { _usePathTable = false; _useTransTbl = false; @@ -509,7 +508,7 @@ public sealed partial class ISO9660 XmlFsType.Type = fsFormat; if(jolietvd != null && - (_namespace == Namespace.Joliet || _namespace == Namespace.Rrip)) + _namespace is Namespace.Joliet or Namespace.Rrip) { rootLocation = jolietvd.Value.root_directory_record.extent; rootXattrLength = jolietvd.Value.root_directory_record.xattr_len; diff --git a/Aaru.Filesystems/LisaFS/Dir.cs b/Aaru.Filesystems/LisaFS/Dir.cs index 653d65849..7b803f1fa 100644 --- a/Aaru.Filesystems/LisaFS/Dir.cs +++ b/Aaru.Filesystems/LisaFS/Dir.cs @@ -105,8 +105,7 @@ public sealed partial class LisaFS _catalogCache = new List(); // Do differently for V1 and V2 - if(_mddf.fsversion == LISA_V2 || - _mddf.fsversion == LISA_V1) + if(_mddf.fsversion is LISA_V2 or LISA_V1) { ErrorNumber error = ReadFile((short)FILEID_CATALOG, out byte[] buf); diff --git a/Aaru.Filesystems/LisaFS/Extent.cs b/Aaru.Filesystems/LisaFS/Extent.cs index eaeb190ef..265263a91 100644 --- a/Aaru.Filesystems/LisaFS/Extent.cs +++ b/Aaru.Filesystems/LisaFS/Extent.cs @@ -75,8 +75,7 @@ public sealed partial class LisaFS ulong ptr = _srecords[fileId].extent_ptr; // An invalid pointer denotes file does not exist - if(ptr == 0xFFFFFFFF || - ptr == 0x00000000) + if(ptr is 0xFFFFFFFF or 0x00000000) return ErrorNumber.NoSuchFile; // Pointers are relative to MDDF diff --git a/Aaru.Filesystems/LisaFS/File.cs b/Aaru.Filesystems/LisaFS/File.cs index 12296019e..da1498beb 100644 --- a/Aaru.Filesystems/LisaFS/File.cs +++ b/Aaru.Filesystems/LisaFS/File.cs @@ -198,8 +198,7 @@ public sealed partial class LisaFS !_debug) return ErrorNumber.AccessDenied; - if(fileId > 4 || - fileId <= 0) + if(fileId is > 4 or <= 0) if(fileId != FILEID_BOOT_SIGNED && fileId != FILEID_LOADER_SIGNED) return ErrorNumber.InvalidArgument; diff --git a/Aaru.Filesystems/Locus.cs b/Aaru.Filesystems/Locus.cs index 7aad335b9..39797c911 100644 --- a/Aaru.Filesystems/Locus.cs +++ b/Aaru.Filesystems/Locus.cs @@ -31,6 +31,7 @@ // ****************************************************************************/ // Commit count + using commitcnt_t = System.Int32; // Disk address @@ -121,10 +122,7 @@ public sealed class Locus : IFilesystem AaruConsole.DebugWriteLine("Locus plugin", "magic at {1} = 0x{0:X8}", locusSb.s_magic, location); - if(locusSb.s_magic == LOCUS_MAGIC || - locusSb.s_magic == LOCUS_CIGAM || - locusSb.s_magic == LOCUS_MAGIC_OLD || - locusSb.s_magic == LOCUS_CIGAM_OLD) + if(locusSb.s_magic is LOCUS_MAGIC or LOCUS_CIGAM or LOCUS_MAGIC_OLD or LOCUS_CIGAM_OLD) return true; } @@ -160,10 +158,7 @@ public sealed class Locus : IFilesystem locusSb = Marshal.ByteArrayToStructureLittleEndian(sector); - if(locusSb.s_magic == LOCUS_MAGIC || - locusSb.s_magic == LOCUS_CIGAM || - locusSb.s_magic == LOCUS_MAGIC_OLD || - locusSb.s_magic == LOCUS_CIGAM_OLD) + if(locusSb.s_magic is LOCUS_MAGIC or LOCUS_CIGAM or LOCUS_MAGIC_OLD or LOCUS_CIGAM_OLD) break; } @@ -175,8 +170,7 @@ public sealed class Locus : IFilesystem return; // Numerical arrays are not important for information so no need to swap them - if(locusSb.s_magic == LOCUS_CIGAM || - locusSb.s_magic == LOCUS_CIGAM_OLD) + if(locusSb.s_magic is LOCUS_CIGAM or LOCUS_CIGAM_OLD) { locusSb = Marshal.ByteArrayToStructureBigEndian(sector); locusSb.s_flags = (Flags)Swapping.Swap((ushort)locusSb.s_flags); diff --git a/Aaru.Filesystems/MinixFS.cs b/Aaru.Filesystems/MinixFS.cs index 1adb4ea19..02fd9945f 100644 --- a/Aaru.Filesystems/MinixFS.cs +++ b/Aaru.Filesystems/MinixFS.cs @@ -110,20 +110,13 @@ public sealed class MinixFS : IFilesystem var magic = BitConverter.ToUInt16(minixSbSector, 0x010); - if(magic == MINIX_MAGIC || - magic == MINIX_MAGIC2 || - magic == MINIX2_MAGIC || - magic == MINIX2_MAGIC2 || - magic == MINIX_CIGAM || - magic == MINIX_CIGAM2 || - magic == MINIX2_CIGAM || - magic == MINIX2_CIGAM2) + if(magic is MINIX_MAGIC or MINIX_MAGIC2 or MINIX2_MAGIC or MINIX2_MAGIC2 or MINIX_CIGAM or MINIX_CIGAM2 + or MINIX2_CIGAM or MINIX2_CIGAM2) return true; magic = BitConverter.ToUInt16(minixSbSector, 0x018); // Here should reside magic number on Minix v3 - return magic == MINIX_MAGIC || magic == MINIX2_MAGIC || magic == MINIX3_MAGIC || magic == MINIX_CIGAM || - magic == MINIX2_CIGAM || magic == MINIX3_CIGAM; + return magic is MINIX_MAGIC or MINIX2_MAGIC or MINIX3_MAGIC or MINIX_CIGAM or MINIX2_CIGAM or MINIX3_CIGAM; } /// @@ -165,15 +158,10 @@ public sealed class MinixFS : IFilesystem bool littleEndian; - if(magic == MINIX3_MAGIC || - magic == MINIX3_CIGAM || - magic == MINIX2_MAGIC || - magic == MINIX2_CIGAM || - magic == MINIX_MAGIC || - magic == MINIX_CIGAM) + if(magic is MINIX3_MAGIC or MINIX3_CIGAM or MINIX2_MAGIC or MINIX2_CIGAM or MINIX_MAGIC or MINIX_CIGAM) { filenamesize = 60; - littleEndian = magic != MINIX3_CIGAM || magic == MINIX2_CIGAM || magic == MINIX_CIGAM; + littleEndian = magic is not MINIX3_CIGAM or MINIX2_CIGAM or MINIX_CIGAM; switch(magic) { diff --git a/Aaru.Filesystems/ODS.cs b/Aaru.Filesystems/ODS.cs index d0fc13d2e..d51399d8d 100644 --- a/Aaru.Filesystems/ODS.cs +++ b/Aaru.Filesystems/ODS.cs @@ -87,8 +87,7 @@ public sealed class ODS : IFilesystem AaruConsole.DebugWriteLine("Files-11 plugin", "magic: \"{0}\"", magic); - if(magic == "DECFILE11A " || - magic == "DECFILE11B ") + if(magic is "DECFILE11A " or "DECFILE11B ") return true; // Optical disc @@ -108,7 +107,7 @@ public sealed class ODS : IFilesystem AaruConsole.DebugWriteLine("Files-11 plugin", "unaligned magic: \"{0}\"", magic); - return magic == "DECFILE11A " || magic == "DECFILE11B "; + return magic is "DECFILE11A " or "DECFILE11B "; } /// diff --git a/Aaru.Filesystems/Opera/File.cs b/Aaru.Filesystems/Opera/File.cs index 607ce5299..2f993624c 100644 --- a/Aaru.Filesystems/Opera/File.cs +++ b/Aaru.Filesystems/Opera/File.cs @@ -123,9 +123,7 @@ public sealed partial class OperaFS uint fileBlockSizeRatio; - if(_image.Info.SectorSize == 2336 || - _image.Info.SectorSize == 2352 || - _image.Info.SectorSize == 2448) + if(_image.Info.SectorSize is 2336 or 2352 or 2448) fileBlockSizeRatio = entry.Entry.block_size / 2048; else fileBlockSizeRatio = entry.Entry.block_size / _image.Info.SectorSize; diff --git a/Aaru.Filesystems/Opera/Info.cs b/Aaru.Filesystems/Opera/Info.cs index 7c5345fcc..01bcc7575 100644 --- a/Aaru.Filesystems/Opera/Info.cs +++ b/Aaru.Filesystems/Opera/Info.cs @@ -101,9 +101,7 @@ public sealed partial class OperaFS superBlockMetadata.AppendFormat("Volume identifier: 0x{0:X8}", sb.volume_id).AppendLine(); superBlockMetadata.AppendFormat("Block size: {0} bytes", sb.block_size).AppendLine(); - if(imagePlugin.Info.SectorSize == 2336 || - imagePlugin.Info.SectorSize == 2352 || - imagePlugin.Info.SectorSize == 2448) + if(imagePlugin.Info.SectorSize is 2336 or 2352 or 2448) { if(sb.block_size != 2048) superBlockMetadata. diff --git a/Aaru.Filesystems/Opera/Super.cs b/Aaru.Filesystems/Opera/Super.cs index 8ab91380d..84a9f57d0 100644 --- a/Aaru.Filesystems/Opera/Super.cs +++ b/Aaru.Filesystems/Opera/Super.cs @@ -69,9 +69,7 @@ public sealed partial class OperaFS if(Encoding.ASCII.GetString(sb.sync_bytes) != SYNC) return ErrorNumber.InvalidArgument; - if(imagePlugin.Info.SectorSize == 2336 || - imagePlugin.Info.SectorSize == 2352 || - imagePlugin.Info.SectorSize == 2448) + if(imagePlugin.Info.SectorSize is 2336 or 2352 or 2448) _volumeBlockSizeRatio = sb.block_size / 2048; else _volumeBlockSizeRatio = sb.block_size / imagePlugin.Info.SectorSize; diff --git a/Aaru.Filesystems/PFS.cs b/Aaru.Filesystems/PFS.cs index a5ad49001..e4b654cc3 100644 --- a/Aaru.Filesystems/PFS.cs +++ b/Aaru.Filesystems/PFS.cs @@ -30,8 +30,6 @@ // Copyright © 2011-2022 Natalia Portillo // ****************************************************************************/ - - // ReSharper disable UnusedType.Local namespace Aaru.Filesystems; @@ -85,8 +83,7 @@ public sealed class PFS : IFilesystem var magic = BigEndianBitConverter.ToUInt32(sector, 0x00); - return magic == AFS_DISK || magic == PFS2_DISK || magic == PFS_DISK || magic == MUAF_DISK || - magic == MUPFS_DISK; + return magic is AFS_DISK or PFS2_DISK or PFS_DISK or MUAF_DISK or MUPFS_DISK; } /// @@ -125,8 +122,7 @@ public sealed class PFS : IFilesystem break; } - if(rootBlock.diskType == MUAF_DISK || - rootBlock.diskType == MUPFS_DISK) + if(rootBlock.diskType is MUAF_DISK or MUPFS_DISK) sbInformation.Append(", with multi-user support"); sbInformation.AppendLine(); diff --git a/Aaru.Filesystems/ProDOS.cs b/Aaru.Filesystems/ProDOS.cs index 542ee4f53..82e139d2f 100644 --- a/Aaru.Filesystems/ProDOS.cs +++ b/Aaru.Filesystems/ProDOS.cs @@ -30,8 +30,6 @@ // Copyright © 2011-2022 Natalia Portillo // ****************************************************************************/ - - // ReSharper disable NotAccessedField.Local namespace Aaru.Filesystems; @@ -111,9 +109,7 @@ public sealed class ProDOSPlugin : IFilesystem var apmFromHddOnCd = false; - if(imagePlugin.Info.SectorSize == 2352 || - imagePlugin.Info.SectorSize == 2448 || - imagePlugin.Info.SectorSize == 2048) + if(imagePlugin.Info.SectorSize is 2352 or 2448 or 2048) { errno = imagePlugin.ReadSectors(partition.Start, 2, out byte[] tmp); @@ -192,9 +188,7 @@ public sealed class ProDOSPlugin : IFilesystem var apmFromHddOnCd = false; - if(imagePlugin.Info.SectorSize == 2352 || - imagePlugin.Info.SectorSize == 2448 || - imagePlugin.Info.SectorSize == 2048) + if(imagePlugin.Info.SectorSize is 2352 or 2448 or 2048) { errno = imagePlugin.ReadSectors(partition.Start, 2, out byte[] tmp); diff --git a/Aaru.Filesystems/RBF.cs b/Aaru.Filesystems/RBF.cs index 36f605055..d75a8f123 100644 --- a/Aaru.Filesystems/RBF.cs +++ b/Aaru.Filesystems/RBF.cs @@ -101,9 +101,8 @@ public sealed class RBF : IFilesystem "magic at {0} = 0x{1:X8} or 0x{2:X8} (expected 0x{3:X8} or 0x{4:X8})", location, rbfSb.dd_sync, rbf9000Sb.rid_sync, RBF_SYNC, RBF_CNYS); - if(rbfSb.dd_sync == RBF_SYNC || - rbf9000Sb.rid_sync == RBF_SYNC || - rbf9000Sb.rid_sync == RBF_CNYS) + if(rbfSb.dd_sync == RBF_SYNC || + rbf9000Sb.rid_sync is RBF_SYNC or RBF_CNYS) return true; } @@ -148,9 +147,8 @@ public sealed class RBF : IFilesystem "magic at {0} = 0x{1:X8} or 0x{2:X8} (expected 0x{3:X8} or 0x{4:X8})", location, rbfSb.dd_sync, rbf9000Sb.rid_sync, RBF_SYNC, RBF_CNYS); - if(rbfSb.dd_sync == RBF_SYNC || - rbf9000Sb.rid_sync == RBF_SYNC || - rbf9000Sb.rid_sync == RBF_CNYS) + if(rbfSb.dd_sync == RBF_SYNC || + rbf9000Sb.rid_sync is RBF_SYNC or RBF_CNYS) break; } diff --git a/Aaru.Filesystems/SFS.cs b/Aaru.Filesystems/SFS.cs index f20c3eb1a..fc552afb9 100644 --- a/Aaru.Filesystems/SFS.cs +++ b/Aaru.Filesystems/SFS.cs @@ -75,7 +75,7 @@ public sealed class SFS : IFilesystem var magic = BigEndianBitConverter.ToUInt32(sector, 0x00); - return magic == SFS_MAGIC || magic == SFS2_MAGIC; + return magic is SFS_MAGIC or SFS2_MAGIC; } /// diff --git a/Aaru.Filesystems/SolarFS.cs b/Aaru.Filesystems/SolarFS.cs index 8bc09c1b0..172430aea 100644 --- a/Aaru.Filesystems/SolarFS.cs +++ b/Aaru.Filesystems/SolarFS.cs @@ -148,9 +148,7 @@ public sealed class SolarFS : IFilesystem sb.AppendFormat("Media descriptor: 0x{0:X2}", bpb.media).AppendLine(); sb.AppendFormat("{0} bytes per sector", bpb.bps).AppendLine(); - if(imagePlugin.Info.SectorSize == 2336 || - imagePlugin.Info.SectorSize == 2352 || - imagePlugin.Info.SectorSize == 2448) + if(imagePlugin.Info.SectorSize is 2336 or 2352 or 2448) { if(bpb.bps != imagePlugin.Info.SectorSize) sb. diff --git a/Aaru.Filesystems/Squash.cs b/Aaru.Filesystems/Squash.cs index ade29ef9f..b5678059b 100644 --- a/Aaru.Filesystems/Squash.cs +++ b/Aaru.Filesystems/Squash.cs @@ -74,7 +74,7 @@ public sealed class Squash : IFilesystem var magic = BitConverter.ToUInt32(sector, 0x00); - return magic == SQUASH_MAGIC || magic == SQUASH_CIGAM; + return magic is SQUASH_MAGIC or SQUASH_CIGAM; } /// diff --git a/Aaru.Filesystems/SysV.cs b/Aaru.Filesystems/SysV.cs index c634497f9..0ed84bd2f 100644 --- a/Aaru.Filesystems/SysV.cs +++ b/Aaru.Filesystems/SysV.cs @@ -30,8 +30,6 @@ // Copyright © 2011-2022 Natalia Portillo // ****************************************************************************/ - - // ReSharper disable NotAccessedField.Local namespace Aaru.Filesystems; @@ -128,22 +126,17 @@ public sealed class SysVfs : IFilesystem var magic = BitConverter.ToUInt32(sb_sector, 0x3F8); - if(magic == XENIX_MAGIC || - magic == XENIX_CIGAM || - magic == SYSV_MAGIC || - magic == SYSV_CIGAM) + if(magic is XENIX_MAGIC or XENIX_CIGAM or SYSV_MAGIC or SYSV_CIGAM) return true; magic = BitConverter.ToUInt32(sb_sector, 0x1F8); // System V magic location - if(magic == SYSV_MAGIC || - magic == SYSV_CIGAM) + if(magic is SYSV_MAGIC or SYSV_CIGAM) return true; magic = BitConverter.ToUInt32(sb_sector, 0x1F0); // XENIX 3 magic location - if(magic == XENIX_MAGIC || - magic == XENIX_CIGAM) + if(magic is XENIX_MAGIC or XENIX_CIGAM) return true; var coherent_string = new byte[6]; @@ -162,12 +155,9 @@ public sealed class SysVfs : IFilesystem var s_nfree = BitConverter.ToUInt16(sb_sector, 0x006); var s_ninode = BitConverter.ToUInt16(sb_sector, 0x0D0); - if(s_fsize <= 0 || - s_fsize >= 0xFFFFFFFF || - s_nfree <= 0 || - s_nfree >= 0xFFFF || - s_ninode <= 0 || - s_ninode >= 0xFFFF) + if(s_fsize is <= 0 or >= 0xFFFFFFFF || + s_nfree is <= 0 or >= 0xFFFF || + s_ninode is <= 0 or >= 0xFFFF) continue; if((s_fsize & 0xFF) == 0x00 && @@ -247,8 +237,7 @@ public sealed class SysVfs : IFilesystem var magic = BitConverter.ToUInt32(sb_sector, 0x3F8); - if(magic == XENIX_MAGIC || - magic == SYSV_MAGIC) + if(magic is XENIX_MAGIC or SYSV_MAGIC) { if(magic == SYSV_MAGIC) { @@ -263,8 +252,7 @@ public sealed class SysVfs : IFilesystem break; } - if(magic == XENIX_CIGAM || - magic == SYSV_CIGAM) + if(magic is XENIX_CIGAM or SYSV_CIGAM) { bigEndian = true; // Big endian @@ -340,12 +328,9 @@ public sealed class SysVfs : IFilesystem var s_nfree = BitConverter.ToUInt16(sb_sector, 0x006); var s_ninode = BitConverter.ToUInt16(sb_sector, 0x0D0); - if(s_fsize <= 0 || - s_fsize >= 0xFFFFFFFF || - s_nfree <= 0 || - s_nfree >= 0xFFFF || - s_ninode <= 0 || - s_ninode >= 0xFFFF) + if(s_fsize is <= 0 or >= 0xFFFFFFFF || + s_nfree is <= 0 or >= 0xFFFF || + s_ninode is <= 0 or >= 0xFFFF) continue; if((s_fsize & 0xFF) == 0x00 && @@ -495,9 +480,7 @@ public sealed class SysVfs : IFilesystem break; } - if(imagePlugin.Info.SectorSize == 2336 || - imagePlugin.Info.SectorSize == 2352 || - imagePlugin.Info.SectorSize == 2448) + if(imagePlugin.Info.SectorSize is 2336 or 2352 or 2448) { if(bs != 2048) sb. diff --git a/Aaru.Filesystems/ZFS.cs b/Aaru.Filesystems/ZFS.cs index 913ff4e1a..ede2119c7 100644 --- a/Aaru.Filesystems/ZFS.cs +++ b/Aaru.Filesystems/ZFS.cs @@ -111,8 +111,7 @@ public sealed class ZFS : IFilesystem magic = BitConverter.ToUInt64(sector, 0x1D8); - if(magic == ZEC_MAGIC || - magic == ZEC_CIGAM) + if(magic is ZEC_MAGIC or ZEC_CIGAM) return true; } @@ -126,7 +125,7 @@ public sealed class ZFS : IFilesystem magic = BitConverter.ToUInt64(sector, 0x1D8); - return magic == ZEC_MAGIC || magic == ZEC_CIGAM; + return magic is ZEC_MAGIC or ZEC_CIGAM; } /// @@ -155,8 +154,7 @@ public sealed class ZFS : IFilesystem magic = BitConverter.ToUInt64(sector, 0x1D8); - if(magic == ZEC_MAGIC || - magic == ZEC_CIGAM) + if(magic is ZEC_MAGIC or ZEC_CIGAM) nvlistOff = 32; } @@ -169,8 +167,7 @@ public sealed class ZFS : IFilesystem magic = BitConverter.ToUInt64(sector, 0x1D8); - if(magic == ZEC_MAGIC || - magic == ZEC_CIGAM) + if(magic is ZEC_MAGIC or ZEC_CIGAM) nvlistOff = 17; } diff --git a/Aaru.Filesystems/dump.cs b/Aaru.Filesystems/dump.cs index 86f555b54..df1426c13 100644 --- a/Aaru.Filesystems/dump.cs +++ b/Aaru.Filesystems/dump.cs @@ -134,9 +134,9 @@ public sealed class dump : IFilesystem AaruConsole.DebugWriteLine("dump(8) plugin", "aix magic = 0x{0:X8}", aixHdr.c_magic); AaruConsole.DebugWriteLine("dump(8) plugin", "new magic = 0x{0:X8}", newHdr.c_magic); - return oldHdr.c_magic == OFS_MAGIC || aixHdr.c_magic == XIX_MAGIC || aixHdr.c_magic == XIX_CIGAM || - newHdr.c_magic == OFS_MAGIC || newHdr.c_magic == NFS_MAGIC || newHdr.c_magic == OFS_CIGAM || - newHdr.c_magic == NFS_CIGAM || newHdr.c_magic == UFS2_MAGIC || newHdr.c_magic == UFS2_CIGAM; + return oldHdr.c_magic == OFS_MAGIC || aixHdr.c_magic is XIX_MAGIC or XIX_CIGAM || newHdr.c_magic == OFS_MAGIC || + newHdr.c_magic == NFS_MAGIC || newHdr.c_magic == OFS_CIGAM || newHdr.c_magic == NFS_CIGAM || + newHdr.c_magic == UFS2_MAGIC || newHdr.c_magic == UFS2_CIGAM; } /// @@ -183,8 +183,7 @@ public sealed class dump : IFilesystem newHdr.c_magic == UFS2_CIGAM) newHdr = Marshal.ByteArrayToStructureBigEndian(sector); } - else if(aixHdr.c_magic == XIX_MAGIC || - aixHdr.c_magic == XIX_CIGAM) + else if(aixHdr.c_magic is XIX_MAGIC or XIX_CIGAM) { useAix = true; diff --git a/Aaru.Filesystems/ext2FS.cs b/Aaru.Filesystems/ext2FS.cs index 5046f0aa2..740a899bb 100644 --- a/Aaru.Filesystems/ext2FS.cs +++ b/Aaru.Filesystems/ext2FS.cs @@ -47,6 +47,7 @@ using Marshal = Aaru.Helpers.Marshal; /// /// Implements detection of the Linux extended filesystem v2, v3 and v4 [SuppressMessage("ReSharper", "UnusedMember.Local")] + // ReSharper disable once InconsistentNaming public sealed class ext2FS : IFilesystem { @@ -148,6 +149,7 @@ public sealed class ext2FS : IFilesystem /// Volume use extents *ext4* const uint EXT4_FEATURE_INCOMPAT_EXTENTS = 0x00000040; /// Supports volumes bigger than 2^32 blocks *ext4* + // ReSharper disable once InconsistentNaming const uint EXT4_FEATURE_INCOMPAT_64BIT = 0x00000080; /// Multi-mount protection *ext4* @@ -208,7 +210,7 @@ public sealed class ext2FS : IFilesystem var magic = BitConverter.ToUInt16(sb, 0x038); - return magic == EXT2_MAGIC || magic == EXT2_MAGIC_OLD; + return magic is EXT2_MAGIC or EXT2_MAGIC_OLD; } /// diff --git a/Aaru.Filters/AppleDouble.cs b/Aaru.Filters/AppleDouble.cs index 2659c4052..b271a675b 100644 --- a/Aaru.Filters/AppleDouble.cs +++ b/Aaru.Filters/AppleDouble.cs @@ -189,7 +189,7 @@ public sealed class AppleDouble : IFilter prodosStream.Close(); if(_header.magic == MAGIC && - (_header.version == VERSION || _header.version == VERSION2)) + _header.version is VERSION or VERSION2) return true; } } @@ -207,7 +207,7 @@ public sealed class AppleDouble : IFilter unixStream.Close(); if(_header.magic == MAGIC && - (_header.version == VERSION || _header.version == VERSION2)) + _header.version is VERSION or VERSION2) return true; } } @@ -225,7 +225,7 @@ public sealed class AppleDouble : IFilter dosStream.Close(); if(_header.magic == MAGIC && - (_header.version == VERSION || _header.version == VERSION2)) + _header.version is VERSION or VERSION2) return true; } } @@ -243,7 +243,7 @@ public sealed class AppleDouble : IFilter doslStream.Close(); if(_header.magic == MAGIC && - (_header.version == VERSION || _header.version == VERSION2)) + _header.version is VERSION or VERSION2) return true; } } @@ -261,7 +261,7 @@ public sealed class AppleDouble : IFilter netatalkStream.Close(); if(_header.magic == MAGIC && - (_header.version == VERSION || _header.version == VERSION2)) + _header.version is VERSION or VERSION2) return true; } } @@ -279,7 +279,7 @@ public sealed class AppleDouble : IFilter daveStream.Close(); if(_header.magic == MAGIC && - (_header.version == VERSION || _header.version == VERSION2)) + _header.version is VERSION or VERSION2) return true; } } @@ -297,7 +297,7 @@ public sealed class AppleDouble : IFilter osxStream.Close(); if(_header.magic == MAGIC && - (_header.version == VERSION || _header.version == VERSION2)) + _header.version is VERSION or VERSION2) return true; } } @@ -316,7 +316,7 @@ public sealed class AppleDouble : IFilter _header = Marshal.ByteArrayToStructureBigEndian
(unarB); unarStream.Close(); - return _header.magic == MAGIC && (_header.version == VERSION || _header.version == VERSION2); + return _header.magic == MAGIC && _header.version is VERSION or VERSION2; } // Now way to have two files in a single byte array @@ -377,7 +377,7 @@ public sealed class AppleDouble : IFilter prodosStream.Close(); if(_header.magic == MAGIC && - (_header.version == VERSION || _header.version == VERSION2)) + _header.version is VERSION or VERSION2) _headerPath = proDosAppleDouble; } } @@ -395,7 +395,7 @@ public sealed class AppleDouble : IFilter unixStream.Close(); if(_header.magic == MAGIC && - (_header.version == VERSION || _header.version == VERSION2)) + _header.version is VERSION or VERSION2) _headerPath = unixAppleDouble; } } @@ -413,7 +413,7 @@ public sealed class AppleDouble : IFilter dosStream.Close(); if(_header.magic == MAGIC && - (_header.version == VERSION || _header.version == VERSION2)) + _header.version is VERSION or VERSION2) _headerPath = dosAppleDouble; } } @@ -431,7 +431,7 @@ public sealed class AppleDouble : IFilter doslStream.Close(); if(_header.magic == MAGIC && - (_header.version == VERSION || _header.version == VERSION2)) + _header.version is VERSION or VERSION2) _headerPath = dosAppleDoubleLower; } } @@ -449,7 +449,7 @@ public sealed class AppleDouble : IFilter netatalkStream.Close(); if(_header.magic == MAGIC && - (_header.version == VERSION || _header.version == VERSION2)) + _header.version is VERSION or VERSION2) _headerPath = netatalkAppleDouble; } } @@ -467,7 +467,7 @@ public sealed class AppleDouble : IFilter daveStream.Close(); if(_header.magic == MAGIC && - (_header.version == VERSION || _header.version == VERSION2)) + _header.version is VERSION or VERSION2) _headerPath = daveAppleDouble; } } @@ -485,7 +485,7 @@ public sealed class AppleDouble : IFilter osxStream.Close(); if(_header.magic == MAGIC && - (_header.version == VERSION || _header.version == VERSION2)) + _header.version is VERSION or VERSION2) _headerPath = osxAppleDouble; } } @@ -503,7 +503,7 @@ public sealed class AppleDouble : IFilter unarStream.Close(); if(_header.magic == MAGIC && - (_header.version == VERSION || _header.version == VERSION2)) + _header.version is VERSION or VERSION2) _headerPath = unArAppleDouble; } } diff --git a/Aaru.Filters/AppleSingle.cs b/Aaru.Filters/AppleSingle.cs index bc1842c32..120cde87a 100644 --- a/Aaru.Filters/AppleSingle.cs +++ b/Aaru.Filters/AppleSingle.cs @@ -178,7 +178,7 @@ public sealed class AppleSingle : IFilter Array.Copy(buffer, 0, hdrB, 0, 26); _header = Marshal.ByteArrayToStructureBigEndian
(hdrB); - return _header.magic == MAGIC && (_header.version == VERSION || _header.version == VERSION2); + return _header.magic == MAGIC && _header.version is VERSION or VERSION2; } /// @@ -193,7 +193,7 @@ public sealed class AppleSingle : IFilter stream.Read(hdrB, 0, 26); _header = Marshal.ByteArrayToStructureBigEndian
(hdrB); - return _header.magic == MAGIC && (_header.version == VERSION || _header.version == VERSION2); + return _header.magic == MAGIC && _header.version is VERSION or VERSION2; } /// @@ -213,7 +213,7 @@ public sealed class AppleSingle : IFilter fstream.Close(); - return _header.magic == MAGIC && (_header.version == VERSION || _header.version == VERSION2); + return _header.magic == MAGIC && _header.version is VERSION or VERSION2; } /// diff --git a/Aaru.Gui/ViewModels/Panels/MediaInfoViewModel.cs b/Aaru.Gui/ViewModels/Panels/MediaInfoViewModel.cs index 5e25ef0c8..87ea4627b 100644 --- a/Aaru.Gui/ViewModels/Panels/MediaInfoViewModel.cs +++ b/Aaru.Gui/ViewModels/Panels/MediaInfoViewModel.cs @@ -387,8 +387,7 @@ public sealed class MediaInfoViewModel : ViewModelBase async void ExecuteDumpCommand() { - if(_scsiInfo.MediaType == CommonTypes.MediaType.GDR || - _scsiInfo.MediaType == CommonTypes.MediaType.GDROM) + if(_scsiInfo.MediaType is CommonTypes.MediaType.GDR or CommonTypes.MediaType.GDROM) { await MessageBoxManager. GetMessageBoxStandardWindow("Error", "GD-ROM dump support is not yet implemented.", ButtonEnum.Ok, @@ -397,8 +396,8 @@ public sealed class MediaInfoViewModel : ViewModelBase return; } - if((_scsiInfo.MediaType == CommonTypes.MediaType.XGD || _scsiInfo.MediaType == CommonTypes.MediaType.XGD2 || - _scsiInfo.MediaType == CommonTypes.MediaType.XGD3) && + if(_scsiInfo.MediaType is CommonTypes.MediaType.XGD or CommonTypes.MediaType.XGD2 + or CommonTypes.MediaType.XGD3 && _scsiInfo.DeviceInfo.ScsiInquiry?.KreonPresent != true) { await MessageBoxManager. diff --git a/Aaru.Gui/ViewModels/Tabs/ScsiInfoViewModel.cs b/Aaru.Gui/ViewModels/Tabs/ScsiInfoViewModel.cs index f85f61bd3..bdede2f8e 100644 --- a/Aaru.Gui/ViewModels/Tabs/ScsiInfoViewModel.cs +++ b/Aaru.Gui/ViewModels/Tabs/ScsiInfoViewModel.cs @@ -528,15 +528,14 @@ public sealed class ScsiInfoViewModel : ViewModelBase evpdPageTitle = "IBM Drive Serial Numbers page"; evpdDecodedPage = EVPD.PrettifyPage_C1_IBM(page.Value); } - else if((page.Key == 0xC0 || page.Key == 0xC1) && + else if(page.Key is 0xC0 or 0xC1 && StringHandlers.CToString(scsiInquiry.Value.VendorIdentification).ToLowerInvariant().Trim() == "certance") { evpdPageTitle = "Certance Drive Component Revision Levels page"; evpdDecodedPage = EVPD.PrettifyPage_C0_C1_Certance(page.Value); } - else if((page.Key == 0xC2 || page.Key == 0xC3 || page.Key == 0xC4 || page.Key == 0xC5 || - page.Key == 0xC6) && + else if(page.Key is 0xC2 or 0xC3 or 0xC4 or 0xC5 or 0xC6 && StringHandlers.CToString(scsiInquiry.Value.VendorIdentification).ToLowerInvariant().Trim() == "certance") { @@ -566,8 +565,7 @@ public sealed class ScsiInfoViewModel : ViewModelBase evpdDecodedPage = EVPD.PrettifyPage_C2_C3_C4_C5_C6_Certance(page.Value); } - else if((page.Key == 0xC0 || page.Key == 0xC1 || page.Key == 0xC2 || page.Key == 0xC3 || - page.Key == 0xC4 || page.Key == 0xC5) && + else if(page.Key is 0xC0 or 0xC1 or 0xC2 or 0xC3 or 0xC4 or 0xC5 && StringHandlers.CToString(scsiInquiry.Value.VendorIdentification).ToLowerInvariant().Trim() == "hp") { diff --git a/Aaru.Gui/ViewModels/Windows/ImageVerifyViewModel.cs b/Aaru.Gui/ViewModels/Windows/ImageVerifyViewModel.cs index 369224db7..4dfdde2f7 100644 --- a/Aaru.Gui/ViewModels/Windows/ImageVerifyViewModel.cs +++ b/Aaru.Gui/ViewModels/Windows/ImageVerifyViewModel.cs @@ -337,7 +337,7 @@ public sealed class ImageVerifyViewModel : ViewModelBase ProgressVisible = true; Progress2Visible = false; - VerifySectorsVisible = _inputFormat is IOpticalMediaImage || _inputFormat is IVerifiableSectorsImage; + VerifySectorsVisible = _inputFormat is IOpticalMediaImage or IVerifiableSectorsImage; // TODO: Do not offer the option to use this form if the image does not support any kind of verification new Thread(DoWork).Start(); diff --git a/Aaru.Helpers b/Aaru.Helpers index 1502ea91c..0462eaac5 160000 --- a/Aaru.Helpers +++ b/Aaru.Helpers @@ -1 +1 @@ -Subproject commit 1502ea91c1658b635f89789893ecd56eb0048a9e +Subproject commit 0462eaac5ef31084ca7c031858caeae358adcb42 diff --git a/Aaru.Images/AaruFormat/Identify.cs b/Aaru.Images/AaruFormat/Identify.cs index e62739a19..47d0196a4 100644 --- a/Aaru.Images/AaruFormat/Identify.cs +++ b/Aaru.Images/AaruFormat/Identify.cs @@ -51,7 +51,6 @@ public sealed partial class AaruFormat _imageStream.Read(_structureBytes, 0, _structureBytes.Length); _header = Marshal.ByteArrayToStructureLittleEndian(_structureBytes); - return (_header.identifier == DIC_MAGIC || _header.identifier == AARU_MAGIC) && - _header.imageMajorVersion <= AARUFMT_VERSION; + return _header.identifier is DIC_MAGIC or AARU_MAGIC && _header.imageMajorVersion <= AARUFMT_VERSION; } } \ No newline at end of file diff --git a/Aaru.Images/AaruFormat/Read.cs b/Aaru.Images/AaruFormat/Read.cs index fa0b07652..e92aa32c2 100644 --- a/Aaru.Images/AaruFormat/Read.cs +++ b/Aaru.Images/AaruFormat/Read.cs @@ -212,8 +212,8 @@ public sealed partial class AaruFormat GC.GetTotalMemory(false)); // Decompress media tag - if(blockHeader.compression == CompressionType.Lzma || - blockHeader.compression == CompressionType.LzmaClauniaSubchannelTransform) + if(blockHeader.compression is CompressionType.Lzma + or CompressionType.LzmaClauniaSubchannelTransform) { if(blockHeader.compression == CompressionType.LzmaClauniaSubchannelTransform && entry.dataType != DataType.CdSectorSubchannel) @@ -1191,7 +1191,7 @@ public sealed partial class AaruFormat Dictionary leadOutStarts = new(); // Lead-out starts foreach(FullTOC.TrackDataDescriptor trk in - decodedFullToc.Value.TrackDescriptors.Where(trk => (trk.ADR == 1 || trk.ADR == 4) && + decodedFullToc.Value.TrackDescriptors.Where(trk => trk.ADR is 1 or 4 && trk.POINT == 0xA2)) { int phour, pmin, psec, pframe; @@ -1430,46 +1430,16 @@ public sealed partial class AaruFormat if(_imageInfo.XmlMediaType != XmlMediaType.OpticalDisc) return ErrorNumber.NoError; - if(_imageInfo.MediaType == MediaType.CD || - _imageInfo.MediaType == MediaType.CDDA || - _imageInfo.MediaType == MediaType.CDG || - _imageInfo.MediaType == MediaType.CDEG || - _imageInfo.MediaType == MediaType.CDI || - _imageInfo.MediaType == MediaType.CDROM || - _imageInfo.MediaType == MediaType.CDROMXA || - _imageInfo.MediaType == MediaType.CDPLUS || - _imageInfo.MediaType == MediaType.CDMO || - _imageInfo.MediaType == MediaType.CDR || - _imageInfo.MediaType == MediaType.CDRW || - _imageInfo.MediaType == MediaType.CDMRW || - _imageInfo.MediaType == MediaType.VCD || - _imageInfo.MediaType == MediaType.SVCD || - _imageInfo.MediaType == MediaType.PCD || - _imageInfo.MediaType == MediaType.DTSCD || - _imageInfo.MediaType == MediaType.CDMIDI || - _imageInfo.MediaType == MediaType.CDV || - _imageInfo.MediaType == MediaType.CDIREADY || - _imageInfo.MediaType == MediaType.FMTOWNS || - _imageInfo.MediaType == MediaType.PS1CD || - _imageInfo.MediaType == MediaType.PS2CD || - _imageInfo.MediaType == MediaType.MEGACD || - _imageInfo.MediaType == MediaType.SATURNCD || - _imageInfo.MediaType == MediaType.GDROM || - _imageInfo.MediaType == MediaType.GDR || - _imageInfo.MediaType == MediaType.MilCD || - _imageInfo.MediaType == MediaType.SuperCDROM2 || - _imageInfo.MediaType == MediaType.JaguarCD || - _imageInfo.MediaType == MediaType.ThreeDO || - _imageInfo.MediaType == MediaType.PCFX || - _imageInfo.MediaType == MediaType.NeoGeoCD || - _imageInfo.MediaType == MediaType.CDTV || - _imageInfo.MediaType == MediaType.CD32 || - _imageInfo.MediaType == MediaType.Playdia || - _imageInfo.MediaType == MediaType.Pippin || - _imageInfo.MediaType == MediaType.VideoNow || - _imageInfo.MediaType == MediaType.VideoNowColor || - _imageInfo.MediaType == MediaType.VideoNowXp || - _imageInfo.MediaType == MediaType.CVD) + if(_imageInfo.MediaType is MediaType.CD or MediaType.CDDA or MediaType.CDG or MediaType.CDEG or MediaType.CDI + or MediaType.CDROM or MediaType.CDROMXA or MediaType.CDPLUS or MediaType.CDMO + or MediaType.CDR or MediaType.CDRW or MediaType.CDMRW or MediaType.VCD or MediaType.SVCD + or MediaType.PCD or MediaType.DTSCD or MediaType.CDMIDI or MediaType.CDV + or MediaType.CDIREADY or MediaType.FMTOWNS or MediaType.PS1CD or MediaType.PS2CD + or MediaType.MEGACD or MediaType.SATURNCD or MediaType.GDROM or MediaType.GDR + or MediaType.MilCD or MediaType.SuperCDROM2 or MediaType.JaguarCD or MediaType.ThreeDO + or MediaType.PCFX or MediaType.NeoGeoCD or MediaType.CDTV or MediaType.CD32 + or MediaType.Playdia or MediaType.Pippin or MediaType.VideoNow + or MediaType.VideoNowColor or MediaType.VideoNowXp or MediaType.CVD) return ErrorNumber.NoError; { diff --git a/Aaru.Images/AaruFormat/Write.cs b/Aaru.Images/AaruFormat/Write.cs index 96e12a8d1..ffbe45f36 100644 --- a/Aaru.Images/AaruFormat/Write.cs +++ b/Aaru.Images/AaruFormat/Write.cs @@ -31,6 +31,8 @@ // Copyright © 2020-2022 Rebecca Wallander // ****************************************************************************/ +namespace Aaru.DiscImages; + using System; using System.Collections.Generic; using System.IO; @@ -54,2030 +56,2123 @@ using Marshal = Aaru.Helpers.Marshal; using Session = Aaru.CommonTypes.Structs.Session; using TrackType = Aaru.CommonTypes.Enums.TrackType; -namespace Aaru.DiscImages +public sealed partial class AaruFormat { - public sealed partial class AaruFormat + /// + public bool Create(string path, MediaType mediaType, Dictionary options, ulong sectors, + uint sectorSize) { - /// - public bool Create(string path, MediaType mediaType, Dictionary options, ulong sectors, - uint sectorSize) + uint sectorsPerBlock; + uint maxDdtSize; + bool doMd5; + bool doSha1; + bool doSha256; + bool doSpamsum; + + if(options != null) { - uint sectorsPerBlock; - uint maxDdtSize; - bool doMd5; - bool doSha1; - bool doSha256; - bool doSpamsum; - - if(options != null) + if(options.TryGetValue("sectors_per_block", out string tmpValue)) { - if(options.TryGetValue("sectors_per_block", out string tmpValue)) + if(!uint.TryParse(tmpValue, out sectorsPerBlock)) { - if(!uint.TryParse(tmpValue, out sectorsPerBlock)) - { - ErrorMessage = "Invalid value for sectors_per_block option"; + ErrorMessage = "Invalid value for sectors_per_block option"; - return false; - } + return false; } - else - sectorsPerBlock = 4096; - - if(options.TryGetValue("dictionary", out tmpValue)) - { - if(!uint.TryParse(tmpValue, out _dictionarySize)) - { - ErrorMessage = "Invalid value for dictionary option"; - - return false; - } - } - else - _dictionarySize = 1 << 25; - - if(options.TryGetValue("max_ddt_size", out tmpValue)) - { - if(!uint.TryParse(tmpValue, out maxDdtSize)) - { - ErrorMessage = "Invalid value for max_ddt_size option"; - - return false; - } - } - else - maxDdtSize = 256; - - if(options.TryGetValue("md5", out tmpValue)) - { - if(!bool.TryParse(tmpValue, out doMd5)) - { - ErrorMessage = "Invalid value for md5 option"; - - return false; - } - } - else - doMd5 = true; - - if(options.TryGetValue("sha1", out tmpValue)) - { - if(!bool.TryParse(tmpValue, out doSha1)) - { - ErrorMessage = "Invalid value for sha1 option"; - - return false; - } - } - else - doSha1 = true; - - if(options.TryGetValue("sha256", out tmpValue)) - { - if(!bool.TryParse(tmpValue, out doSha256)) - { - ErrorMessage = "Invalid value for sha256 option"; - - return false; - } - } - else - doSha256 = true; - - if(options.TryGetValue("spamsum", out tmpValue)) - { - if(!bool.TryParse(tmpValue, out doSpamsum)) - { - ErrorMessage = "Invalid value for spamsum option"; - - return false; - } - } - else - doSpamsum = false; - - if(options.TryGetValue("deduplicate", out tmpValue)) - { - if(!bool.TryParse(tmpValue, out _deduplicate)) - { - ErrorMessage = "Invalid value for deduplicate option"; - - return false; - } - } - else - _deduplicate = true; - - if(options.TryGetValue("compress", out tmpValue)) - { - if(!bool.TryParse(tmpValue, out _compress)) - { - ErrorMessage = "Invalid value for compress option"; - - return false; - } - } - else - _compress = true; } else - { sectorsPerBlock = 4096; - _dictionarySize = 1 << 25; - maxDdtSize = 256; - doMd5 = true; - doSha1 = true; - doSha256 = true; - doSpamsum = false; - _deduplicate = true; - _compress = true; - } - _compressionAlgorithm = _compress ? CompressionType.Lzma : CompressionType.None; - - // This really, cannot happen - if(!SupportedMediaTypes.Contains(mediaType)) + if(options.TryGetValue("dictionary", out tmpValue)) { - ErrorMessage = $"Unsupported media format {mediaType}"; + if(!uint.TryParse(tmpValue, out _dictionarySize)) + { + ErrorMessage = "Invalid value for dictionary option"; + + return false; + } + } + else + _dictionarySize = 1 << 25; + + if(options.TryGetValue("max_ddt_size", out tmpValue)) + { + if(!uint.TryParse(tmpValue, out maxDdtSize)) + { + ErrorMessage = "Invalid value for max_ddt_size option"; + + return false; + } + } + else + maxDdtSize = 256; + + if(options.TryGetValue("md5", out tmpValue)) + { + if(!bool.TryParse(tmpValue, out doMd5)) + { + ErrorMessage = "Invalid value for md5 option"; + + return false; + } + } + else + doMd5 = true; + + if(options.TryGetValue("sha1", out tmpValue)) + { + if(!bool.TryParse(tmpValue, out doSha1)) + { + ErrorMessage = "Invalid value for sha1 option"; + + return false; + } + } + else + doSha1 = true; + + if(options.TryGetValue("sha256", out tmpValue)) + { + if(!bool.TryParse(tmpValue, out doSha256)) + { + ErrorMessage = "Invalid value for sha256 option"; + + return false; + } + } + else + doSha256 = true; + + if(options.TryGetValue("spamsum", out tmpValue)) + { + if(!bool.TryParse(tmpValue, out doSpamsum)) + { + ErrorMessage = "Invalid value for spamsum option"; + + return false; + } + } + else + doSpamsum = false; + + if(options.TryGetValue("deduplicate", out tmpValue)) + { + if(!bool.TryParse(tmpValue, out _deduplicate)) + { + ErrorMessage = "Invalid value for deduplicate option"; + + return false; + } + } + else + _deduplicate = true; + + if(options.TryGetValue("compress", out tmpValue)) + { + if(!bool.TryParse(tmpValue, out _compress)) + { + ErrorMessage = "Invalid value for compress option"; + + return false; + } + } + else + _compress = true; + } + else + { + sectorsPerBlock = 4096; + _dictionarySize = 1 << 25; + maxDdtSize = 256; + doMd5 = true; + doSha1 = true; + doSha256 = true; + doSpamsum = false; + _deduplicate = true; + _compress = true; + } + + _compressionAlgorithm = _compress ? CompressionType.Lzma : CompressionType.None; + + // This really, cannot happen + if(!SupportedMediaTypes.Contains(mediaType)) + { + ErrorMessage = $"Unsupported media format {mediaType}"; + + return false; + } + + // Calculate shift + _shift = 0; + uint oldSectorsPerBlock = sectorsPerBlock; + + while(sectorsPerBlock > 1) + { + sectorsPerBlock >>= 1; + _shift++; + } + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Got a shift of {0} for {1} sectors per block", _shift, + oldSectorsPerBlock); + + _imageInfo = new ImageInfo + { + MediaType = mediaType, + SectorSize = sectorSize, + Sectors = sectors, + XmlMediaType = GetXmlMediaType(mediaType) + }; + + try + { + _imageStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); + } + catch(IOException e) + { + ErrorMessage = $"Could not create new image file, exception {e.Message}"; + + return false; + } + + // Check if appending to an existing image + if(_imageStream.Length > Marshal.SizeOf()) + { + _structureBytes = new byte[Marshal.SizeOf()]; + _imageStream.Read(_structureBytes, 0, _structureBytes.Length); + _header = Marshal.ByteArrayToStructureLittleEndian(_structureBytes); + + if(_header.identifier != DIC_MAGIC && + _header.identifier != AARU_MAGIC) + { + ErrorMessage = "Cannot append to a non Aaru Format image"; return false; } - // Calculate shift - _shift = 0; - uint oldSectorsPerBlock = sectorsPerBlock; - - while(sectorsPerBlock > 1) + if(_header.imageMajorVersion > AARUFMT_VERSION) { - sectorsPerBlock >>= 1; - _shift++; + ErrorMessage = $"Cannot append to an unknown image version {_header.imageMajorVersion}"; + + return false; } - AaruConsole.DebugWriteLine("Aaru Format plugin", "Got a shift of {0} for {1} sectors per block", _shift, - oldSectorsPerBlock); - - _imageInfo = new ImageInfo + if(_header.mediaType != mediaType) { - MediaType = mediaType, - SectorSize = sectorSize, - Sectors = sectors, - XmlMediaType = GetXmlMediaType(mediaType) + ErrorMessage = $"Cannot write a media with type {mediaType} to an image with type {_header.mediaType}"; + + return false; + } + } + else + { + _header = new AaruHeader + { + identifier = AARU_MAGIC, + mediaType = mediaType, + creationTime = DateTime.UtcNow.ToFileTimeUtc() }; - try + _imageStream.Write(new byte[Marshal.SizeOf()], 0, Marshal.SizeOf()); + } + + _header.application = "Aaru"; + _header.imageMajorVersion = AARUFMT_VERSION_V1; + _header.imageMinorVersion = 0; + _header.applicationMajorVersion = (byte)typeof(AaruFormat).Assembly.GetName().Version.Major; + _header.applicationMinorVersion = (byte)typeof(AaruFormat).Assembly.GetName().Version.Minor; + + // Initialize tables + _index = new List(); + _mediaTags = new Dictionary(); + _checksumProvider = SHA256.Create(); + _deduplicationTable = new Dictionary(); + _trackIsrcs = new Dictionary(); + _trackFlags = new Dictionary(); + _imageInfo.ReadableSectorTags = new List(); + + // If there exists an index, we are appending, so read index + if(_header.indexOffset > 0) + { + List compactDiscIndexes = null; + + // Initialize caches + _blockCache = new Dictionary(); + _blockHeaderCache = new Dictionary(); + _currentCacheSize = 0; + + // Can't calculate checksum of an appended image + _md5Provider = null; + _sha1Provider = null; + _sha256Provider = null; + _spamsumProvider = null; + + _imageStream.Position = (long)_header.indexOffset; + _structureBytes = new byte[Marshal.SizeOf()]; + _imageStream.Read(_structureBytes, 0, _structureBytes.Length); + IndexHeader idxHeader = Marshal.SpanToStructureLittleEndian(_structureBytes); + + if(idxHeader.identifier != BlockType.Index) { - _imageStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); - } - catch(IOException e) - { - ErrorMessage = $"Could not create new image file, exception {e.Message}"; + ErrorMessage = "Index not found in existing image, cannot continue"; return false; } - // Check if appending to an existing image - if(_imageStream.Length > Marshal.SizeOf()) + AaruConsole.DebugWriteLine("Aaru Format plugin", "Index at {0} contains {1} entries", _header.indexOffset, + idxHeader.entries); + + for(ushort i = 0; i < idxHeader.entries; i++) { - _structureBytes = new byte[Marshal.SizeOf()]; + _structureBytes = new byte[Marshal.SizeOf()]; _imageStream.Read(_structureBytes, 0, _structureBytes.Length); - _header = Marshal.ByteArrayToStructureLittleEndian(_structureBytes); + IndexEntry entry = Marshal.SpanToStructureLittleEndian(_structureBytes); - if(_header.identifier != DIC_MAGIC && - _header.identifier != AARU_MAGIC) - { - ErrorMessage = "Cannot append to a non Aaru Format image"; + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Block type {0} with data type {1} is indexed to be at {2}", entry.blockType, + entry.dataType, entry.offset); - return false; - } - - if(_header.imageMajorVersion > AARUFMT_VERSION) - { - ErrorMessage = $"Cannot append to an unknown image version {_header.imageMajorVersion}"; - - return false; - } - - if(_header.mediaType != mediaType) - { - ErrorMessage = - $"Cannot write a media with type {mediaType} to an image with type {_header.mediaType}"; - - return false; - } - } - else - { - _header = new AaruHeader - { - identifier = AARU_MAGIC, - mediaType = mediaType, - creationTime = DateTime.UtcNow.ToFileTimeUtc() - }; - - _imageStream.Write(new byte[Marshal.SizeOf()], 0, Marshal.SizeOf()); + _index.Add(entry); } - _header.application = "Aaru"; - _header.imageMajorVersion = AARUFMT_VERSION_V1; - _header.imageMinorVersion = 0; - _header.applicationMajorVersion = (byte)typeof(AaruFormat).Assembly.GetName().Version.Major; - _header.applicationMinorVersion = (byte)typeof(AaruFormat).Assembly.GetName().Version.Minor; + // Invalidate previous checksum block + _index.RemoveAll(t => t.blockType == BlockType.ChecksumBlock && t.dataType == DataType.NoData); - // Initialize tables - _index = new List(); - _mediaTags = new Dictionary(); - _checksumProvider = SHA256.Create(); - _deduplicationTable = new Dictionary(); - _trackIsrcs = new Dictionary(); - _trackFlags = new Dictionary(); - _imageInfo.ReadableSectorTags = new List(); + var foundUserDataDdt = false; - // If there exists an index, we are appending, so read index - if(_header.indexOffset > 0) + foreach(IndexEntry entry in _index) { - List compactDiscIndexes = null; + _imageStream.Position = (long)entry.offset; - // Initialize caches - _blockCache = new Dictionary(); - _blockHeaderCache = new Dictionary(); - _currentCacheSize = 0; - - // Can't calculate checksum of an appended image - _md5Provider = null; - _sha1Provider = null; - _sha256Provider = null; - _spamsumProvider = null; - - _imageStream.Position = (long)_header.indexOffset; - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.Read(_structureBytes, 0, _structureBytes.Length); - IndexHeader idxHeader = Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(idxHeader.identifier != BlockType.Index) + switch(entry.blockType) { - ErrorMessage = "Index not found in existing image, cannot continue"; + case BlockType.DataBlock: + // NOP block, skip + if(entry.dataType == DataType.NoData) + break; - return false; - } + _imageStream.Position = (long)entry.offset; - AaruConsole.DebugWriteLine("Aaru Format plugin", "Index at {0} contains {1} entries", - _header.indexOffset, idxHeader.entries); + _structureBytes = new byte[Marshal.SizeOf()]; + _imageStream.Read(_structureBytes, 0, _structureBytes.Length); + BlockHeader blockHeader = Marshal.SpanToStructureLittleEndian(_structureBytes); + _imageInfo.ImageSize += blockHeader.cmpLength; - for(ushort i = 0; i < idxHeader.entries; i++) - { - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.Read(_structureBytes, 0, _structureBytes.Length); - IndexEntry entry = Marshal.SpanToStructureLittleEndian(_structureBytes); - - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Block type {0} with data type {1} is indexed to be at {2}", - entry.blockType, entry.dataType, entry.offset); - - _index.Add(entry); - } - - // Invalidate previous checksum block - _index.RemoveAll(t => t.blockType == BlockType.ChecksumBlock && t.dataType == DataType.NoData); - - bool foundUserDataDdt = false; - - foreach(IndexEntry entry in _index) - { - _imageStream.Position = (long)entry.offset; - - switch(entry.blockType) - { - case BlockType.DataBlock: - // NOP block, skip - if(entry.dataType == DataType.NoData) - break; - - _imageStream.Position = (long)entry.offset; - - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.Read(_structureBytes, 0, _structureBytes.Length); - BlockHeader blockHeader = Marshal.SpanToStructureLittleEndian(_structureBytes); - _imageInfo.ImageSize += blockHeader.cmpLength; - - // Unused, skip - if(entry.dataType == DataType.UserData) - break; - - if(blockHeader.identifier != entry.blockType) - { - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Incorrect identifier for data block at position {0}", - entry.offset); - - break; - } - - if(blockHeader.type != entry.dataType) - { - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Expected block with data type {0} at position {1} but found data type {2}", - entry.dataType, entry.offset, blockHeader.type); - - break; - } - - byte[] data; + // Unused, skip + if(entry.dataType == DataType.UserData) + break; + if(blockHeader.identifier != entry.blockType) + { AaruConsole.DebugWriteLine("Aaru Format plugin", - "Found data block type {0} at position {1}", entry.dataType, + "Incorrect identifier for data block at position {0}", entry.offset); + break; + } + + if(blockHeader.type != entry.dataType) + { + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Expected block with data type {0} at position {1} but found data type {2}", + entry.dataType, entry.offset, blockHeader.type); + + break; + } + + byte[] data; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Found data block type {0} at position {1}", + entry.dataType, entry.offset); + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", + GC.GetTotalMemory(false)); + + // Decompress media tag + if(blockHeader.compression is CompressionType.Lzma + or CompressionType.LzmaClauniaSubchannelTransform) + { + if(blockHeader.compression == CompressionType.LzmaClauniaSubchannelTransform && + entry.dataType != DataType.CdSectorSubchannel) + { + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Invalid compression type {0} for block with data type {1}, continuing...", + blockHeader.compression, entry.dataType); + + break; + } + + DateTime startDecompress = DateTime.Now; + var compressedTag = new byte[blockHeader.cmpLength - LZMA_PROPERTIES_LENGTH]; + var lzmaProperties = new byte[LZMA_PROPERTIES_LENGTH]; + _imageStream.Read(lzmaProperties, 0, LZMA_PROPERTIES_LENGTH); + _imageStream.Read(compressedTag, 0, compressedTag.Length); + data = new byte[blockHeader.length]; + int decompressedLength = LZMA.DecodeBuffer(compressedTag, data, lzmaProperties); + + if(decompressedLength != blockHeader.length) + { + ErrorMessage = + $"Error decompressing block, should be {blockHeader.length} bytes but got {decompressedLength} bytes."; + + return false; + } + + if(blockHeader.compression == CompressionType.LzmaClauniaSubchannelTransform) + data = ClauniaSubchannelUntransform(data); + + DateTime endDecompress = DateTime.Now; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Took {0} seconds to decompress block", + (endDecompress - startDecompress).TotalSeconds); + AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", GC.GetTotalMemory(false)); + } + else if(blockHeader.compression == CompressionType.None) + { + data = new byte[blockHeader.length]; + _imageStream.Read(data, 0, (int)blockHeader.length); - // Decompress media tag - if(blockHeader.compression == CompressionType.Lzma || - blockHeader.compression == CompressionType.LzmaClauniaSubchannelTransform) - { - if(blockHeader.compression == CompressionType.LzmaClauniaSubchannelTransform && - entry.dataType != DataType.CdSectorSubchannel) + AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", + GC.GetTotalMemory(false)); + } + else + { + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Found unknown compression type {0}, continuing...", + (ushort)blockHeader.compression); + + break; + } + + // Check CRC, if not correct, skip it + Crc64Context.Data(data, out byte[] blockCrc); + + if(BitConverter.ToUInt64(blockCrc, 0) != blockHeader.crc64 && + blockHeader.crc64 != 0) + { + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Incorrect CRC found: 0x{0:X16} found, expected 0x{1:X16}, continuing...", + BitConverter.ToUInt64(blockCrc, 0), blockHeader.crc64); + + break; + } + + // Check if it's not a media tag, but a sector tag, and fill the appropriate table then + switch(entry.dataType) + { + case DataType.CdSectorPrefix: + case DataType.CdSectorPrefixCorrected: + if(entry.dataType == DataType.CdSectorPrefixCorrected) + { + _sectorPrefixMs = new MemoryStream(); + _sectorPrefixMs.Write(data, 0, data.Length); + } + else + _sectorPrefix = data; + + if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) + _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + + if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) + _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", + GC.GetTotalMemory(false)); + + break; + case DataType.CdSectorSuffix: + case DataType.CdSectorSuffixCorrected: + if(entry.dataType == DataType.CdSectorSuffixCorrected) + { + _sectorSuffixMs = new MemoryStream(); + _sectorSuffixMs.Write(data, 0, data.Length); + } + else + _sectorSuffix = data; + + 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); + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", + GC.GetTotalMemory(false)); + + break; + case DataType.CdSectorSubchannel: + _sectorSubchannel = data; + + if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel)) + _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel); + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", + GC.GetTotalMemory(false)); + + break; + case DataType.AppleProfileTag: + case DataType.AppleSonyTag: + case DataType.PriamDataTowerTag: + _sectorSubchannel = data; + + if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag)) + _imageInfo.ReadableSectorTags.Add(SectorTagType.AppleSectorTag); + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", + GC.GetTotalMemory(false)); + + break; + case DataType.CompactDiscMode2Subheader: + _mode2Subheaders = data; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", + GC.GetTotalMemory(false)); + + break; + case DataType.DvdSectorCpiMai: + _sectorCpiMai = data; + + if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdCmi)) + _imageInfo.ReadableSectorTags.Add(SectorTagType.DvdCmi); + + if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdTitleKey)) + _imageInfo.ReadableSectorTags.Add(SectorTagType.DvdTitleKey); + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", + GC.GetTotalMemory(false)); + + break; + case DataType.DvdSectorTitleKeyDecrypted: + _sectorDecryptedTitleKey = data; + + if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdTitleKeyDecrypted)) + _imageInfo.ReadableSectorTags.Add(SectorTagType.DvdTitleKeyDecrypted); + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", + GC.GetTotalMemory(false)); + + break; + default: + MediaTagType mediaTagType = GetMediaTagTypeForDataType(blockHeader.type); + + if(_mediaTags.ContainsKey(mediaTagType)) { AaruConsole.DebugWriteLine("Aaru Format plugin", - "Invalid compression type {0} for block with data type {1}, continuing...", - blockHeader.compression, entry.dataType); + "Media tag type {0} duplicated, removing previous entry...", + mediaTagType); - break; + _mediaTags.Remove(mediaTagType); } - DateTime startDecompress = DateTime.Now; - byte[] compressedTag = new byte[blockHeader.cmpLength - LZMA_PROPERTIES_LENGTH]; - byte[] lzmaProperties = new byte[LZMA_PROPERTIES_LENGTH]; - _imageStream.Read(lzmaProperties, 0, LZMA_PROPERTIES_LENGTH); - _imageStream.Read(compressedTag, 0, compressedTag.Length); - data = new byte[blockHeader.length]; - int decompressedLength = LZMA.DecodeBuffer(compressedTag, data, lzmaProperties); - - if(decompressedLength != blockHeader.length) - { - ErrorMessage = - $"Error decompressing block, should be {blockHeader.length} bytes but got {decompressedLength} bytes."; - - return false; - } - - if(blockHeader.compression == CompressionType.LzmaClauniaSubchannelTransform) - data = ClauniaSubchannelUntransform(data); - - DateTime endDecompress = DateTime.Now; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Took {0} seconds to decompress block", - (endDecompress - startDecompress).TotalSeconds); + _mediaTags.Add(mediaTagType, data); AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", GC.GetTotalMemory(false)); - } - else if(blockHeader.compression == CompressionType.None) - { - data = new byte[blockHeader.length]; - _imageStream.Read(data, 0, (int)blockHeader.length); - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", - GC.GetTotalMemory(false)); - } - else - { - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Found unknown compression type {0}, continuing...", - (ushort)blockHeader.compression); break; - } + } - // Check CRC, if not correct, skip it - Crc64Context.Data(data, out byte[] blockCrc); + break; + case BlockType.DeDuplicationTable: + // Only user data deduplication tables are used right now + if(entry.dataType == DataType.UserData) + { + _structureBytes = new byte[Marshal.SizeOf()]; + _imageStream.Read(_structureBytes, 0, _structureBytes.Length); - if(BitConverter.ToUInt64(blockCrc, 0) != blockHeader.crc64 && - blockHeader.crc64 != 0) - { - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Incorrect CRC found: 0x{0:X16} found, expected 0x{1:X16}, continuing...", - BitConverter.ToUInt64(blockCrc, 0), blockHeader.crc64); + DdtHeader ddtHeader = Marshal.ByteArrayToStructureLittleEndian(_structureBytes); + if(ddtHeader.identifier != BlockType.DeDuplicationTable) break; + + if(ddtHeader.entries != _imageInfo.Sectors && + !IsTape) + { + ErrorMessage = + $"Trying to write a media with {_imageInfo.Sectors} sectors to an image with {ddtHeader.entries} sectors, not continuing..."; + + return false; } - // Check if it's not a media tag, but a sector tag, and fill the appropriate table then - switch(entry.dataType) + _shift = ddtHeader.shift; + + switch(ddtHeader.compression) { - case DataType.CdSectorPrefix: - case DataType.CdSectorPrefixCorrected: - if(entry.dataType == DataType.CdSectorPrefixCorrected) + case CompressionType.Lzma: + AaruConsole.DebugWriteLine("Aaru Format plugin", "Decompressing DDT..."); + + DateTime ddtStart = DateTime.UtcNow; + + var compressedDdt = new byte[ddtHeader.cmpLength - LZMA_PROPERTIES_LENGTH]; + + var lzmaProperties = new byte[LZMA_PROPERTIES_LENGTH]; + _imageStream.Read(lzmaProperties, 0, LZMA_PROPERTIES_LENGTH); + _imageStream.Read(compressedDdt, 0, compressedDdt.Length); + var decompressedDdt = new byte[ddtHeader.length]; + + var decompressedLength = + (ulong)LZMA.DecodeBuffer(compressedDdt, decompressedDdt, lzmaProperties); + + if(decompressedLength != ddtHeader.length) { - _sectorPrefixMs = new MemoryStream(); - _sectorPrefixMs.Write(data, 0, data.Length); + ErrorMessage = + $"Error decompressing DDT, should be {ddtHeader.length} bytes but got {decompressedLength} bytes."; + + return false; } - else - _sectorPrefix = data; - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + _userDataDdt = MemoryMarshal.Cast(decompressedDdt).ToArray(); + DateTime ddtEnd = DateTime.UtcNow; + _inMemoryDdt = true; - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", - GC.GetTotalMemory(false)); + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Took {0} seconds to decompress DDT", + (ddtEnd - ddtStart).TotalSeconds); break; - case DataType.CdSectorSuffix: - case DataType.CdSectorSuffixCorrected: - if(entry.dataType == DataType.CdSectorSuffixCorrected) - { - _sectorSuffixMs = new MemoryStream(); - _sectorSuffixMs.Write(data, 0, data.Length); - } - else - _sectorSuffix = data; - - 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); - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", - GC.GetTotalMemory(false)); - - break; - case DataType.CdSectorSubchannel: - _sectorSubchannel = data; - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel); - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", - GC.GetTotalMemory(false)); - - break; - case DataType.AppleProfileTag: - case DataType.AppleSonyTag: - case DataType.PriamDataTowerTag: - _sectorSubchannel = data; - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.AppleSectorTag); - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", - GC.GetTotalMemory(false)); - - break; - case DataType.CompactDiscMode2Subheader: - _mode2Subheaders = data; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", - GC.GetTotalMemory(false)); - - break; - case DataType.DvdSectorCpiMai: - _sectorCpiMai = data; - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdCmi)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.DvdCmi); - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdTitleKey)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.DvdTitleKey); - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", - GC.GetTotalMemory(false)); - - break; - case DataType.DvdSectorTitleKeyDecrypted: - _sectorDecryptedTitleKey = data; - - if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdTitleKeyDecrypted)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.DvdTitleKeyDecrypted); - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", - GC.GetTotalMemory(false)); + case CompressionType.None: + _inMemoryDdt = false; + _outMemoryDdtPosition = (long)entry.offset; break; default: - MediaTagType mediaTagType = GetMediaTagTypeForDataType(blockHeader.type); + ErrorMessage = + $"Found unsupported compression algorithm {(ushort)ddtHeader.compression}"; - if(_mediaTags.ContainsKey(mediaTagType)) + return false; + } + + if(IsTape) + { + _tapeDdt = new Dictionary(); + + for(long i = 0; i < _userDataDdt.LongLength; i++) + _tapeDdt.Add((ulong)i, _userDataDdt[i]); + + _userDataDdt = null; + } + + foundUserDataDdt = true; + } + else if(entry.dataType is DataType.CdSectorPrefixCorrected or DataType.CdSectorSuffixCorrected) + { + _structureBytes = new byte[Marshal.SizeOf()]; + _imageStream.Read(_structureBytes, 0, _structureBytes.Length); + + DdtHeader ddtHeader = Marshal.ByteArrayToStructureLittleEndian(_structureBytes); + + if(ddtHeader.identifier != BlockType.DeDuplicationTable) + break; + + if(ddtHeader.entries != _imageInfo.Sectors) + { + ErrorMessage = + $"Trying to write a media with {_imageInfo.Sectors} sectors to an image with {ddtHeader.entries} sectors, not continuing..."; + + return false; + } + + var decompressedDdt = new byte[ddtHeader.length]; + + switch(ddtHeader.compression) + { + case CompressionType.Lzma: + AaruConsole.DebugWriteLine("Aaru Format plugin", "Decompressing DDT..."); + + DateTime ddtStart = DateTime.UtcNow; + + var compressedDdt = new byte[ddtHeader.cmpLength - LZMA_PROPERTIES_LENGTH]; + + var lzmaProperties = new byte[LZMA_PROPERTIES_LENGTH]; + _imageStream.Read(lzmaProperties, 0, LZMA_PROPERTIES_LENGTH); + _imageStream.Read(compressedDdt, 0, compressedDdt.Length); + + var decompressedLength = + (ulong)LZMA.DecodeBuffer(compressedDdt, decompressedDdt, lzmaProperties); + + if(decompressedLength != ddtHeader.length) { - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Media tag type {0} duplicated, removing previous entry...", - mediaTagType); + ErrorMessage = + $"Error decompressing DDT, should be {ddtHeader.length} bytes but got {decompressedLength} bytes."; - _mediaTags.Remove(mediaTagType); + return false; } - _mediaTags.Add(mediaTagType, data); + DateTime ddtEnd = DateTime.UtcNow; - AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", - GC.GetTotalMemory(false)); + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Took {0} seconds to decompress DDT", + (ddtEnd - ddtStart).TotalSeconds); break; - } + case CompressionType.None: + _imageStream.Read(decompressedDdt, 0, decompressedDdt.Length); - break; - case BlockType.DeDuplicationTable: - // Only user data deduplication tables are used right now - if(entry.dataType == DataType.UserData) - { - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.Read(_structureBytes, 0, _structureBytes.Length); - - DdtHeader ddtHeader = - Marshal.ByteArrayToStructureLittleEndian(_structureBytes); - - if(ddtHeader.identifier != BlockType.DeDuplicationTable) break; - - if(ddtHeader.entries != _imageInfo.Sectors && - !IsTape) - { + default: ErrorMessage = - $"Trying to write a media with {_imageInfo.Sectors} sectors to an image with {ddtHeader.entries} sectors, not continuing..."; + $"Found unsupported compression algorithm {(ushort)ddtHeader.compression}"; return false; - } - - _shift = ddtHeader.shift; - - switch(ddtHeader.compression) - { - case CompressionType.Lzma: - AaruConsole.DebugWriteLine("Aaru Format plugin", "Decompressing DDT..."); - - DateTime ddtStart = DateTime.UtcNow; - - byte[] compressedDdt = new byte[ddtHeader.cmpLength - LZMA_PROPERTIES_LENGTH]; - - byte[] lzmaProperties = new byte[LZMA_PROPERTIES_LENGTH]; - _imageStream.Read(lzmaProperties, 0, LZMA_PROPERTIES_LENGTH); - _imageStream.Read(compressedDdt, 0, compressedDdt.Length); - byte[] decompressedDdt = new byte[ddtHeader.length]; - - ulong decompressedLength = - (ulong)LZMA.DecodeBuffer(compressedDdt, decompressedDdt, lzmaProperties); - - if(decompressedLength != ddtHeader.length) - { - ErrorMessage = - $"Error decompressing DDT, should be {ddtHeader.length} bytes but got {decompressedLength} bytes."; - - return false; - } - - _userDataDdt = MemoryMarshal.Cast(decompressedDdt).ToArray(); - DateTime ddtEnd = DateTime.UtcNow; - _inMemoryDdt = true; - - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Took {0} seconds to decompress DDT", - (ddtEnd - ddtStart).TotalSeconds); - - break; - case CompressionType.None: - _inMemoryDdt = false; - _outMemoryDdtPosition = (long)entry.offset; - - break; - default: - ErrorMessage = - $"Found unsupported compression algorithm {(ushort)ddtHeader.compression}"; - - return false; - } - - if(IsTape) - { - _tapeDdt = new Dictionary(); - - for(long i = 0; i < _userDataDdt.LongLength; i++) - _tapeDdt.Add((ulong)i, _userDataDdt[i]); - - _userDataDdt = null; - } - - foundUserDataDdt = true; } - else if(entry.dataType == DataType.CdSectorPrefixCorrected || - entry.dataType == DataType.CdSectorSuffixCorrected) + + uint[] cdDdt = MemoryMarshal.Cast(decompressedDdt).ToArray(); + + switch(entry.dataType) { - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.Read(_structureBytes, 0, _structureBytes.Length); + case DataType.CdSectorPrefixCorrected: + _sectorPrefixDdt = cdDdt; - DdtHeader ddtHeader = - Marshal.ByteArrayToStructureLittleEndian(_structureBytes); - - if(ddtHeader.identifier != BlockType.DeDuplicationTable) break; + case DataType.CdSectorSuffixCorrected: + _sectorSuffixDdt = cdDdt; - if(ddtHeader.entries != _imageInfo.Sectors) - { - ErrorMessage = - $"Trying to write a media with {_imageInfo.Sectors} sectors to an image with {ddtHeader.entries} sectors, not continuing..."; - - return false; - } - - byte[] decompressedDdt = new byte[ddtHeader.length]; - - switch(ddtHeader.compression) - { - case CompressionType.Lzma: - AaruConsole.DebugWriteLine("Aaru Format plugin", "Decompressing DDT..."); - - DateTime ddtStart = DateTime.UtcNow; - - byte[] compressedDdt = new byte[ddtHeader.cmpLength - LZMA_PROPERTIES_LENGTH]; - - byte[] lzmaProperties = new byte[LZMA_PROPERTIES_LENGTH]; - _imageStream.Read(lzmaProperties, 0, LZMA_PROPERTIES_LENGTH); - _imageStream.Read(compressedDdt, 0, compressedDdt.Length); - - ulong decompressedLength = - (ulong)LZMA.DecodeBuffer(compressedDdt, decompressedDdt, lzmaProperties); - - if(decompressedLength != ddtHeader.length) - { - ErrorMessage = - $"Error decompressing DDT, should be {ddtHeader.length} bytes but got {decompressedLength} bytes."; - - return false; - } - - DateTime ddtEnd = DateTime.UtcNow; - - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Took {0} seconds to decompress DDT", - (ddtEnd - ddtStart).TotalSeconds); - - break; - case CompressionType.None: - _imageStream.Read(decompressedDdt, 0, decompressedDdt.Length); - - break; - default: - ErrorMessage = - $"Found unsupported compression algorithm {(ushort)ddtHeader.compression}"; - - return false; - } - - uint[] cdDdt = MemoryMarshal.Cast(decompressedDdt).ToArray(); - - switch(entry.dataType) - { - case DataType.CdSectorPrefixCorrected: - _sectorPrefixDdt = cdDdt; - - break; - case DataType.CdSectorSuffixCorrected: - _sectorSuffixDdt = cdDdt; - - break; - } + break; } + } - break; + break; - // Logical geometry block. It doesn't have a CRC coz, well, it's not so important - case BlockType.GeometryBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.Read(_structureBytes, 0, _structureBytes.Length); - _geometryBlock = Marshal.SpanToStructureLittleEndian(_structureBytes); + // Logical geometry block. It doesn't have a CRC coz, well, it's not so important + case BlockType.GeometryBlock: + _structureBytes = new byte[Marshal.SizeOf()]; + _imageStream.Read(_structureBytes, 0, _structureBytes.Length); + _geometryBlock = Marshal.SpanToStructureLittleEndian(_structureBytes); - if(_geometryBlock.identifier == BlockType.GeometryBlock) - { - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Geometry set to {0} cylinders {1} heads {2} sectors per track", - _geometryBlock.cylinders, _geometryBlock.heads, - _geometryBlock.sectorsPerTrack); - - _imageInfo.Cylinders = _geometryBlock.cylinders; - _imageInfo.Heads = _geometryBlock.heads; - _imageInfo.SectorsPerTrack = _geometryBlock.sectorsPerTrack; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", - GC.GetTotalMemory(false)); - } - - break; - - // Metadata block - case BlockType.MetadataBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.Read(_structureBytes, 0, _structureBytes.Length); - - MetadataBlock metadataBlock = - Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(metadataBlock.identifier != entry.blockType) - { - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Incorrect identifier for data block at position {0}", - entry.offset); - - break; - } - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Found metadata block at position {0}", - entry.offset); - - byte[] metadata = new byte[metadataBlock.blockSize]; - _imageStream.Position = (long)entry.offset; - _imageStream.Read(metadata, 0, metadata.Length); - - if(metadataBlock.mediaSequence > 0 && - metadataBlock.lastMediaSequence > 0) - { - _imageInfo.MediaSequence = metadataBlock.mediaSequence; - _imageInfo.LastMediaSequence = metadataBlock.lastMediaSequence; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting media sequence as {0} of {1}", - _imageInfo.MediaSequence, _imageInfo.LastMediaSequence); - } - - if(metadataBlock.creatorLength > 0 && - metadataBlock.creatorLength + metadataBlock.creatorOffset <= metadata.Length) - { - _imageInfo.Creator = - Encoding.Unicode.GetString(metadata, (int)metadataBlock.creatorOffset, - (int)(metadataBlock.creatorLength - 2)); - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting creator: {0}", - _imageInfo.Creator); - } - - if(metadataBlock.commentsOffset > 0 && - metadataBlock.commentsLength + metadataBlock.commentsOffset <= metadata.Length) - { - _imageInfo.Comments = - Encoding.Unicode.GetString(metadata, (int)metadataBlock.commentsOffset, - (int)(metadataBlock.commentsLength - 2)); - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting comments: {0}", - _imageInfo.Comments); - } - - if(metadataBlock.mediaTitleOffset > 0 && - metadataBlock.mediaTitleLength + metadataBlock.mediaTitleOffset <= metadata.Length) - { - _imageInfo.MediaTitle = - Encoding.Unicode.GetString(metadata, (int)metadataBlock.mediaTitleOffset, - (int)(metadataBlock.mediaTitleLength - 2)); - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting media title: {0}", - _imageInfo.MediaTitle); - } - - if(metadataBlock.mediaManufacturerOffset > 0 && - metadataBlock.mediaManufacturerLength + metadataBlock.mediaManufacturerOffset <= - metadata.Length) - { - _imageInfo.MediaManufacturer = - Encoding.Unicode.GetString(metadata, (int)metadataBlock.mediaManufacturerOffset, - (int)(metadataBlock.mediaManufacturerLength - 2)); - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting media manufacturer: {0}", - _imageInfo.MediaManufacturer); - } - - if(metadataBlock.mediaModelOffset > 0 && - metadataBlock.mediaModelLength + metadataBlock.mediaModelOffset <= metadata.Length) - { - _imageInfo.MediaModel = - Encoding.Unicode.GetString(metadata, (int)metadataBlock.mediaModelOffset, - (int)(metadataBlock.mediaModelLength - 2)); - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting media model: {0}", - _imageInfo.MediaModel); - } - - if(metadataBlock.mediaSerialNumberOffset > 0 && - metadataBlock.mediaSerialNumberLength + metadataBlock.mediaSerialNumberOffset <= - metadata.Length) - { - _imageInfo.MediaSerialNumber = - Encoding.Unicode.GetString(metadata, (int)metadataBlock.mediaSerialNumberOffset, - (int)(metadataBlock.mediaSerialNumberLength - 2)); - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting media serial number: {0}", - _imageInfo.MediaSerialNumber); - } - - if(metadataBlock.mediaBarcodeOffset > 0 && - metadataBlock.mediaBarcodeLength + metadataBlock.mediaBarcodeOffset <= metadata.Length) - { - _imageInfo.MediaBarcode = - Encoding.Unicode.GetString(metadata, (int)metadataBlock.mediaBarcodeOffset, - (int)(metadataBlock.mediaBarcodeLength - 2)); - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting media barcode: {0}", - _imageInfo.MediaBarcode); - } - - if(metadataBlock.mediaPartNumberOffset > 0 && - metadataBlock.mediaPartNumberLength + metadataBlock.mediaPartNumberOffset <= - metadata.Length) - { - _imageInfo.MediaPartNumber = - Encoding.Unicode.GetString(metadata, (int)metadataBlock.mediaPartNumberOffset, - (int)(metadataBlock.mediaPartNumberLength - 2)); - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting media part number: {0}", - _imageInfo.MediaPartNumber); - } - - if(metadataBlock.driveManufacturerOffset > 0 && - metadataBlock.driveManufacturerLength + metadataBlock.driveManufacturerOffset <= - metadata.Length) - { - _imageInfo.DriveManufacturer = - Encoding.Unicode.GetString(metadata, (int)metadataBlock.driveManufacturerOffset, - (int)(metadataBlock.driveManufacturerLength - 2)); - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting drive manufacturer: {0}", - _imageInfo.DriveManufacturer); - } - - if(metadataBlock.driveModelOffset > 0 && - metadataBlock.driveModelLength + metadataBlock.driveModelOffset <= metadata.Length) - { - _imageInfo.DriveModel = - Encoding.Unicode.GetString(metadata, (int)metadataBlock.driveModelOffset, - (int)(metadataBlock.driveModelLength - 2)); - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting drive model: {0}", - _imageInfo.DriveModel); - } - - if(metadataBlock.driveSerialNumberOffset > 0 && - metadataBlock.driveSerialNumberLength + metadataBlock.driveSerialNumberOffset <= - metadata.Length) - { - _imageInfo.DriveSerialNumber = - Encoding.Unicode.GetString(metadata, (int)metadataBlock.driveSerialNumberOffset, - (int)(metadataBlock.driveSerialNumberLength - 2)); - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting drive serial number: {0}", - _imageInfo.DriveSerialNumber); - } - - if(metadataBlock.driveFirmwareRevisionOffset > 0 && - metadataBlock.driveFirmwareRevisionLength + metadataBlock.driveFirmwareRevisionOffset <= - metadata.Length) - { - _imageInfo.DriveFirmwareRevision = - Encoding.Unicode.GetString(metadata, (int)metadataBlock.driveFirmwareRevisionOffset, - (int)(metadataBlock.driveFirmwareRevisionLength - 2)); - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting drive firmware revision: {0}", - _imageInfo.DriveFirmwareRevision); - } - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", - GC.GetTotalMemory(false)); - - break; - - // Optical disc tracks block - case BlockType.TracksBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.Read(_structureBytes, 0, _structureBytes.Length); - - TracksHeader tracksHeader = - Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(tracksHeader.identifier != BlockType.TracksBlock) - { - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Incorrect identifier for tracks block at position {0}", - entry.offset); - - break; - } - - _structureBytes = new byte[Marshal.SizeOf() * tracksHeader.entries]; - _imageStream.Read(_structureBytes, 0, _structureBytes.Length); - Crc64Context.Data(_structureBytes, out byte[] trksCrc); - - if(BitConverter.ToUInt64(trksCrc, 0) != tracksHeader.crc64) - { - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Incorrect CRC found: 0x{0:X16} found, expected 0x{1:X16}, continuing...", - BitConverter.ToUInt64(trksCrc, 0), tracksHeader.crc64); - - break; - } - - _imageStream.Position -= _structureBytes.Length; - - Tracks = new List(); - _trackFlags = new Dictionary(); - _trackIsrcs = new Dictionary(); - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Found {0} tracks at position {0}", - tracksHeader.entries, entry.offset); - - for(ushort i = 0; i < tracksHeader.entries; i++) - { - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.Read(_structureBytes, 0, _structureBytes.Length); - - TrackEntry trackEntry = - Marshal.ByteArrayToStructureLittleEndian(_structureBytes); - - Tracks.Add(new Track - { - Sequence = trackEntry.sequence, - Type = trackEntry.type, - StartSector = (ulong)trackEntry.start, - EndSector = (ulong)trackEntry.end, - Pregap = (ulong)trackEntry.pregap, - Session = trackEntry.session, - FileType = "BINARY" - }); - - if(trackEntry.type == TrackType.Data) - continue; - - _trackFlags.Add(trackEntry.sequence, trackEntry.flags); - - if(!string.IsNullOrEmpty(trackEntry.isrc)) - _trackIsrcs.Add(trackEntry.sequence, trackEntry.isrc); - } - - if(_trackFlags.Count > 0 && - !_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdTrackFlags)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackFlags); - - if(_trackIsrcs.Count > 0 && - !_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdTrackIsrc)) - _imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackIsrc); - - _imageInfo.HasPartitions = true; - _imageInfo.HasSessions = true; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", - GC.GetTotalMemory(false)); - - break; - - // CICM XML metadata block - case BlockType.CicmBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.Read(_structureBytes, 0, _structureBytes.Length); - - CicmMetadataBlock cicmBlock = - Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(cicmBlock.identifier != BlockType.CicmBlock) - break; - - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Found CICM XML metadata block at position {0}", entry.offset); - - byte[] cicmBytes = new byte[cicmBlock.length]; - _imageStream.Read(cicmBytes, 0, cicmBytes.Length); - var cicmMs = new MemoryStream(cicmBytes); - var cicmXs = new XmlSerializer(typeof(CICMMetadataType)); - - try - { - var sr = new StreamReader(cicmMs); - CicmMetadata = (CICMMetadataType)cicmXs.Deserialize(sr); - sr.Close(); - } - catch(XmlException ex) - { - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Exception {0} processing CICM XML metadata block", - ex.Message); - - CicmMetadata = null; - } - - break; - - // Dump hardware block - case BlockType.DumpHardwareBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.Read(_structureBytes, 0, _structureBytes.Length); - - DumpHardwareHeader dumpBlock = - Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(dumpBlock.identifier != BlockType.DumpHardwareBlock) - break; - - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Found dump hardware block at position {0}", entry.offset); - - _structureBytes = new byte[dumpBlock.length]; - _imageStream.Read(_structureBytes, 0, _structureBytes.Length); - Crc64Context.Data(_structureBytes, out byte[] dumpCrc); - - if(BitConverter.ToUInt64(dumpCrc, 0) != dumpBlock.crc64) - { - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Incorrect CRC found: 0x{0:X16} found, expected 0x{1:X16}, continuing...", - BitConverter.ToUInt64(dumpCrc, 0), dumpBlock.crc64); - - break; - } - - _imageStream.Position -= _structureBytes.Length; - - DumpHardware = new List(); - - for(ushort i = 0; i < dumpBlock.entries; i++) - { - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.Read(_structureBytes, 0, _structureBytes.Length); - - DumpHardwareEntry dumpEntry = - Marshal.SpanToStructureLittleEndian(_structureBytes); - - var dump = new DumpHardwareType - { - Software = new SoftwareType(), - Extents = new ExtentType[dumpEntry.extents] - }; - - byte[] tmp; - - if(dumpEntry.manufacturerLength > 0) - { - tmp = new byte[dumpEntry.manufacturerLength - 1]; - _imageStream.Read(tmp, 0, tmp.Length); - _imageStream.Position += 1; - dump.Manufacturer = Encoding.UTF8.GetString(tmp); - } - - if(dumpEntry.modelLength > 0) - { - tmp = new byte[dumpEntry.modelLength - 1]; - _imageStream.Read(tmp, 0, tmp.Length); - _imageStream.Position += 1; - dump.Model = Encoding.UTF8.GetString(tmp); - } - - if(dumpEntry.revisionLength > 0) - { - tmp = new byte[dumpEntry.revisionLength - 1]; - _imageStream.Read(tmp, 0, tmp.Length); - _imageStream.Position += 1; - dump.Revision = Encoding.UTF8.GetString(tmp); - } - - if(dumpEntry.firmwareLength > 0) - { - tmp = new byte[dumpEntry.firmwareLength - 1]; - _imageStream.Read(tmp, 0, tmp.Length); - _imageStream.Position += 1; - dump.Firmware = Encoding.UTF8.GetString(tmp); - } - - if(dumpEntry.serialLength > 0) - { - tmp = new byte[dumpEntry.serialLength - 1]; - _imageStream.Read(tmp, 0, tmp.Length); - _imageStream.Position += 1; - dump.Serial = Encoding.UTF8.GetString(tmp); - } - - if(dumpEntry.softwareNameLength > 0) - { - tmp = new byte[dumpEntry.softwareNameLength - 1]; - _imageStream.Read(tmp, 0, tmp.Length); - _imageStream.Position += 1; - dump.Software.Name = Encoding.UTF8.GetString(tmp); - } - - if(dumpEntry.softwareVersionLength > 0) - { - tmp = new byte[dumpEntry.softwareVersionLength - 1]; - _imageStream.Read(tmp, 0, tmp.Length); - _imageStream.Position += 1; - dump.Software.Version = Encoding.UTF8.GetString(tmp); - } - - if(dumpEntry.softwareOperatingSystemLength > 0) - { - tmp = new byte[dumpEntry.softwareOperatingSystemLength - 1]; - _imageStream.Position += 1; - _imageStream.Read(tmp, 0, tmp.Length); - dump.Software.OperatingSystem = Encoding.UTF8.GetString(tmp); - } - - tmp = new byte[16]; - - for(uint j = 0; j < dumpEntry.extents; j++) - { - _imageStream.Read(tmp, 0, tmp.Length); - - dump.Extents[j] = new ExtentType - { - Start = BitConverter.ToUInt64(tmp, 0), - End = BitConverter.ToUInt64(tmp, 8) - }; - } - - dump.Extents = dump.Extents.OrderBy(t => t.Start).ToArray(); - - if(dump.Extents.Length > 0) - DumpHardware.Add(dump); - } - - if(DumpHardware.Count == 0) - DumpHardware = null; - - break; - - // Tape partition block - case BlockType.TapePartitionBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.Read(_structureBytes, 0, _structureBytes.Length); - - TapePartitionHeader partitionHeader = - Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(partitionHeader.identifier != BlockType.TapePartitionBlock) - break; - - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Found tape partition block at position {0}", entry.offset); - - byte[] tapePartitionBytes = new byte[partitionHeader.length]; - _imageStream.Read(tapePartitionBytes, 0, tapePartitionBytes.Length); - - Span tapePartitions = - MemoryMarshal.Cast(tapePartitionBytes); - - TapePartitions = new List(); - - foreach(TapePartitionEntry tapePartition in tapePartitions) - TapePartitions.Add(new TapePartition - { - FirstBlock = tapePartition.FirstBlock, - LastBlock = tapePartition.LastBlock, - Number = tapePartition.Number - }); - - IsTape = true; - - break; - - // Tape file block - case BlockType.TapeFileBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.Read(_structureBytes, 0, _structureBytes.Length); - - TapeFileHeader fileHeader = - Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(fileHeader.identifier != BlockType.TapeFileBlock) - break; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Found tape file block at position {0}", - entry.offset); - - byte[] tapeFileBytes = new byte[fileHeader.length]; - _imageStream.Read(tapeFileBytes, 0, tapeFileBytes.Length); - Span tapeFiles = MemoryMarshal.Cast(tapeFileBytes); - Files = new List(); - - foreach(TapeFileEntry file in tapeFiles) - Files.Add(new TapeFile - { - FirstBlock = file.FirstBlock, - LastBlock = file.LastBlock, - Partition = file.Partition, - File = file.File - }); - - IsTape = true; - - break; - - // Optical disc tracks block - case BlockType.CompactDiscIndexesBlock: - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.Read(_structureBytes, 0, _structureBytes.Length); - - CompactDiscIndexesHeader indexesHeader = - Marshal.SpanToStructureLittleEndian(_structureBytes); - - if(indexesHeader.identifier != BlockType.CompactDiscIndexesBlock) - { - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Incorrect identifier for compact disc indexes block at position {0}", - entry.offset); - - break; - } - - _structureBytes = new byte[Marshal.SizeOf() * indexesHeader.entries]; - _imageStream.Read(_structureBytes, 0, _structureBytes.Length); - Crc64Context.Data(_structureBytes, out byte[] idsxCrc); - - if(BitConverter.ToUInt64(idsxCrc, 0) != indexesHeader.crc64) - { - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Incorrect CRC found: 0x{0:X16} found, expected 0x{1:X16}, continuing...", - BitConverter.ToUInt64(idsxCrc, 0), indexesHeader.crc64); - - break; - } - - _imageStream.Position -= _structureBytes.Length; - - compactDiscIndexes = new List(); - - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Found {0} compact disc indexes at position {0}", - indexesHeader.entries, entry.offset); - - for(ushort i = 0; i < indexesHeader.entries; i++) - { - _structureBytes = new byte[Marshal.SizeOf()]; - _imageStream.Read(_structureBytes, 0, _structureBytes.Length); - - compactDiscIndexes.Add(Marshal. - ByteArrayToStructureLittleEndian< - CompactDiscIndexEntry>(_structureBytes)); - } - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", - GC.GetTotalMemory(false)); - - break; - } - } - - if(!foundUserDataDdt) - { - ErrorMessage = "Could not find user data deduplication table."; - - return false; - } - - if(_sectorSuffixMs == null || - _sectorSuffixDdt == null || - _sectorPrefixMs == null || - _sectorPrefixDdt == null) - { - _sectorSuffixMs = null; - _sectorSuffixDdt = null; - _sectorPrefixMs = null; - _sectorPrefixDdt = null; - } - - if(!_inMemoryDdt) - _ddtEntryCache = new Dictionary(); - - // Initialize tracks, sessions and partitions - if(_imageInfo.XmlMediaType == XmlMediaType.OpticalDisc) - { - if(Tracks != null && - _mediaTags.TryGetValue(MediaTagType.CD_FullTOC, out byte[] fullToc)) - { - byte[] tmp = new byte[fullToc.Length + 2]; - Array.Copy(fullToc, 0, tmp, 2, fullToc.Length); - tmp[0] = (byte)(fullToc.Length >> 8); - tmp[1] = (byte)(fullToc.Length & 0xFF); - - FullTOC.CDFullTOC? decodedFullToc = FullTOC.Decode(tmp); - - if(decodedFullToc.HasValue) + if(_geometryBlock.identifier == BlockType.GeometryBlock) { - Dictionary leadOutStarts = new(); // Lead-out starts + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Geometry set to {0} cylinders {1} heads {2} sectors per track", + _geometryBlock.cylinders, _geometryBlock.heads, + _geometryBlock.sectorsPerTrack); - foreach(FullTOC.TrackDataDescriptor trk in - decodedFullToc.Value.TrackDescriptors.Where(trk => (trk.ADR == 1 || trk.ADR == 4) && - trk.POINT == 0xA2)) + _imageInfo.Cylinders = _geometryBlock.cylinders; + _imageInfo.Heads = _geometryBlock.heads; + _imageInfo.SectorsPerTrack = _geometryBlock.sectorsPerTrack; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", + GC.GetTotalMemory(false)); + } + + break; + + // Metadata block + case BlockType.MetadataBlock: + _structureBytes = new byte[Marshal.SizeOf()]; + _imageStream.Read(_structureBytes, 0, _structureBytes.Length); + + MetadataBlock metadataBlock = + Marshal.SpanToStructureLittleEndian(_structureBytes); + + if(metadataBlock.identifier != entry.blockType) + { + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Incorrect identifier for data block at position {0}", + entry.offset); + + break; + } + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Found metadata block at position {0}", + entry.offset); + + var metadata = new byte[metadataBlock.blockSize]; + _imageStream.Position = (long)entry.offset; + _imageStream.Read(metadata, 0, metadata.Length); + + if(metadataBlock.mediaSequence > 0 && + metadataBlock.lastMediaSequence > 0) + { + _imageInfo.MediaSequence = metadataBlock.mediaSequence; + _imageInfo.LastMediaSequence = metadataBlock.lastMediaSequence; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting media sequence as {0} of {1}", + _imageInfo.MediaSequence, _imageInfo.LastMediaSequence); + } + + if(metadataBlock.creatorLength > 0 && + metadataBlock.creatorLength + metadataBlock.creatorOffset <= metadata.Length) + { + _imageInfo.Creator = + Encoding.Unicode.GetString(metadata, (int)metadataBlock.creatorOffset, + (int)(metadataBlock.creatorLength - 2)); + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting creator: {0}", + _imageInfo.Creator); + } + + if(metadataBlock.commentsOffset > 0 && + metadataBlock.commentsLength + metadataBlock.commentsOffset <= metadata.Length) + { + _imageInfo.Comments = + Encoding.Unicode.GetString(metadata, (int)metadataBlock.commentsOffset, + (int)(metadataBlock.commentsLength - 2)); + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting comments: {0}", + _imageInfo.Comments); + } + + if(metadataBlock.mediaTitleOffset > 0 && + metadataBlock.mediaTitleLength + metadataBlock.mediaTitleOffset <= metadata.Length) + { + _imageInfo.MediaTitle = + Encoding.Unicode.GetString(metadata, (int)metadataBlock.mediaTitleOffset, + (int)(metadataBlock.mediaTitleLength - 2)); + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting media title: {0}", + _imageInfo.MediaTitle); + } + + if(metadataBlock.mediaManufacturerOffset > 0 && + metadataBlock.mediaManufacturerLength + metadataBlock.mediaManufacturerOffset <= + metadata.Length) + { + _imageInfo.MediaManufacturer = + Encoding.Unicode.GetString(metadata, (int)metadataBlock.mediaManufacturerOffset, + (int)(metadataBlock.mediaManufacturerLength - 2)); + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting media manufacturer: {0}", + _imageInfo.MediaManufacturer); + } + + if(metadataBlock.mediaModelOffset > 0 && + metadataBlock.mediaModelLength + metadataBlock.mediaModelOffset <= metadata.Length) + { + _imageInfo.MediaModel = + Encoding.Unicode.GetString(metadata, (int)metadataBlock.mediaModelOffset, + (int)(metadataBlock.mediaModelLength - 2)); + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting media model: {0}", + _imageInfo.MediaModel); + } + + if(metadataBlock.mediaSerialNumberOffset > 0 && + metadataBlock.mediaSerialNumberLength + metadataBlock.mediaSerialNumberOffset <= + metadata.Length) + { + _imageInfo.MediaSerialNumber = + Encoding.Unicode.GetString(metadata, (int)metadataBlock.mediaSerialNumberOffset, + (int)(metadataBlock.mediaSerialNumberLength - 2)); + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting media serial number: {0}", + _imageInfo.MediaSerialNumber); + } + + if(metadataBlock.mediaBarcodeOffset > 0 && + metadataBlock.mediaBarcodeLength + metadataBlock.mediaBarcodeOffset <= metadata.Length) + { + _imageInfo.MediaBarcode = + Encoding.Unicode.GetString(metadata, (int)metadataBlock.mediaBarcodeOffset, + (int)(metadataBlock.mediaBarcodeLength - 2)); + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting media barcode: {0}", + _imageInfo.MediaBarcode); + } + + if(metadataBlock.mediaPartNumberOffset > 0 && + metadataBlock.mediaPartNumberLength + metadataBlock.mediaPartNumberOffset <= metadata.Length) + { + _imageInfo.MediaPartNumber = + Encoding.Unicode.GetString(metadata, (int)metadataBlock.mediaPartNumberOffset, + (int)(metadataBlock.mediaPartNumberLength - 2)); + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting media part number: {0}", + _imageInfo.MediaPartNumber); + } + + if(metadataBlock.driveManufacturerOffset > 0 && + metadataBlock.driveManufacturerLength + metadataBlock.driveManufacturerOffset <= + metadata.Length) + { + _imageInfo.DriveManufacturer = + Encoding.Unicode.GetString(metadata, (int)metadataBlock.driveManufacturerOffset, + (int)(metadataBlock.driveManufacturerLength - 2)); + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting drive manufacturer: {0}", + _imageInfo.DriveManufacturer); + } + + if(metadataBlock.driveModelOffset > 0 && + metadataBlock.driveModelLength + metadataBlock.driveModelOffset <= metadata.Length) + { + _imageInfo.DriveModel = + Encoding.Unicode.GetString(metadata, (int)metadataBlock.driveModelOffset, + (int)(metadataBlock.driveModelLength - 2)); + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting drive model: {0}", + _imageInfo.DriveModel); + } + + if(metadataBlock.driveSerialNumberOffset > 0 && + metadataBlock.driveSerialNumberLength + metadataBlock.driveSerialNumberOffset <= + metadata.Length) + { + _imageInfo.DriveSerialNumber = + Encoding.Unicode.GetString(metadata, (int)metadataBlock.driveSerialNumberOffset, + (int)(metadataBlock.driveSerialNumberLength - 2)); + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting drive serial number: {0}", + _imageInfo.DriveSerialNumber); + } + + if(metadataBlock.driveFirmwareRevisionOffset > 0 && + metadataBlock.driveFirmwareRevisionLength + metadataBlock.driveFirmwareRevisionOffset <= + metadata.Length) + { + _imageInfo.DriveFirmwareRevision = + Encoding.Unicode.GetString(metadata, (int)metadataBlock.driveFirmwareRevisionOffset, + (int)(metadataBlock.driveFirmwareRevisionLength - 2)); + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Setting drive firmware revision: {0}", + _imageInfo.DriveFirmwareRevision); + } + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", + GC.GetTotalMemory(false)); + + break; + + // Optical disc tracks block + case BlockType.TracksBlock: + _structureBytes = new byte[Marshal.SizeOf()]; + _imageStream.Read(_structureBytes, 0, _structureBytes.Length); + + TracksHeader tracksHeader = Marshal.SpanToStructureLittleEndian(_structureBytes); + + if(tracksHeader.identifier != BlockType.TracksBlock) + { + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Incorrect identifier for tracks block at position {0}", + entry.offset); + + break; + } + + _structureBytes = new byte[Marshal.SizeOf() * tracksHeader.entries]; + _imageStream.Read(_structureBytes, 0, _structureBytes.Length); + Crc64Context.Data(_structureBytes, out byte[] trksCrc); + + if(BitConverter.ToUInt64(trksCrc, 0) != tracksHeader.crc64) + { + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Incorrect CRC found: 0x{0:X16} found, expected 0x{1:X16}, continuing...", + BitConverter.ToUInt64(trksCrc, 0), tracksHeader.crc64); + + break; + } + + _imageStream.Position -= _structureBytes.Length; + + Tracks = new List(); + _trackFlags = new Dictionary(); + _trackIsrcs = new Dictionary(); + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Found {0} tracks at position {0}", + tracksHeader.entries, entry.offset); + + for(ushort i = 0; i < tracksHeader.entries; i++) + { + _structureBytes = new byte[Marshal.SizeOf()]; + _imageStream.Read(_structureBytes, 0, _structureBytes.Length); + + TrackEntry trackEntry = + Marshal.ByteArrayToStructureLittleEndian(_structureBytes); + + Tracks.Add(new Track { - int phour, pmin, psec, pframe; + Sequence = trackEntry.sequence, + Type = trackEntry.type, + StartSector = (ulong)trackEntry.start, + EndSector = (ulong)trackEntry.end, + Pregap = (ulong)trackEntry.pregap, + Session = trackEntry.session, + FileType = "BINARY" + }); - if(trk.PFRAME == 0) + if(trackEntry.type == TrackType.Data) + continue; + + _trackFlags.Add(trackEntry.sequence, trackEntry.flags); + + if(!string.IsNullOrEmpty(trackEntry.isrc)) + _trackIsrcs.Add(trackEntry.sequence, trackEntry.isrc); + } + + if(_trackFlags.Count > 0 && + !_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdTrackFlags)) + _imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackFlags); + + if(_trackIsrcs.Count > 0 && + !_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdTrackIsrc)) + _imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackIsrc); + + _imageInfo.HasPartitions = true; + _imageInfo.HasSessions = true; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", + GC.GetTotalMemory(false)); + + break; + + // CICM XML metadata block + case BlockType.CicmBlock: + _structureBytes = new byte[Marshal.SizeOf()]; + _imageStream.Read(_structureBytes, 0, _structureBytes.Length); + + CicmMetadataBlock cicmBlock = + Marshal.SpanToStructureLittleEndian(_structureBytes); + + if(cicmBlock.identifier != BlockType.CicmBlock) + break; + + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Found CICM XML metadata block at position {0}", entry.offset); + + var cicmBytes = new byte[cicmBlock.length]; + _imageStream.Read(cicmBytes, 0, cicmBytes.Length); + var cicmMs = new MemoryStream(cicmBytes); + var cicmXs = new XmlSerializer(typeof(CICMMetadataType)); + + try + { + var sr = new StreamReader(cicmMs); + CicmMetadata = (CICMMetadataType)cicmXs.Deserialize(sr); + sr.Close(); + } + catch(XmlException ex) + { + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Exception {0} processing CICM XML metadata block", ex.Message); + + CicmMetadata = null; + } + + break; + + // Dump hardware block + case BlockType.DumpHardwareBlock: + _structureBytes = new byte[Marshal.SizeOf()]; + _imageStream.Read(_structureBytes, 0, _structureBytes.Length); + + DumpHardwareHeader dumpBlock = + Marshal.SpanToStructureLittleEndian(_structureBytes); + + if(dumpBlock.identifier != BlockType.DumpHardwareBlock) + break; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Found dump hardware block at position {0}", + entry.offset); + + _structureBytes = new byte[dumpBlock.length]; + _imageStream.Read(_structureBytes, 0, _structureBytes.Length); + Crc64Context.Data(_structureBytes, out byte[] dumpCrc); + + if(BitConverter.ToUInt64(dumpCrc, 0) != dumpBlock.crc64) + { + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Incorrect CRC found: 0x{0:X16} found, expected 0x{1:X16}, continuing...", + BitConverter.ToUInt64(dumpCrc, 0), dumpBlock.crc64); + + break; + } + + _imageStream.Position -= _structureBytes.Length; + + DumpHardware = new List(); + + for(ushort i = 0; i < dumpBlock.entries; i++) + { + _structureBytes = new byte[Marshal.SizeOf()]; + _imageStream.Read(_structureBytes, 0, _structureBytes.Length); + + DumpHardwareEntry dumpEntry = + Marshal.SpanToStructureLittleEndian(_structureBytes); + + var dump = new DumpHardwareType + { + Software = new SoftwareType(), + Extents = new ExtentType[dumpEntry.extents] + }; + + byte[] tmp; + + if(dumpEntry.manufacturerLength > 0) + { + tmp = new byte[dumpEntry.manufacturerLength - 1]; + _imageStream.Read(tmp, 0, tmp.Length); + _imageStream.Position += 1; + dump.Manufacturer = Encoding.UTF8.GetString(tmp); + } + + if(dumpEntry.modelLength > 0) + { + tmp = new byte[dumpEntry.modelLength - 1]; + _imageStream.Read(tmp, 0, tmp.Length); + _imageStream.Position += 1; + dump.Model = Encoding.UTF8.GetString(tmp); + } + + if(dumpEntry.revisionLength > 0) + { + tmp = new byte[dumpEntry.revisionLength - 1]; + _imageStream.Read(tmp, 0, tmp.Length); + _imageStream.Position += 1; + dump.Revision = Encoding.UTF8.GetString(tmp); + } + + if(dumpEntry.firmwareLength > 0) + { + tmp = new byte[dumpEntry.firmwareLength - 1]; + _imageStream.Read(tmp, 0, tmp.Length); + _imageStream.Position += 1; + dump.Firmware = Encoding.UTF8.GetString(tmp); + } + + if(dumpEntry.serialLength > 0) + { + tmp = new byte[dumpEntry.serialLength - 1]; + _imageStream.Read(tmp, 0, tmp.Length); + _imageStream.Position += 1; + dump.Serial = Encoding.UTF8.GetString(tmp); + } + + if(dumpEntry.softwareNameLength > 0) + { + tmp = new byte[dumpEntry.softwareNameLength - 1]; + _imageStream.Read(tmp, 0, tmp.Length); + _imageStream.Position += 1; + dump.Software.Name = Encoding.UTF8.GetString(tmp); + } + + if(dumpEntry.softwareVersionLength > 0) + { + tmp = new byte[dumpEntry.softwareVersionLength - 1]; + _imageStream.Read(tmp, 0, tmp.Length); + _imageStream.Position += 1; + dump.Software.Version = Encoding.UTF8.GetString(tmp); + } + + if(dumpEntry.softwareOperatingSystemLength > 0) + { + tmp = new byte[dumpEntry.softwareOperatingSystemLength - 1]; + _imageStream.Position += 1; + _imageStream.Read(tmp, 0, tmp.Length); + dump.Software.OperatingSystem = Encoding.UTF8.GetString(tmp); + } + + tmp = new byte[16]; + + for(uint j = 0; j < dumpEntry.extents; j++) + { + _imageStream.Read(tmp, 0, tmp.Length); + + dump.Extents[j] = new ExtentType { - pframe = 74; + Start = BitConverter.ToUInt64(tmp, 0), + End = BitConverter.ToUInt64(tmp, 8) + }; + } - if(trk.PSEC == 0) + dump.Extents = dump.Extents.OrderBy(t => t.Start).ToArray(); + + if(dump.Extents.Length > 0) + DumpHardware.Add(dump); + } + + if(DumpHardware.Count == 0) + DumpHardware = null; + + break; + + // Tape partition block + case BlockType.TapePartitionBlock: + _structureBytes = new byte[Marshal.SizeOf()]; + _imageStream.Read(_structureBytes, 0, _structureBytes.Length); + + TapePartitionHeader partitionHeader = + Marshal.SpanToStructureLittleEndian(_structureBytes); + + if(partitionHeader.identifier != BlockType.TapePartitionBlock) + break; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Found tape partition block at position {0}", + entry.offset); + + var tapePartitionBytes = new byte[partitionHeader.length]; + _imageStream.Read(tapePartitionBytes, 0, tapePartitionBytes.Length); + + Span tapePartitions = + MemoryMarshal.Cast(tapePartitionBytes); + + TapePartitions = new List(); + + foreach(TapePartitionEntry tapePartition in tapePartitions) + TapePartitions.Add(new TapePartition + { + FirstBlock = tapePartition.FirstBlock, + LastBlock = tapePartition.LastBlock, + Number = tapePartition.Number + }); + + IsTape = true; + + break; + + // Tape file block + case BlockType.TapeFileBlock: + _structureBytes = new byte[Marshal.SizeOf()]; + _imageStream.Read(_structureBytes, 0, _structureBytes.Length); + + TapeFileHeader fileHeader = + Marshal.SpanToStructureLittleEndian(_structureBytes); + + if(fileHeader.identifier != BlockType.TapeFileBlock) + break; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Found tape file block at position {0}", + entry.offset); + + var tapeFileBytes = new byte[fileHeader.length]; + _imageStream.Read(tapeFileBytes, 0, tapeFileBytes.Length); + Span tapeFiles = MemoryMarshal.Cast(tapeFileBytes); + Files = new List(); + + foreach(TapeFileEntry file in tapeFiles) + Files.Add(new TapeFile + { + FirstBlock = file.FirstBlock, + LastBlock = file.LastBlock, + Partition = file.Partition, + File = file.File + }); + + IsTape = true; + + break; + + // Optical disc tracks block + case BlockType.CompactDiscIndexesBlock: + _structureBytes = new byte[Marshal.SizeOf()]; + _imageStream.Read(_structureBytes, 0, _structureBytes.Length); + + CompactDiscIndexesHeader indexesHeader = + Marshal.SpanToStructureLittleEndian(_structureBytes); + + if(indexesHeader.identifier != BlockType.CompactDiscIndexesBlock) + { + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Incorrect identifier for compact disc indexes block at position {0}", + entry.offset); + + break; + } + + _structureBytes = new byte[Marshal.SizeOf() * indexesHeader.entries]; + _imageStream.Read(_structureBytes, 0, _structureBytes.Length); + Crc64Context.Data(_structureBytes, out byte[] idsxCrc); + + if(BitConverter.ToUInt64(idsxCrc, 0) != indexesHeader.crc64) + { + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Incorrect CRC found: 0x{0:X16} found, expected 0x{1:X16}, continuing...", + BitConverter.ToUInt64(idsxCrc, 0), indexesHeader.crc64); + + break; + } + + _imageStream.Position -= _structureBytes.Length; + + compactDiscIndexes = new List(); + + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Found {0} compact disc indexes at position {0}", + indexesHeader.entries, entry.offset); + + for(ushort i = 0; i < indexesHeader.entries; i++) + { + _structureBytes = new byte[Marshal.SizeOf()]; + _imageStream.Read(_structureBytes, 0, _structureBytes.Length); + + compactDiscIndexes.Add(Marshal. + ByteArrayToStructureLittleEndian< + CompactDiscIndexEntry>(_structureBytes)); + } + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", + GC.GetTotalMemory(false)); + + break; + } + } + + if(!foundUserDataDdt) + { + ErrorMessage = "Could not find user data deduplication table."; + + return false; + } + + if(_sectorSuffixMs == null || + _sectorSuffixDdt == null || + _sectorPrefixMs == null || + _sectorPrefixDdt == null) + { + _sectorSuffixMs = null; + _sectorSuffixDdt = null; + _sectorPrefixMs = null; + _sectorPrefixDdt = null; + } + + if(!_inMemoryDdt) + _ddtEntryCache = new Dictionary(); + + // Initialize tracks, sessions and partitions + if(_imageInfo.XmlMediaType == XmlMediaType.OpticalDisc) + { + if(Tracks != null && + _mediaTags.TryGetValue(MediaTagType.CD_FullTOC, out byte[] fullToc)) + { + var tmp = new byte[fullToc.Length + 2]; + Array.Copy(fullToc, 0, tmp, 2, fullToc.Length); + tmp[0] = (byte)(fullToc.Length >> 8); + tmp[1] = (byte)(fullToc.Length & 0xFF); + + FullTOC.CDFullTOC? decodedFullToc = FullTOC.Decode(tmp); + + if(decodedFullToc.HasValue) + { + Dictionary leadOutStarts = new(); // Lead-out starts + + foreach(FullTOC.TrackDataDescriptor trk in + decodedFullToc.Value.TrackDescriptors.Where(trk => trk.ADR is 1 or 4 && + trk.POINT == 0xA2)) + { + int phour, pmin, psec, pframe; + + if(trk.PFRAME == 0) + { + pframe = 74; + + if(trk.PSEC == 0) + { + psec = 59; + + if(trk.PMIN == 0) { - psec = 59; - - if(trk.PMIN == 0) - { - pmin = 59; - phour = trk.PHOUR - 1; - } - else - { - pmin = trk.PMIN - 1; - phour = trk.PHOUR; - } + pmin = 59; + phour = trk.PHOUR - 1; } else { - psec = trk.PSEC - 1; - pmin = trk.PMIN; + pmin = trk.PMIN - 1; phour = trk.PHOUR; } } else { - pframe = trk.PFRAME - 1; - psec = trk.PSEC; - pmin = trk.PMIN; - phour = trk.PHOUR; + psec = trk.PSEC - 1; + pmin = trk.PMIN; + phour = trk.PHOUR; } - - int lastSector = (phour * 3600 * 75) + (pmin * 60 * 75) + (psec * 75) + pframe - 150; - leadOutStarts?.Add(trk.SessionNumber, lastSector + 1); } - - foreach(KeyValuePair leadOuts in leadOutStarts) + else { - var lastTrackInSession = new Track(); - - foreach(Track trk in Tracks.Where(trk => trk.Session == leadOuts.Key). - Where(trk => trk.Sequence > lastTrackInSession.Sequence)) - lastTrackInSession = trk; - - if(lastTrackInSession.Sequence == 0 || - lastTrackInSession.EndSector == (ulong)leadOuts.Value - 1) - continue; - - lastTrackInSession.EndSector = (ulong)leadOuts.Value - 1; + pframe = trk.PFRAME - 1; + psec = trk.PSEC; + pmin = trk.PMIN; + phour = trk.PHOUR; } - } - } - AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", - GC.GetTotalMemory(false)); - - if(Tracks == null || - Tracks.Count == 0) - { - Tracks = new List - { - new() - { - BytesPerSector = (int)_imageInfo.SectorSize, - EndSector = _imageInfo.Sectors - 1, - FileType = "BINARY", - RawBytesPerSector = (int)_imageInfo.SectorSize, - Session = 1, - Sequence = 1, - Type = TrackType.Data - } - }; - - _trackFlags = new Dictionary - { - { - 1, (byte)CdFlags.DataTrack - } - }; - - _trackIsrcs = new Dictionary(); - } - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", - GC.GetTotalMemory(false)); - - Sessions = new List(); - - for(int i = 1; i <= Tracks.Max(t => t.Session); i++) - Sessions.Add(new Session - { - Sequence = (ushort)i, - StartTrack = Tracks.Where(t => t.Session == i).Min(t => t.Sequence), - EndTrack = Tracks.Where(t => t.Session == i).Max(t => t.Sequence), - StartSector = Tracks.Where(t => t.Session == i).Min(t => t.StartSector), - EndSector = Tracks.Where(t => t.Session == i).Max(t => t.EndSector) - }); - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", - GC.GetTotalMemory(false)); - - foreach(Track track in Tracks.OrderBy(t => t.StartSector)) - { - if(track.Sequence == 1) - { - track.Pregap = 150; - track.Indexes[0] = -150; - track.Indexes[1] = (int)track.StartSector; - - continue; + int lastSector = phour * 3600 * 75 + pmin * 60 * 75 + psec * 75 + pframe - 150; + leadOutStarts?.Add(trk.SessionNumber, lastSector + 1); } - if(track.Pregap > 0) + foreach(KeyValuePair leadOuts in leadOutStarts) { - track.Indexes[0] = (int)track.StartSector; - track.Indexes[1] = (int)(track.StartSector + track.Pregap); - } - else - track.Indexes[1] = (int)track.StartSector; - } + var lastTrackInSession = new Track(); - ulong currentTrackOffset = 0; - Partitions = new List(); + foreach(Track trk in Tracks.Where(trk => trk.Session == leadOuts.Key). + Where(trk => trk.Sequence > lastTrackInSession.Sequence)) + lastTrackInSession = trk; - foreach(Track track in Tracks.OrderBy(t => t.StartSector)) - { - Partitions.Add(new Partition - { - Sequence = track.Sequence, - Type = track.Type.ToString(), - Name = $"Track {track.Sequence}", - Offset = currentTrackOffset, - Start = (ulong)track.Indexes[1], - Size = (track.EndSector - (ulong)track.Indexes[1] + 1) * (ulong)track.BytesPerSector, - Length = track.EndSector - (ulong)track.Indexes[1] + 1, - Scheme = "Optical disc track" - }); - - currentTrackOffset += (track.EndSector - track.StartSector + 1) * (ulong)track.BytesPerSector; - } - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", - GC.GetTotalMemory(false)); - - Track[] tracks = Tracks.ToArray(); - - foreach(Track trk in tracks) - { - ErrorNumber errno = ReadSector(trk.StartSector, out byte[] sector); - - if(errno != ErrorNumber.NoError) - continue; - - trk.BytesPerSector = sector.Length; - - trk.RawBytesPerSector = - (_sectorPrefix != null && _sectorSuffix != null) || - (_sectorPrefixDdt != null && _sectorSuffixDdt != null) ? 2352 : sector.Length; - - if(_sectorSubchannel == null) - continue; - - trk.SubchannelFile = trk.File; - trk.SubchannelFilter = trk.Filter; - trk.SubchannelType = TrackSubchannelType.Raw; - } - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", - GC.GetTotalMemory(false)); - - Tracks = tracks.ToList(); - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", - GC.GetTotalMemory(false)); - - if(compactDiscIndexes != null) - { - foreach(CompactDiscIndexEntry compactDiscIndex in compactDiscIndexes.OrderBy(i => i.Track). - ThenBy(i => i.Index)) - { - Track track = Tracks.FirstOrDefault(t => t.Sequence == compactDiscIndex.Track); - - if(track is null) + if(lastTrackInSession.Sequence == 0 || + lastTrackInSession.EndSector == (ulong)leadOuts.Value - 1) continue; - track.Indexes[compactDiscIndex.Index] = compactDiscIndex.Lba; + lastTrackInSession.EndSector = (ulong)leadOuts.Value - 1; } } } - else + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", + GC.GetTotalMemory(false)); + + if(Tracks == null || + Tracks.Count == 0) { - Tracks = null; - Sessions = null; - Partitions = null; - } - } - - // Creating new - else - { - // Checking that DDT is smaller than requested size - _inMemoryDdt = sectors <= maxDdtSize * 1024 * 1024 / sizeof(ulong); - - // If in memory, easy - if(_inMemoryDdt) - { - if(IsTape) - _tapeDdt = new Dictionary(); - else - _userDataDdt = new ulong[sectors]; - } - - // If not, create the block, add to index, and enlarge the file to allow the DDT to exist on-disk - else - { - _outMemoryDdtPosition = _imageStream.Position; - - _index.Add(new IndexEntry + Tracks = new List { - blockType = BlockType.DeDuplicationTable, - dataType = DataType.UserData, - offset = (ulong)_outMemoryDdtPosition - }); - - // CRC64 will be calculated later - var ddtHeader = new DdtHeader - { - identifier = BlockType.DeDuplicationTable, - type = DataType.UserData, - compression = CompressionType.None, - shift = _shift, - entries = sectors, - cmpLength = sectors * sizeof(ulong), - length = sectors * sizeof(ulong) + new() + { + BytesPerSector = (int)_imageInfo.SectorSize, + EndSector = _imageInfo.Sectors - 1, + FileType = "BINARY", + RawBytesPerSector = (int)_imageInfo.SectorSize, + Session = 1, + Sequence = 1, + Type = TrackType.Data + } }; - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref ddtHeader); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _structureBytes = null; + _trackFlags = new Dictionary + { + { + 1, (byte)CdFlags.DataTrack + } + }; - _imageStream.Position += (long)(sectors * sizeof(ulong)) - 1; - _imageStream.WriteByte(0); + _trackIsrcs = new Dictionary(); } - if(doMd5) - _md5Provider = new Md5Context(); + AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", + GC.GetTotalMemory(false)); - if(doSha1) - _sha1Provider = new Sha1Context(); + Sessions = new List(); - if(doSha256) - _sha256Provider = new Sha256Context(); + for(var i = 1; i <= Tracks.Max(t => t.Session); i++) + Sessions.Add(new Session + { + Sequence = (ushort)i, + StartTrack = Tracks.Where(t => t.Session == i).Min(t => t.Sequence), + EndTrack = Tracks.Where(t => t.Session == i).Max(t => t.Sequence), + StartSector = Tracks.Where(t => t.Session == i).Min(t => t.StartSector), + EndSector = Tracks.Where(t => t.Session == i).Max(t => t.EndSector) + }); - if(doSpamsum) - _spamsumProvider = new SpamSumContext(); + AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", + GC.GetTotalMemory(false)); + + foreach(Track track in Tracks.OrderBy(t => t.StartSector)) + { + if(track.Sequence == 1) + { + track.Pregap = 150; + track.Indexes[0] = -150; + track.Indexes[1] = (int)track.StartSector; + + continue; + } + + if(track.Pregap > 0) + { + track.Indexes[0] = (int)track.StartSector; + track.Indexes[1] = (int)(track.StartSector + track.Pregap); + } + else + track.Indexes[1] = (int)track.StartSector; + } + + ulong currentTrackOffset = 0; + Partitions = new List(); + + foreach(Track track in Tracks.OrderBy(t => t.StartSector)) + { + Partitions.Add(new Partition + { + Sequence = track.Sequence, + Type = track.Type.ToString(), + Name = $"Track {track.Sequence}", + Offset = currentTrackOffset, + Start = (ulong)track.Indexes[1], + Size = (track.EndSector - (ulong)track.Indexes[1] + 1) * (ulong)track.BytesPerSector, + Length = track.EndSector - (ulong)track.Indexes[1] + 1, + Scheme = "Optical disc track" + }); + + currentTrackOffset += (track.EndSector - track.StartSector + 1) * (ulong)track.BytesPerSector; + } + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", + GC.GetTotalMemory(false)); + + Track[] tracks = Tracks.ToArray(); + + foreach(Track trk in tracks) + { + ErrorNumber errno = ReadSector(trk.StartSector, out byte[] sector); + + if(errno != ErrorNumber.NoError) + continue; + + trk.BytesPerSector = sector.Length; + + trk.RawBytesPerSector = + _sectorPrefix != null && _sectorSuffix != null || + _sectorPrefixDdt != null && _sectorSuffixDdt != null ? 2352 : sector.Length; + + if(_sectorSubchannel == null) + continue; + + trk.SubchannelFile = trk.File; + trk.SubchannelFilter = trk.Filter; + trk.SubchannelType = TrackSubchannelType.Raw; + } + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", + GC.GetTotalMemory(false)); + + Tracks = tracks.ToList(); + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes", + GC.GetTotalMemory(false)); + + if(compactDiscIndexes != null) + foreach(CompactDiscIndexEntry compactDiscIndex in compactDiscIndexes.OrderBy(i => i.Track). + ThenBy(i => i.Index)) + { + Track track = Tracks.FirstOrDefault(t => t.Sequence == compactDiscIndex.Track); + + if(track is null) + continue; + + track.Indexes[compactDiscIndex.Index] = compactDiscIndex.Lba; + } + } + else + { + Tracks = null; + Sessions = null; + Partitions = null; } - - AaruConsole.DebugWriteLine("Aaru Format plugin", "In memory DDT?: {0}", _inMemoryDdt); - - _imageStream.Seek(0, SeekOrigin.End); - - IsWriting = true; - ErrorMessage = null; - - return true; } - /// - public bool WriteMediaTag(byte[] data, MediaTagType tag) + // Creating new + else { - if(!IsWriting) + // Checking that DDT is smaller than requested size + _inMemoryDdt = sectors <= maxDdtSize * 1024 * 1024 / sizeof(ulong); + + // If in memory, easy + if(_inMemoryDdt) { - ErrorMessage = "Tried to write on a non-writable image"; - - return false; - } - - if(_mediaTags.ContainsKey(tag)) - _mediaTags.Remove(tag); - - _mediaTags.Add(tag, data); - - ErrorMessage = ""; - - return true; - } - - /// - public bool WriteSector(byte[] data, ulong sectorAddress) - { - if(!IsWriting) - { - ErrorMessage = "Tried to write on a non-writable image"; - - return false; - } - - if(sectorAddress >= Info.Sectors && - !IsTape) - { - ErrorMessage = "Tried to write past image size"; - - return false; - } - - if((_imageInfo.XmlMediaType != XmlMediaType.OpticalDisc || !_writingLong) && - !_rewinded) - { - if(sectorAddress <= _lastWrittenBlock && _alreadyWrittenZero) - { - _rewinded = true; - _md5Provider = null; - _sha1Provider = null; - _sha256Provider = null; - _spamsumProvider = null; - } - - _md5Provider?.Update(data); - _sha1Provider?.Update(data); - _sha256Provider?.Update(data); - _spamsumProvider?.Update(data); - _lastWrittenBlock = sectorAddress; - } - - if(sectorAddress == 0) - _alreadyWrittenZero = true; - - byte[] hash = null; - _writtenSectors++; - - // Compute hash only if asked to deduplicate, or the sector is empty (those will always be deduplicated) - if(_deduplicate || ArrayHelpers.ArrayIsNullOrEmpty(data)) - hash = _checksumProvider.ComputeHash(data); - - string hashString = null; - - if(hash != null) - { - var hashSb = new StringBuilder(); - - foreach(byte h in hash) - hashSb.Append(h.ToString("x2")); - - hashString = hashSb.ToString(); - - if(_deduplicationTable.TryGetValue(hashString, out ulong pointer)) - { - SetDdtEntry(sectorAddress, pointer); - ErrorMessage = ""; - - return true; - } - } - - var trk = new Track(); - - // If optical disc check track - if(_imageInfo.XmlMediaType == XmlMediaType.OpticalDisc) - { - trk = Tracks.FirstOrDefault(t => sectorAddress >= t.StartSector && sectorAddress <= t.EndSector) ?? - new Track(); - - if(trk.Sequence == 0 && - trk.StartSector == 0 && - trk.EndSector == 0) - trk.Type = TrackType.Data; // TODO: Check intersession data type - } - - // Close current block first - if(_writingBuffer != null && - - // When sector siz changes - (_currentBlockHeader.sectorSize != data.Length || - - // When block if filled - _currentBlockOffset == 1 << _shift || - - // When we change to/from CompactDisc audio - (_currentBlockHeader.compression == CompressionType.Flac && trk.Type != TrackType.Audio))) - { - _currentBlockHeader.length = _currentBlockOffset * _currentBlockHeader.sectorSize; - _currentBlockHeader.crc64 = BitConverter.ToUInt64(_crc64.Final(), 0); - - var cmpCrc64Context = new Crc64Context(); - - byte[] lzmaProperties = Array.Empty(); - int compressedLength; - - switch(_currentBlockHeader.compression) - { - case CompressionType.Flac: - { - uint currentSamples = _currentBlockOffset * SAMPLES_PER_SECTOR; - uint flacBlockSize = _currentBlockOffset * SAMPLES_PER_SECTOR; - - if(flacBlockSize > MAX_FLAKE_BLOCK) - flacBlockSize = MAX_FLAKE_BLOCK; - - if(flacBlockSize < MIN_FLAKE_BLOCK) - flacBlockSize = MIN_FLAKE_BLOCK; - - long remaining = currentSamples % flacBlockSize; - - // Fill FLAC block - if(remaining != 0) - for(int r = 0; r < remaining * 4; r++) - _writingBuffer[_writingBufferPosition + r] = 0; - - compressedLength = FLAC.EncodeBuffer(_writingBuffer, _compressedBuffer, flacBlockSize, true, - false, "hamming", 12, 15, true, false, 0, - 8, "Aaru"); - - if(compressedLength >= _writingBufferPosition) - _currentBlockHeader.compression = CompressionType.None; - - break; - } - case CompressionType.Lzma: - { - compressedLength = LZMA.EncodeBuffer(_writingBuffer, _compressedBuffer, out lzmaProperties, 9, - _dictionarySize, 4, 0, 2, 273); - - cmpCrc64Context.Update(lzmaProperties); - - if(compressedLength >= _writingBufferPosition) - _currentBlockHeader.compression = CompressionType.None; - - break; - } - default: throw new ArgumentOutOfRangeException(); - } - - if(_currentBlockHeader.compression == CompressionType.None) - { - _currentBlockHeader.cmpCrc64 = _currentBlockHeader.crc64; - _currentBlockHeader.cmpLength = (uint)_writingBufferPosition; - } + if(IsTape) + _tapeDdt = new Dictionary(); else - { - cmpCrc64Context.Update(_compressedBuffer, (uint)compressedLength); - _currentBlockHeader.cmpCrc64 = BitConverter.ToUInt64(cmpCrc64Context.Final(), 0); - _currentBlockHeader.cmpLength = (uint)compressedLength; - } + _userDataDdt = new ulong[sectors]; + } - if(_currentBlockHeader.compression == CompressionType.Lzma) - _currentBlockHeader.cmpLength += LZMA_PROPERTIES_LENGTH; + // If not, create the block, add to index, and enlarge the file to allow the DDT to exist on-disk + else + { + _outMemoryDdtPosition = _imageStream.Position; _index.Add(new IndexEntry { - blockType = BlockType.DataBlock, + blockType = BlockType.DeDuplicationTable, dataType = DataType.UserData, - offset = (ulong)_imageStream.Position + offset = (ulong)_outMemoryDdtPosition }); - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref _currentBlockHeader); + // CRC64 will be calculated later + var ddtHeader = new DdtHeader + { + identifier = BlockType.DeDuplicationTable, + type = DataType.UserData, + compression = CompressionType.None, + shift = _shift, + entries = sectors, + cmpLength = sectors * sizeof(ulong), + length = sectors * sizeof(ulong) + }; + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref ddtHeader); _imageStream.Write(_structureBytes, 0, _structureBytes.Length); _structureBytes = null; - if(_currentBlockHeader.compression == CompressionType.Lzma) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - if(_currentBlockHeader.compression == CompressionType.None) - _imageStream.Write(_writingBuffer, 0, _writingBufferPosition); - else - _imageStream.Write(_compressedBuffer, 0, compressedLength); - - _writingBufferPosition = 0; - GC.Collect(GC.MaxGeneration, GCCollectionMode.Optimized, false); - _currentBlockOffset = 0; + _imageStream.Position += (long)(sectors * sizeof(ulong)) - 1; + _imageStream.WriteByte(0); } - // No block set - if(_writingBufferPosition == 0) + if(doMd5) + _md5Provider = new Md5Context(); + + if(doSha1) + _sha1Provider = new Sha1Context(); + + if(doSha256) + _sha256Provider = new Sha256Context(); + + if(doSpamsum) + _spamsumProvider = new SpamSumContext(); + } + + AaruConsole.DebugWriteLine("Aaru Format plugin", "In memory DDT?: {0}", _inMemoryDdt); + + _imageStream.Seek(0, SeekOrigin.End); + + IsWriting = true; + ErrorMessage = null; + + return true; + } + + /// + public bool WriteMediaTag(byte[] data, MediaTagType tag) + { + if(!IsWriting) + { + ErrorMessage = "Tried to write on a non-writable image"; + + return false; + } + + if(_mediaTags.ContainsKey(tag)) + _mediaTags.Remove(tag); + + _mediaTags.Add(tag, data); + + ErrorMessage = ""; + + return true; + } + + /// + public bool WriteSector(byte[] data, ulong sectorAddress) + { + if(!IsWriting) + { + ErrorMessage = "Tried to write on a non-writable image"; + + return false; + } + + if(sectorAddress >= Info.Sectors && + !IsTape) + { + ErrorMessage = "Tried to write past image size"; + + return false; + } + + if((_imageInfo.XmlMediaType != XmlMediaType.OpticalDisc || !_writingLong) && + !_rewinded) + { + if(sectorAddress <= _lastWrittenBlock && _alreadyWrittenZero) { - _currentBlockHeader = new BlockHeader + _rewinded = true; + _md5Provider = null; + _sha1Provider = null; + _sha256Provider = null; + _spamsumProvider = null; + } + + _md5Provider?.Update(data); + _sha1Provider?.Update(data); + _sha256Provider?.Update(data); + _spamsumProvider?.Update(data); + _lastWrittenBlock = sectorAddress; + } + + if(sectorAddress == 0) + _alreadyWrittenZero = true; + + byte[] hash = null; + _writtenSectors++; + + // Compute hash only if asked to deduplicate, or the sector is empty (those will always be deduplicated) + if(_deduplicate || ArrayHelpers.ArrayIsNullOrEmpty(data)) + hash = _checksumProvider.ComputeHash(data); + + string hashString = null; + + if(hash != null) + { + var hashSb = new StringBuilder(); + + foreach(byte h in hash) + hashSb.Append(h.ToString("x2")); + + hashString = hashSb.ToString(); + + if(_deduplicationTable.TryGetValue(hashString, out ulong pointer)) + { + SetDdtEntry(sectorAddress, pointer); + ErrorMessage = ""; + + return true; + } + } + + var trk = new Track(); + + // If optical disc check track + if(_imageInfo.XmlMediaType == XmlMediaType.OpticalDisc) + { + trk = Tracks.FirstOrDefault(t => sectorAddress >= t.StartSector && sectorAddress <= t.EndSector) ?? + new Track(); + + if(trk.Sequence == 0 && + trk.StartSector == 0 && + trk.EndSector == 0) + trk.Type = TrackType.Data; // TODO: Check intersession data type + } + + // Close current block first + if(_writingBuffer != null && + + // When sector siz changes + (_currentBlockHeader.sectorSize != data.Length || + + // When block if filled + _currentBlockOffset == 1 << _shift || + + // When we change to/from CompactDisc audio + _currentBlockHeader.compression == CompressionType.Flac && trk.Type != TrackType.Audio)) + { + _currentBlockHeader.length = _currentBlockOffset * _currentBlockHeader.sectorSize; + _currentBlockHeader.crc64 = BitConverter.ToUInt64(_crc64.Final(), 0); + + var cmpCrc64Context = new Crc64Context(); + + byte[] lzmaProperties = Array.Empty(); + int compressedLength; + + switch(_currentBlockHeader.compression) + { + case CompressionType.Flac: { - identifier = BlockType.DataBlock, - type = DataType.UserData, - compression = _compress ? _compressionAlgorithm : CompressionType.None, - sectorSize = (uint)data.Length - }; + uint currentSamples = _currentBlockOffset * SAMPLES_PER_SECTOR; + uint flacBlockSize = _currentBlockOffset * SAMPLES_PER_SECTOR; - if(_imageInfo.XmlMediaType == XmlMediaType.OpticalDisc && - trk.Type == TrackType.Audio && - _compress) - _currentBlockHeader.compression = CompressionType.Flac; + if(flacBlockSize > MAX_FLAKE_BLOCK) + flacBlockSize = MAX_FLAKE_BLOCK; - // JaguarCD stores data in audio tracks. FLAC is too inefficient, use LZMA there. - // VideoNow stores video in audio tracks, and LZMA works better too. - if(((_imageInfo.MediaType == MediaType.JaguarCD && trk.Session > 1) || - _imageInfo.MediaType == MediaType.VideoNow || _imageInfo.MediaType == MediaType.VideoNowColor || - _imageInfo.MediaType == MediaType.VideoNowXp) && - trk.Type == TrackType.Audio && - _compress && - _currentBlockHeader.compression == CompressionType.Flac) - _currentBlockHeader.compression = CompressionType.Lzma; + if(flacBlockSize < MIN_FLAKE_BLOCK) + flacBlockSize = MIN_FLAKE_BLOCK; - int maxBufferSize = ((1 << _shift) * data.Length) + (MAX_FLAKE_BLOCK * 4); + long remaining = currentSamples % flacBlockSize; - if(_writingBuffer == null || - _writingBuffer.Length < maxBufferSize) + // Fill FLAC block + if(remaining != 0) + for(var r = 0; r < remaining * 4; r++) + _writingBuffer[_writingBufferPosition + r] = 0; + + compressedLength = FLAC.EncodeBuffer(_writingBuffer, _compressedBuffer, flacBlockSize, true, false, + "hamming", 12, 15, true, false, 0, 8, "Aaru"); + + if(compressedLength >= _writingBufferPosition) + _currentBlockHeader.compression = CompressionType.None; + + break; + } + case CompressionType.Lzma: { - _writingBuffer = new byte[maxBufferSize]; - _compressedBuffer = new byte[maxBufferSize * 2]; + compressedLength = LZMA.EncodeBuffer(_writingBuffer, _compressedBuffer, out lzmaProperties, 9, + _dictionarySize, 4, 0, 2, 273); + + cmpCrc64Context.Update(lzmaProperties); + + if(compressedLength >= _writingBufferPosition) + _currentBlockHeader.compression = CompressionType.None; + + break; + } + default: throw new ArgumentOutOfRangeException(); + } + + if(_currentBlockHeader.compression == CompressionType.None) + { + _currentBlockHeader.cmpCrc64 = _currentBlockHeader.crc64; + _currentBlockHeader.cmpLength = (uint)_writingBufferPosition; + } + else + { + cmpCrc64Context.Update(_compressedBuffer, (uint)compressedLength); + _currentBlockHeader.cmpCrc64 = BitConverter.ToUInt64(cmpCrc64Context.Final(), 0); + _currentBlockHeader.cmpLength = (uint)compressedLength; + } + + if(_currentBlockHeader.compression == CompressionType.Lzma) + _currentBlockHeader.cmpLength += LZMA_PROPERTIES_LENGTH; + + _index.Add(new IndexEntry + { + blockType = BlockType.DataBlock, + dataType = DataType.UserData, + offset = (ulong)_imageStream.Position + }); + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref _currentBlockHeader); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + _structureBytes = null; + + if(_currentBlockHeader.compression == CompressionType.Lzma) + _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); + + if(_currentBlockHeader.compression == CompressionType.None) + _imageStream.Write(_writingBuffer, 0, _writingBufferPosition); + else + _imageStream.Write(_compressedBuffer, 0, compressedLength); + + _writingBufferPosition = 0; + GC.Collect(GC.MaxGeneration, GCCollectionMode.Optimized, false); + _currentBlockOffset = 0; + } + + // No block set + if(_writingBufferPosition == 0) + { + _currentBlockHeader = new BlockHeader + { + identifier = BlockType.DataBlock, + type = DataType.UserData, + compression = _compress ? _compressionAlgorithm : CompressionType.None, + sectorSize = (uint)data.Length + }; + + if(_imageInfo.XmlMediaType == XmlMediaType.OpticalDisc && + trk.Type == TrackType.Audio && + _compress) + _currentBlockHeader.compression = CompressionType.Flac; + + // JaguarCD stores data in audio tracks. FLAC is too inefficient, use LZMA there. + // VideoNow stores video in audio tracks, and LZMA works better too. + if((_imageInfo.MediaType == MediaType.JaguarCD && trk.Session > 1 || + _imageInfo.MediaType is MediaType.VideoNow or MediaType.VideoNowColor or MediaType.VideoNowXp) && + trk.Type == TrackType.Audio && + _compress && + _currentBlockHeader.compression == CompressionType.Flac) + _currentBlockHeader.compression = CompressionType.Lzma; + + int maxBufferSize = (1 << _shift) * data.Length + MAX_FLAKE_BLOCK * 4; + + if(_writingBuffer == null || + _writingBuffer.Length < maxBufferSize) + { + _writingBuffer = new byte[maxBufferSize]; + _compressedBuffer = new byte[maxBufferSize * 2]; + } + + _writingBufferPosition = 0; + _crc64 = new Crc64Context(); + } + + var ddtEntry = (ulong)((_imageStream.Position << _shift) + _currentBlockOffset); + + if(hash != null) + _deduplicationTable.Add(hashString, ddtEntry); + + Array.Copy(data, 0, _writingBuffer, _writingBufferPosition, data.Length); + _writingBufferPosition += data.Length; + + SetDdtEntry(sectorAddress, ddtEntry); + _crc64.Update(data); + _currentBlockOffset++; + + ErrorMessage = ""; + + return true; + } + + /// + public bool WriteSectors(byte[] data, ulong sectorAddress, uint length) + { + if(!IsWriting) + { + ErrorMessage = "Tried to write on a non-writable image"; + + return false; + } + + if(sectorAddress + length > Info.Sectors) + { + ErrorMessage = "Tried to write past image size"; + + return false; + } + + var sectorSize = (uint)(data.Length / length); + + for(uint i = 0; i < length; i++) + { + var tmp = new byte[sectorSize]; + Array.Copy(data, i * sectorSize, tmp, 0, sectorSize); + + if(!WriteSector(tmp, sectorAddress + i)) + return false; + } + + ErrorMessage = ""; + + return true; + } + + /// + public bool WriteSectorLong(byte[] data, ulong sectorAddress) + { + if(!IsWriting) + { + ErrorMessage = "Tried to write on a non-writable image"; + + return false; + } + + byte[] sector; + + switch(_imageInfo.XmlMediaType) + { + case XmlMediaType.OpticalDisc: + Track track = + Tracks.FirstOrDefault(trk => sectorAddress >= trk.StartSector && sectorAddress <= trk.EndSector); + + if(track is null) + { + ErrorMessage = "Track not found"; + + return false; } - _writingBufferPosition = 0; - _crc64 = new Crc64Context(); - } + if(track.Sequence == 0 && + track.StartSector == 0 && + track.EndSector == 0) + track.Type = TrackType.Data; - ulong ddtEntry = (ulong)((_imageStream.Position << _shift) + _currentBlockOffset); + if(data.Length != 2352) + { + ErrorMessage = "Incorrect data size"; - if(hash != null) - _deduplicationTable.Add(hashString, ddtEntry); - - Array.Copy(data, 0, _writingBuffer, _writingBufferPosition, data.Length); - _writingBufferPosition += data.Length; - - SetDdtEntry(sectorAddress, ddtEntry); - _crc64.Update(data); - _currentBlockOffset++; - - ErrorMessage = ""; - - return true; - } - - /// - public bool WriteSectors(byte[] data, ulong sectorAddress, uint length) - { - if(!IsWriting) - { - ErrorMessage = "Tried to write on a non-writable image"; - - return false; - } - - if(sectorAddress + length > Info.Sectors) - { - ErrorMessage = "Tried to write past image size"; - - return false; - } - - uint sectorSize = (uint)(data.Length / length); - - for(uint i = 0; i < length; i++) - { - byte[] tmp = new byte[sectorSize]; - Array.Copy(data, i * sectorSize, tmp, 0, sectorSize); - - if(!WriteSector(tmp, sectorAddress + i)) return false; - } + } - ErrorMessage = ""; + _writingLong = true; - return true; - } - - /// - public bool WriteSectorLong(byte[] data, ulong sectorAddress) - { - if(!IsWriting) - { - ErrorMessage = "Tried to write on a non-writable image"; - - return false; - } - - byte[] sector; - - switch(_imageInfo.XmlMediaType) - { - case XmlMediaType.OpticalDisc: - Track track = - Tracks.FirstOrDefault(trk => sectorAddress >= trk.StartSector && - sectorAddress <= trk.EndSector); - - if(track is null) + if(!_rewinded) + { + if(sectorAddress <= _lastWrittenBlock && _alreadyWrittenZero) { - ErrorMessage = "Track not found"; - - return false; + _rewinded = true; + _md5Provider = null; + _sha1Provider = null; + _sha256Provider = null; + _spamsumProvider = null; } - if(track.Sequence == 0 && - track.StartSector == 0 && - track.EndSector == 0) - track.Type = TrackType.Data; + _md5Provider?.Update(data); + _sha1Provider?.Update(data); + _sha256Provider?.Update(data); + _spamsumProvider?.Update(data); + _lastWrittenBlock = sectorAddress; + } - if(data.Length != 2352) - { - ErrorMessage = "Incorrect data size"; + bool prefixCorrect; + int minute; + int second; + int frame; + int storedLba; - return false; - } - - _writingLong = true; - - if(!_rewinded) - { - if(sectorAddress <= _lastWrittenBlock && _alreadyWrittenZero) + // Split raw cd sector data in prefix (sync, header), user data and suffix (edc, ecc p, ecc q) + switch(track.Type) + { + case TrackType.Audio: + case TrackType.Data: return WriteSector(data, sectorAddress); + case TrackType.CdMode1: + if(_sectorPrefix != null && + _sectorSuffix != null) { - _rewinded = true; - _md5Provider = null; - _sha1Provider = null; - _sha256Provider = null; - _spamsumProvider = null; + sector = new byte[2048]; + Array.Copy(data, 0, _sectorPrefix, (int)sectorAddress * 16, 16); + Array.Copy(data, 16, sector, 0, 2048); + Array.Copy(data, 2064, _sectorSuffix, (int)sectorAddress * 288, 288); + + return WriteSector(sector, sectorAddress); } - _md5Provider?.Update(data); - _sha1Provider?.Update(data); - _sha256Provider?.Update(data); - _spamsumProvider?.Update(data); - _lastWrittenBlock = sectorAddress; - } + _sectorSuffixMs ??= new MemoryStream(); - bool prefixCorrect; - int minute; - int second; - int frame; - int storedLba; + _sectorPrefixMs ??= new MemoryStream(); - // Split raw cd sector data in prefix (sync, header), user data and suffix (edc, ecc p, ecc q) - switch(track.Type) - { - case TrackType.Audio: - case TrackType.Data: return WriteSector(data, sectorAddress); - case TrackType.CdMode1: - if(_sectorPrefix != null && - _sectorSuffix != null) - { - sector = new byte[2048]; - Array.Copy(data, 0, _sectorPrefix, (int)sectorAddress * 16, 16); - Array.Copy(data, 16, sector, 0, 2048); - Array.Copy(data, 2064, _sectorSuffix, (int)sectorAddress * 288, 288); + if(_sectorSuffixDdt == null) + { + _sectorSuffixDdt = new uint[_imageInfo.Sectors]; + EccInit(); + } - return WriteSector(sector, sectorAddress); - } + _sectorPrefixDdt ??= new uint[_imageInfo.Sectors]; - _sectorSuffixMs ??= new MemoryStream(); + sector = new byte[2048]; - _sectorPrefixMs ??= new MemoryStream(); + if(ArrayHelpers.ArrayIsNullOrEmpty(data)) + { + _sectorPrefixDdt[sectorAddress] = (uint)CdFixFlags.NotDumped; + _sectorSuffixDdt[sectorAddress] = (uint)CdFixFlags.NotDumped; - if(_sectorSuffixDdt == null) - { - _sectorSuffixDdt = new uint[_imageInfo.Sectors]; - EccInit(); - } + return WriteSector(sector, sectorAddress); + } - _sectorPrefixDdt ??= new uint[_imageInfo.Sectors]; + prefixCorrect = true; - sector = new byte[2048]; + if(data[0x00] != 0x00 || + data[0x01] != 0xFF || + data[0x02] != 0xFF || + data[0x03] != 0xFF || + data[0x04] != 0xFF || + data[0x05] != 0xFF || + data[0x06] != 0xFF || + data[0x07] != 0xFF || + data[0x08] != 0xFF || + data[0x09] != 0xFF || + data[0x0A] != 0xFF || + data[0x0B] != 0x00 || + data[0x0F] != 0x01) + prefixCorrect = false; - if(ArrayHelpers.ArrayIsNullOrEmpty(data)) - { - _sectorPrefixDdt[sectorAddress] = (uint)CdFixFlags.NotDumped; - _sectorSuffixDdt[sectorAddress] = (uint)CdFixFlags.NotDumped; + if(prefixCorrect) + { + minute = (data[0x0C] >> 4) * 10 + (data[0x0C] & 0x0F); + second = (data[0x0D] >> 4) * 10 + (data[0x0D] & 0x0F); + frame = (data[0x0E] >> 4) * 10 + (data[0x0E] & 0x0F); + storedLba = minute * 60 * 75 + second * 75 + frame - 150; + prefixCorrect = storedLba == (int)sectorAddress; + } - return WriteSector(sector, sectorAddress); - } - - prefixCorrect = true; - - if(data[0x00] != 0x00 || - data[0x01] != 0xFF || - data[0x02] != 0xFF || - data[0x03] != 0xFF || - data[0x04] != 0xFF || - data[0x05] != 0xFF || - data[0x06] != 0xFF || - data[0x07] != 0xFF || - data[0x08] != 0xFF || - data[0x09] != 0xFF || - data[0x0A] != 0xFF || - data[0x0B] != 0x00 || - data[0x0F] != 0x01) - prefixCorrect = false; - - if(prefixCorrect) - { - minute = ((data[0x0C] >> 4) * 10) + (data[0x0C] & 0x0F); - second = ((data[0x0D] >> 4) * 10) + (data[0x0D] & 0x0F); - frame = ((data[0x0E] >> 4) * 10) + (data[0x0E] & 0x0F); - storedLba = (minute * 60 * 75) + (second * 75) + frame - 150; - prefixCorrect = storedLba == (int)sectorAddress; - } - - if(prefixCorrect) - _sectorPrefixDdt[sectorAddress] = (uint)CdFixFlags.Correct; + if(prefixCorrect) + _sectorPrefixDdt[sectorAddress] = (uint)CdFixFlags.Correct; + else + { + if((_sectorPrefixDdt[sectorAddress] & CD_DFIX_MASK) > 0) + _sectorPrefixMs.Position = ((_sectorPrefixDdt[sectorAddress] & CD_DFIX_MASK) - 1) * 16; else - { - if((_sectorPrefixDdt[sectorAddress] & CD_DFIX_MASK) > 0) - _sectorPrefixMs.Position = - ((_sectorPrefixDdt[sectorAddress] & CD_DFIX_MASK) - 1) * 16; - else - _sectorPrefixMs.Seek(0, SeekOrigin.End); + _sectorPrefixMs.Seek(0, SeekOrigin.End); - _sectorPrefixDdt[sectorAddress] = (uint)((_sectorPrefixMs.Position / 16) + 1); - _sectorPrefixMs.Write(data, 0, 16); - } + _sectorPrefixDdt[sectorAddress] = (uint)(_sectorPrefixMs.Position / 16 + 1); + _sectorPrefixMs.Write(data, 0, 16); + } - bool correct = SuffixIsCorrect(data); + bool correct = SuffixIsCorrect(data); - if(correct) - _sectorSuffixDdt[sectorAddress] = (uint)CdFixFlags.Correct; + if(correct) + _sectorSuffixDdt[sectorAddress] = (uint)CdFixFlags.Correct; + else + { + if((_sectorSuffixDdt[sectorAddress] & CD_DFIX_MASK) > 0) + _sectorSuffixMs.Position = ((_sectorSuffixDdt[sectorAddress] & CD_DFIX_MASK) - 1) * 288; + else + _sectorSuffixMs.Seek(0, SeekOrigin.End); + + _sectorSuffixDdt[sectorAddress] = (uint)(_sectorSuffixMs.Position / 288 + 1); + + _sectorSuffixMs.Write(data, 2064, 288); + } + + Array.Copy(data, 16, sector, 0, 2048); + + return WriteSector(sector, sectorAddress); + case TrackType.CdMode2Formless: + case TrackType.CdMode2Form1: + case TrackType.CdMode2Form2: + if(_sectorPrefix != null && + _sectorSuffix != null) + { + sector = new byte[2336]; + Array.Copy(data, 0, _sectorPrefix, (int)sectorAddress * 16, 16); + Array.Copy(data, 16, sector, 0, 2336); + + return WriteSector(sector, sectorAddress); + } + + _sectorSuffixMs ??= new MemoryStream(); + + _sectorPrefixMs ??= new MemoryStream(); + + if(_sectorSuffixDdt == null) + { + _sectorSuffixDdt = new uint[_imageInfo.Sectors]; + EccInit(); + } + + _sectorPrefixDdt ??= new uint[_imageInfo.Sectors]; + + sector = new byte[2328]; + + if(ArrayHelpers.ArrayIsNullOrEmpty(data)) + { + _sectorPrefixDdt[sectorAddress] = (uint)CdFixFlags.NotDumped; + + return WriteSector(sector, sectorAddress); + } + + prefixCorrect = true; + + if(data[0x00] != 0x00 || + data[0x01] != 0xFF || + data[0x02] != 0xFF || + data[0x03] != 0xFF || + data[0x04] != 0xFF || + data[0x05] != 0xFF || + data[0x06] != 0xFF || + data[0x07] != 0xFF || + data[0x08] != 0xFF || + data[0x09] != 0xFF || + data[0x0A] != 0xFF || + data[0x0B] != 0x00 || + data[0x0F] != 0x02) + prefixCorrect = false; + + if(prefixCorrect) + { + minute = (data[0x0C] >> 4) * 10 + (data[0x0C] & 0x0F); + second = (data[0x0D] >> 4) * 10 + (data[0x0D] & 0x0F); + frame = (data[0x0E] >> 4) * 10 + (data[0x0E] & 0x0F); + storedLba = minute * 60 * 75 + second * 75 + frame - 150; + prefixCorrect = storedLba == (int)sectorAddress; + } + + if(prefixCorrect) + _sectorPrefixDdt[sectorAddress] = (uint)CdFixFlags.Correct; + else + { + if((_sectorPrefixDdt[sectorAddress] & CD_DFIX_MASK) > 0) + _sectorPrefixMs.Position = ((_sectorPrefixDdt[sectorAddress] & CD_DFIX_MASK) - 1) * 16; + else + _sectorPrefixMs.Seek(0, SeekOrigin.End); + + _sectorPrefixDdt[sectorAddress] = (uint)(_sectorPrefixMs.Position / 16 + 1); + + _sectorPrefixMs.Write(data, 0, 16); + } + + _mode2Subheaders ??= new byte[_imageInfo.Sectors * 8]; + + bool form2 = (data[18] & 0x20) == 0x20 || (data[22] & 0x20) == 0x20; + + if(form2) + { + uint computedEdc = ComputeEdc(0, data, 0x91C, 0x10); + var edc = BitConverter.ToUInt32(data, 0x92C); + bool correctEdc = computedEdc == edc; + + sector = new byte[2324]; + + _sectorSuffixDdt ??= new uint[_imageInfo.Sectors]; + + Array.Copy(data, 24, sector, 0, 2324); + + if(correctEdc) + _sectorSuffixDdt[sectorAddress] = (uint)CdFixFlags.Mode2Form2Ok; + else if(BitConverter.ToUInt32(data, 0x92C) == 0) + _sectorSuffixDdt[sectorAddress] = (uint)CdFixFlags.Mode2Form2NoCrc; else { if((_sectorSuffixDdt[sectorAddress] & CD_DFIX_MASK) > 0) @@ -2086,2768 +2181,2626 @@ namespace Aaru.DiscImages else _sectorSuffixMs.Seek(0, SeekOrigin.End); - _sectorSuffixDdt[sectorAddress] = (uint)((_sectorSuffixMs.Position / 288) + 1); + _sectorSuffixDdt[sectorAddress] = (uint)(_sectorSuffixMs.Position / 288 + 1); - _sectorSuffixMs.Write(data, 2064, 288); + _sectorSuffixMs.Write(data, 2348, 4); } + } + else + { + bool correctEcc = SuffixIsCorrectMode2(data); - Array.Copy(data, 16, sector, 0, 2048); + uint computedEdc = ComputeEdc(0, data, 0x808, 0x10); + var edc = BitConverter.ToUInt32(data, 0x818); + bool correctEdc = computedEdc == edc; - return WriteSector(sector, sectorAddress); - case TrackType.CdMode2Formless: - case TrackType.CdMode2Form1: - case TrackType.CdMode2Form2: - if(_sectorPrefix != null && - _sectorSuffix != null) + sector = new byte[2048]; + Array.Copy(data, 24, sector, 0, 2048); + + if(correctEcc && correctEdc) { - sector = new byte[2336]; - Array.Copy(data, 0, _sectorPrefix, (int)sectorAddress * 16, 16); - Array.Copy(data, 16, sector, 0, 2336); - - return WriteSector(sector, sectorAddress); - } - - _sectorSuffixMs ??= new MemoryStream(); - - _sectorPrefixMs ??= new MemoryStream(); - - if(_sectorSuffixDdt == null) - { - _sectorSuffixDdt = new uint[_imageInfo.Sectors]; - EccInit(); - } - - _sectorPrefixDdt ??= new uint[_imageInfo.Sectors]; - - sector = new byte[2328]; - - if(ArrayHelpers.ArrayIsNullOrEmpty(data)) - { - _sectorPrefixDdt[sectorAddress] = (uint)CdFixFlags.NotDumped; - - return WriteSector(sector, sectorAddress); - } - - prefixCorrect = true; - - if(data[0x00] != 0x00 || - data[0x01] != 0xFF || - data[0x02] != 0xFF || - data[0x03] != 0xFF || - data[0x04] != 0xFF || - data[0x05] != 0xFF || - data[0x06] != 0xFF || - data[0x07] != 0xFF || - data[0x08] != 0xFF || - data[0x09] != 0xFF || - data[0x0A] != 0xFF || - data[0x0B] != 0x00 || - data[0x0F] != 0x02) - prefixCorrect = false; - - if(prefixCorrect) - { - minute = ((data[0x0C] >> 4) * 10) + (data[0x0C] & 0x0F); - second = ((data[0x0D] >> 4) * 10) + (data[0x0D] & 0x0F); - frame = ((data[0x0E] >> 4) * 10) + (data[0x0E] & 0x0F); - storedLba = (minute * 60 * 75) + (second * 75) + frame - 150; - prefixCorrect = storedLba == (int)sectorAddress; - } - - if(prefixCorrect) - _sectorPrefixDdt[sectorAddress] = (uint)CdFixFlags.Correct; - else - { - if((_sectorPrefixDdt[sectorAddress] & CD_DFIX_MASK) > 0) - _sectorPrefixMs.Position = - ((_sectorPrefixDdt[sectorAddress] & CD_DFIX_MASK) - 1) * 16; - else - _sectorPrefixMs.Seek(0, SeekOrigin.End); - - _sectorPrefixDdt[sectorAddress] = (uint)((_sectorPrefixMs.Position / 16) + 1); - - _sectorPrefixMs.Write(data, 0, 16); - } - - _mode2Subheaders ??= new byte[_imageInfo.Sectors * 8]; - - bool form2 = (data[18] & 0x20) == 0x20 || (data[22] & 0x20) == 0x20; - - if(form2) - { - uint computedEdc = ComputeEdc(0, data, 0x91C, 0x10); - uint edc = BitConverter.ToUInt32(data, 0x92C); - bool correctEdc = computedEdc == edc; - - sector = new byte[2324]; - _sectorSuffixDdt ??= new uint[_imageInfo.Sectors]; - Array.Copy(data, 24, sector, 0, 2324); - - if(correctEdc) - { - _sectorSuffixDdt[sectorAddress] = (uint)CdFixFlags.Mode2Form2Ok; - } - else if(BitConverter.ToUInt32(data, 0x92C) == 0) - { - _sectorSuffixDdt[sectorAddress] = (uint)CdFixFlags.Mode2Form2NoCrc; - } - else - { - if((_sectorSuffixDdt[sectorAddress] & CD_DFIX_MASK) > 0) - _sectorSuffixMs.Position = - ((_sectorSuffixDdt[sectorAddress] & CD_DFIX_MASK) - 1) * 288; - else - _sectorSuffixMs.Seek(0, SeekOrigin.End); - - _sectorSuffixDdt[sectorAddress] = (uint)((_sectorSuffixMs.Position / 288) + 1); - - _sectorSuffixMs.Write(data, 2348, 4); - } + _sectorSuffixDdt[sectorAddress] = (uint)CdFixFlags.Mode2Form1Ok; } else { - bool correctEcc = SuffixIsCorrectMode2(data); - - uint computedEdc = ComputeEdc(0, data, 0x808, 0x10); - uint edc = BitConverter.ToUInt32(data, 0x818); - bool correctEdc = computedEdc == edc; - - sector = new byte[2048]; - Array.Copy(data, 24, sector, 0, 2048); - - if(correctEcc && correctEdc) - { - _sectorSuffixDdt ??= new uint[_imageInfo.Sectors]; - - _sectorSuffixDdt[sectorAddress] = (uint)CdFixFlags.Mode2Form1Ok; - } + if((_sectorSuffixDdt[sectorAddress] & CD_DFIX_MASK) > 0) + _sectorSuffixMs.Position = + ((_sectorSuffixDdt[sectorAddress] & CD_DFIX_MASK) - 1) * 288; else - { - if((_sectorSuffixDdt[sectorAddress] & CD_DFIX_MASK) > 0) - _sectorSuffixMs.Position = - ((_sectorSuffixDdt[sectorAddress] & CD_DFIX_MASK) - 1) * 288; - else - _sectorSuffixMs.Seek(0, SeekOrigin.End); + _sectorSuffixMs.Seek(0, SeekOrigin.End); - _sectorSuffixDdt[sectorAddress] = (uint)((_sectorSuffixMs.Position / 288) + 1); + _sectorSuffixDdt[sectorAddress] = (uint)(_sectorSuffixMs.Position / 288 + 1); - _sectorSuffixMs.Write(data, 2072, 280); - } + _sectorSuffixMs.Write(data, 2072, 280); } + } - Array.Copy(data, 16, _mode2Subheaders, (int)sectorAddress * 8, 8); + Array.Copy(data, 16, _mode2Subheaders, (int)sectorAddress * 8, 8); - return WriteSector(sector, sectorAddress); - } + return WriteSector(sector, sectorAddress); + } - break; - case XmlMediaType.BlockMedia: - switch(_imageInfo.MediaType) - { - // Split user data from Apple tags - case MediaType.AppleFileWare: - case MediaType.AppleProfile: - case MediaType.AppleSonyDS: - case MediaType.AppleSonySS: - case MediaType.AppleWidget: - case MediaType.PriamDataTower: - byte[] oldTag; - byte[] newTag; + break; + case XmlMediaType.BlockMedia: + switch(_imageInfo.MediaType) + { + // Split user data from Apple tags + case MediaType.AppleFileWare: + case MediaType.AppleProfile: + case MediaType.AppleSonyDS: + case MediaType.AppleSonySS: + case MediaType.AppleWidget: + case MediaType.PriamDataTower: + byte[] oldTag; + byte[] newTag; - switch(data.Length - 512) - { - // Sony tag, convert to Profile - case 12 when _imageInfo.MediaType == MediaType.AppleProfile || - _imageInfo.MediaType == MediaType.AppleFileWare: - oldTag = new byte[12]; - Array.Copy(data, 512, oldTag, 0, 12); - newTag = LisaTag.DecodeSonyTag(oldTag)?.ToProfile().GetBytes(); + switch(data.Length - 512) + { + // Sony tag, convert to Profile + case 12 when _imageInfo.MediaType is MediaType.AppleProfile or MediaType.AppleFileWare: + oldTag = new byte[12]; + Array.Copy(data, 512, oldTag, 0, 12); + newTag = LisaTag.DecodeSonyTag(oldTag)?.ToProfile().GetBytes(); - break; + break; - // Sony tag, convert to Priam - case 12 when _imageInfo.MediaType == MediaType.PriamDataTower: - oldTag = new byte[12]; - Array.Copy(data, 512, oldTag, 0, 12); - newTag = LisaTag.DecodeSonyTag(oldTag)?.ToPriam().GetBytes(); + // Sony tag, convert to Priam + case 12 when _imageInfo.MediaType == MediaType.PriamDataTower: + oldTag = new byte[12]; + Array.Copy(data, 512, oldTag, 0, 12); + newTag = LisaTag.DecodeSonyTag(oldTag)?.ToPriam().GetBytes(); - break; + break; - // Sony tag, copy to Sony - case 12 when _imageInfo.MediaType == MediaType.AppleSonySS || - _imageInfo.MediaType == MediaType.AppleSonySS: - newTag = new byte[12]; - Array.Copy(data, 512, newTag, 0, 12); + // Sony tag, copy to Sony + case 12 when _imageInfo.MediaType is MediaType.AppleSonySS or MediaType.AppleSonySS: + newTag = new byte[12]; + Array.Copy(data, 512, newTag, 0, 12); - break; + break; - // Profile tag, copy to Profile - case 20 when _imageInfo.MediaType == MediaType.AppleProfile || - _imageInfo.MediaType == MediaType.AppleFileWare: - newTag = new byte[20]; - Array.Copy(data, 512, newTag, 0, 20); + // Profile tag, copy to Profile + case 20 when _imageInfo.MediaType is MediaType.AppleProfile or MediaType.AppleFileWare: + newTag = new byte[20]; + Array.Copy(data, 512, newTag, 0, 20); - break; + break; - // Profile tag, convert to Priam - case 20 when _imageInfo.MediaType == MediaType.PriamDataTower: - oldTag = new byte[20]; - Array.Copy(data, 512, oldTag, 0, 20); - newTag = LisaTag.DecodeProfileTag(oldTag)?.ToPriam().GetBytes(); + // Profile tag, convert to Priam + case 20 when _imageInfo.MediaType == MediaType.PriamDataTower: + oldTag = new byte[20]; + Array.Copy(data, 512, oldTag, 0, 20); + newTag = LisaTag.DecodeProfileTag(oldTag)?.ToPriam().GetBytes(); - break; + break; - // Profile tag, convert to Sony - case 20 when _imageInfo.MediaType == MediaType.AppleSonySS || - _imageInfo.MediaType == MediaType.AppleSonySS: - oldTag = new byte[20]; - Array.Copy(data, 512, oldTag, 0, 20); - newTag = LisaTag.DecodeProfileTag(oldTag)?.ToSony().GetBytes(); + // Profile tag, convert to Sony + case 20 when _imageInfo.MediaType is MediaType.AppleSonySS or MediaType.AppleSonySS: + oldTag = new byte[20]; + Array.Copy(data, 512, oldTag, 0, 20); + newTag = LisaTag.DecodeProfileTag(oldTag)?.ToSony().GetBytes(); - break; + break; - // Priam tag, convert to Profile - case 24 when _imageInfo.MediaType == MediaType.AppleProfile || - _imageInfo.MediaType == MediaType.AppleFileWare: - oldTag = new byte[24]; - Array.Copy(data, 512, oldTag, 0, 24); - newTag = LisaTag.DecodePriamTag(oldTag)?.ToProfile().GetBytes(); + // Priam tag, convert to Profile + case 24 when _imageInfo.MediaType is MediaType.AppleProfile or MediaType.AppleFileWare: + oldTag = new byte[24]; + Array.Copy(data, 512, oldTag, 0, 24); + newTag = LisaTag.DecodePriamTag(oldTag)?.ToProfile().GetBytes(); - break; + break; - // Priam tag, copy to Priam - case 12 when _imageInfo.MediaType == MediaType.PriamDataTower: - newTag = new byte[24]; - Array.Copy(data, 512, newTag, 0, 24); + // Priam tag, copy to Priam + case 12 when _imageInfo.MediaType == MediaType.PriamDataTower: + newTag = new byte[24]; + Array.Copy(data, 512, newTag, 0, 24); - break; + break; - // Priam tag, convert to Sony - case 24 when _imageInfo.MediaType == MediaType.AppleSonySS || - _imageInfo.MediaType == MediaType.AppleSonySS: - oldTag = new byte[24]; - Array.Copy(data, 512, oldTag, 0, 24); - newTag = LisaTag.DecodePriamTag(oldTag)?.ToSony().GetBytes(); + // Priam tag, convert to Sony + case 24 when _imageInfo.MediaType is MediaType.AppleSonySS or MediaType.AppleSonySS: + oldTag = new byte[24]; + Array.Copy(data, 512, oldTag, 0, 24); + newTag = LisaTag.DecodePriamTag(oldTag)?.ToSony().GetBytes(); - break; - case 0: - newTag = null; + break; + case 0: + newTag = null; - break; - default: - ErrorMessage = "Incorrect data size"; - - return false; - } - - sector = new byte[512]; - Array.Copy(data, 0, sector, 0, 512); - - if(newTag == null) - return WriteSector(sector, sectorAddress); - - _sectorSubchannel ??= new byte[newTag.Length * (int)_imageInfo.Sectors]; - - Array.Copy(newTag, 0, _sectorSubchannel, newTag.Length * (int)sectorAddress, newTag.Length); - - return WriteSector(sector, sectorAddress); - } - - break; - } - - ErrorMessage = "Unknown long sector type, cannot write."; - - return false; - } - - /// - public bool WriteSectorsLong(byte[] data, ulong sectorAddress, uint length) - { - byte[] sector; - - switch(_imageInfo.XmlMediaType) - { - case XmlMediaType.OpticalDisc: - if(data.Length % 2352 != 0) - { - ErrorMessage = "Incorrect data size"; - - return false; - } - - sector = new byte[2352]; - - for(uint i = 0; i < length; i++) - { - Array.Copy(data, 2352 * i, sector, 0, 2352); - - if(!WriteSectorLong(sector, sectorAddress + i)) - return false; - } - - ErrorMessage = ""; - - return true; - case XmlMediaType.BlockMedia: - switch(_imageInfo.MediaType) - { - case MediaType.AppleFileWare: - case MediaType.AppleProfile: - case MediaType.AppleSonyDS: - case MediaType.AppleSonySS: - case MediaType.AppleWidget: - case MediaType.PriamDataTower: - int sectorSize = 0; - - if(data.Length % 524 == 0) - sectorSize = 524; - else if(data.Length % 532 == 0) - sectorSize = 532; - else if(data.Length % 536 == 0) - sectorSize = 536; - - if(sectorSize == 0) - { + break; + default: ErrorMessage = "Incorrect data size"; return false; - } + } - sector = new byte[sectorSize]; + sector = new byte[512]; + Array.Copy(data, 0, sector, 0, 512); - for(uint i = 0; i < length; i++) - { - Array.Copy(data, sectorSize * i, sector, 0, sectorSize); + if(newTag == null) + return WriteSector(sector, sectorAddress); - if(!WriteSectorLong(sector, sectorAddress + i)) - return false; - } + _sectorSubchannel ??= new byte[newTag.Length * (int)_imageInfo.Sectors]; - ErrorMessage = ""; + Array.Copy(newTag, 0, _sectorSubchannel, newTag.Length * (int)sectorAddress, newTag.Length); - return true; - } + return WriteSector(sector, sectorAddress); + } - break; - } + break; + } - ErrorMessage = "Unknown long sector type, cannot write."; + ErrorMessage = "Unknown long sector type, cannot write."; + + return false; + } + + /// + public bool WriteSectorsLong(byte[] data, ulong sectorAddress, uint length) + { + byte[] sector; + + switch(_imageInfo.XmlMediaType) + { + case XmlMediaType.OpticalDisc: + if(data.Length % 2352 != 0) + { + ErrorMessage = "Incorrect data size"; + + return false; + } + + sector = new byte[2352]; + + for(uint i = 0; i < length; i++) + { + Array.Copy(data, 2352 * i, sector, 0, 2352); + + if(!WriteSectorLong(sector, sectorAddress + i)) + return false; + } + + ErrorMessage = ""; + + return true; + case XmlMediaType.BlockMedia: + switch(_imageInfo.MediaType) + { + case MediaType.AppleFileWare: + case MediaType.AppleProfile: + case MediaType.AppleSonyDS: + case MediaType.AppleSonySS: + case MediaType.AppleWidget: + case MediaType.PriamDataTower: + var sectorSize = 0; + + if(data.Length % 524 == 0) + sectorSize = 524; + else if(data.Length % 532 == 0) + sectorSize = 532; + else if(data.Length % 536 == 0) + sectorSize = 536; + + if(sectorSize == 0) + { + ErrorMessage = "Incorrect data size"; + + return false; + } + + sector = new byte[sectorSize]; + + for(uint i = 0; i < length; i++) + { + Array.Copy(data, sectorSize * i, sector, 0, sectorSize); + + if(!WriteSectorLong(sector, sectorAddress + i)) + return false; + } + + ErrorMessage = ""; + + return true; + } + + break; + } + + ErrorMessage = "Unknown long sector type, cannot write."; + + return false; + } + + /// + public bool SetTracks(List tracks) + { + if(_imageInfo.XmlMediaType != XmlMediaType.OpticalDisc) + { + ErrorMessage = "Unsupported feature"; return false; } - /// - public bool SetTracks(List tracks) + if(!IsWriting) { - if(_imageInfo.XmlMediaType != XmlMediaType.OpticalDisc) - { - ErrorMessage = "Unsupported feature"; + ErrorMessage = "Tried to write on a non-writable image"; - return false; - } - - if(!IsWriting) - { - ErrorMessage = "Tried to write on a non-writable image"; - - return false; - } - - Tracks = tracks; - ErrorMessage = ""; - - return true; + return false; } - /// - public bool Close() + Tracks = tracks; + ErrorMessage = ""; + + return true; + } + + /// + public bool Close() + { + if(!IsWriting) { - if(!IsWriting) + ErrorMessage = "Image is not opened for writing"; + + return false; + } + + // Close current block first + if(_writingBuffer != null) + { + _currentBlockHeader.length = _currentBlockOffset * _currentBlockHeader.sectorSize; + _currentBlockHeader.crc64 = BitConverter.ToUInt64(_crc64.Final(), 0); + + var cmpCrc64Context = new Crc64Context(); + + byte[] lzmaProperties = Array.Empty(); + var compressedLength = 0; + + switch(_currentBlockHeader.compression) { - ErrorMessage = "Image is not opened for writing"; - - return false; - } - - // Close current block first - if(_writingBuffer != null) - { - _currentBlockHeader.length = _currentBlockOffset * _currentBlockHeader.sectorSize; - _currentBlockHeader.crc64 = BitConverter.ToUInt64(_crc64.Final(), 0); - - var cmpCrc64Context = new Crc64Context(); - - byte[] lzmaProperties = Array.Empty(); - int compressedLength = 0; - - switch(_currentBlockHeader.compression) + case CompressionType.Flac: { - case CompressionType.Flac: - { - uint currentSamples = _currentBlockOffset * SAMPLES_PER_SECTOR; - uint flacBlockSize = _currentBlockOffset * SAMPLES_PER_SECTOR; + uint currentSamples = _currentBlockOffset * SAMPLES_PER_SECTOR; + uint flacBlockSize = _currentBlockOffset * SAMPLES_PER_SECTOR; - if(flacBlockSize > MAX_FLAKE_BLOCK) - flacBlockSize = MAX_FLAKE_BLOCK; + if(flacBlockSize > MAX_FLAKE_BLOCK) + flacBlockSize = MAX_FLAKE_BLOCK; - if(flacBlockSize < MIN_FLAKE_BLOCK) - flacBlockSize = MIN_FLAKE_BLOCK; + if(flacBlockSize < MIN_FLAKE_BLOCK) + flacBlockSize = MIN_FLAKE_BLOCK; - long remaining = currentSamples % flacBlockSize; + long remaining = currentSamples % flacBlockSize; - // Fill FLAC block - if(remaining != 0) - for(int r = 0; r < remaining * 4; r++) - _writingBuffer[_writingBufferPosition + r] = 0; + // Fill FLAC block + if(remaining != 0) + for(var r = 0; r < remaining * 4; r++) + _writingBuffer[_writingBufferPosition + r] = 0; - compressedLength = FLAC.EncodeBuffer(_writingBuffer, _compressedBuffer, flacBlockSize, true, - false, "hamming", 12, 15, true, false, 0, - 8, "Aaru"); + compressedLength = FLAC.EncodeBuffer(_writingBuffer, _compressedBuffer, flacBlockSize, true, false, + "hamming", 12, 15, true, false, 0, 8, "Aaru"); - if(compressedLength >= _writingBufferPosition) - _currentBlockHeader.compression = CompressionType.None; + if(compressedLength >= _writingBufferPosition) + _currentBlockHeader.compression = CompressionType.None; - break; - } - case CompressionType.Lzma: - { - compressedLength = LZMA.EncodeBuffer(_writingBuffer, _compressedBuffer, out lzmaProperties, 9, - _dictionarySize, 4, 0, 2, 273); - - cmpCrc64Context.Update(lzmaProperties); - - if(compressedLength >= _writingBufferPosition) - _currentBlockHeader.compression = CompressionType.None; - - break; - } - default: throw new ArgumentOutOfRangeException(); + break; } - - if(_currentBlockHeader.compression == CompressionType.None) + case CompressionType.Lzma: { - _currentBlockHeader.cmpCrc64 = _currentBlockHeader.crc64; - _currentBlockHeader.cmpLength = (uint)_writingBufferPosition; - } - else - { - cmpCrc64Context.Update(_compressedBuffer, (uint)compressedLength); - _currentBlockHeader.cmpCrc64 = BitConverter.ToUInt64(cmpCrc64Context.Final(), 0); - _currentBlockHeader.cmpLength = (uint)compressedLength; - } + compressedLength = LZMA.EncodeBuffer(_writingBuffer, _compressedBuffer, out lzmaProperties, 9, + _dictionarySize, 4, 0, 2, 273); - if(_currentBlockHeader.compression == CompressionType.Lzma) - _currentBlockHeader.cmpLength += LZMA_PROPERTIES_LENGTH; - - _index.Add(new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = DataType.UserData, - offset = (ulong)_imageStream.Position - }); - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref _currentBlockHeader); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _structureBytes = null; - - if(_currentBlockHeader.compression == CompressionType.Lzma) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - if(_currentBlockHeader.compression == CompressionType.None) - _imageStream.Write(_writingBuffer, 0, _writingBufferPosition); - else - _imageStream.Write(_compressedBuffer, 0, compressedLength); - - _writingBuffer = null; - } - - if(_deduplicate) - AaruConsole.DebugWriteLine("Aaru Format plugin", "Of {0} sectors written, {1} are unique ({2:P})", - _writtenSectors, _deduplicationTable.Count, - (double)_deduplicationTable.Count / _writtenSectors); - - IndexEntry idxEntry; - - // TODO: Reuse buffer - MemoryStream blockStream; - - // Write media tag blocks - foreach(KeyValuePair mediaTag in _mediaTags) - { - DataType dataType = GetDataTypeForMediaTag(mediaTag.Key); - - if(mediaTag.Value is null) - { - AaruConsole.ErrorWriteLine("Tag type {0} is null, skipping...", dataType); - - continue; - } - - idxEntry = new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = dataType, - offset = (ulong)_imageStream.Position - }; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing tag type {0} to position {1}", mediaTag.Key, - idxEntry.offset); - - Crc64Context.Data(mediaTag.Value, out byte[] tagCrc); - - var tagBlock = new BlockHeader - { - identifier = BlockType.DataBlock, - type = dataType, - length = (uint)mediaTag.Value.Length, - crc64 = BitConverter.ToUInt64(tagCrc, 0) - }; - - byte[] cmpBuffer = new byte[mediaTag.Value.Length + 262144]; - - int cmpLen; - byte[] lzmaProperties = null; - bool doNotCompress = false; - - switch(_compressionAlgorithm) - { - case CompressionType.Lzma: - cmpLen = LZMA.EncodeBuffer(mediaTag.Value, cmpBuffer, out lzmaProperties, 9, _dictionarySize, 4, - 0, 2, 273); - - if(cmpLen + LZMA_PROPERTIES_LENGTH > mediaTag.Value.Length) - doNotCompress = true; - - break; - case CompressionType.None: - doNotCompress = true; - - break; - default: throw new ArgumentOutOfRangeException(); - } - - byte[] tagData; - - // Not compressible - if(doNotCompress) - { - tagBlock.cmpLength = tagBlock.length; - tagBlock.cmpCrc64 = tagBlock.crc64; - tagData = mediaTag.Value; - tagBlock.compression = CompressionType.None; - } - else - { - tagData = cmpBuffer; - var crc64Ctx = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) - crc64Ctx.Update(lzmaProperties); - - crc64Ctx.Update(tagData); - tagCrc = crc64Ctx.Final(); - tagBlock.cmpLength = (uint)tagData.Length; - tagBlock.cmpCrc64 = BitConverter.ToUInt64(tagCrc, 0); - tagBlock.compression = _compressionAlgorithm; - - if(_compressionAlgorithm == CompressionType.Lzma) - tagBlock.cmpLength += LZMA_PROPERTIES_LENGTH; - } - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref tagBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - if(tagBlock.compression == CompressionType.Lzma) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(tagData, 0, tagData.Length); - - _index.RemoveAll(t => t.blockType == BlockType.DataBlock && t.dataType == dataType); - - _index.Add(idxEntry); - } - - // If we have set the geometry block, write it - if(_geometryBlock.identifier == BlockType.GeometryBlock) - { - idxEntry = new IndexEntry - { - blockType = BlockType.GeometryBlock, - dataType = DataType.NoData, - offset = (ulong)_imageStream.Position - }; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing geometry block to position {0}", - idxEntry.offset); - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref _geometryBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - _index.RemoveAll(t => t.blockType == BlockType.GeometryBlock && t.dataType == DataType.NoData); - - _index.Add(idxEntry); - } - - // If we have dump hardware, write it - if(DumpHardware != null) - { - var dumpMs = new MemoryStream(); - - foreach(DumpHardwareType dump in DumpHardware) - { - byte[] dumpManufacturer = null; - byte[] dumpModel = null; - byte[] dumpRevision = null; - byte[] dumpFirmware = null; - byte[] dumpSerial = null; - byte[] dumpSoftwareName = null; - byte[] dumpSoftwareVersion = null; - byte[] dumpSoftwareOperatingSystem = null; - - if(!string.IsNullOrWhiteSpace(dump.Manufacturer)) - dumpManufacturer = Encoding.UTF8.GetBytes(dump.Manufacturer); - - if(!string.IsNullOrWhiteSpace(dump.Model)) - dumpModel = Encoding.UTF8.GetBytes(dump.Model); - - if(!string.IsNullOrWhiteSpace(dump.Revision)) - dumpRevision = Encoding.UTF8.GetBytes(dump.Revision); - - if(!string.IsNullOrWhiteSpace(dump.Firmware)) - dumpFirmware = Encoding.UTF8.GetBytes(dump.Firmware); - - if(!string.IsNullOrWhiteSpace(dump.Serial)) - dumpSerial = Encoding.UTF8.GetBytes(dump.Serial); - - if(!string.IsNullOrWhiteSpace(dump.Software?.Name)) - dumpSoftwareName = Encoding.UTF8.GetBytes(dump.Software.Name); - - if(!string.IsNullOrWhiteSpace(dump.Software?.Version)) - dumpSoftwareVersion = Encoding.UTF8.GetBytes(dump.Software.Version); - - if(!string.IsNullOrWhiteSpace(dump.Software?.OperatingSystem)) - dumpSoftwareOperatingSystem = Encoding.UTF8.GetBytes(dump.Software.OperatingSystem); - - var dumpEntry = new DumpHardwareEntry - { - manufacturerLength = (uint)(dumpManufacturer?.Length + 1 ?? 0), - modelLength = (uint)(dumpModel?.Length + 1 ?? 0), - revisionLength = (uint)(dumpRevision?.Length + 1 ?? 0), - firmwareLength = (uint)(dumpFirmware?.Length + 1 ?? 0), - serialLength = (uint)(dumpSerial?.Length + 1 ?? 0), - softwareNameLength = (uint)(dumpSoftwareName?.Length + 1 ?? 0), - softwareVersionLength = (uint)(dumpSoftwareVersion?.Length + 1 ?? 0), - softwareOperatingSystemLength = (uint)(dumpSoftwareOperatingSystem?.Length + 1 ?? 0), - extents = (uint)dump.Extents.Length - }; - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref dumpEntry); - dumpMs.Write(_structureBytes, 0, _structureBytes.Length); - - if(dumpManufacturer != null) - { - dumpMs.Write(dumpManufacturer, 0, dumpManufacturer.Length); - dumpMs.WriteByte(0); - } - - if(dumpModel != null) - { - dumpMs.Write(dumpModel, 0, dumpModel.Length); - dumpMs.WriteByte(0); - } - - if(dumpRevision != null) - { - dumpMs.Write(dumpRevision, 0, dumpRevision.Length); - dumpMs.WriteByte(0); - } - - if(dumpFirmware != null) - { - dumpMs.Write(dumpFirmware, 0, dumpFirmware.Length); - dumpMs.WriteByte(0); - } - - if(dumpSerial != null) - { - dumpMs.Write(dumpSerial, 0, dumpSerial.Length); - dumpMs.WriteByte(0); - } - - if(dumpSoftwareName != null) - { - dumpMs.Write(dumpSoftwareName, 0, dumpSoftwareName.Length); - dumpMs.WriteByte(0); - } - - if(dumpSoftwareVersion != null) - { - dumpMs.Write(dumpSoftwareVersion, 0, dumpSoftwareVersion.Length); - dumpMs.WriteByte(0); - } - - if(dumpSoftwareOperatingSystem != null) - { - dumpMs.Write(dumpSoftwareOperatingSystem, 0, dumpSoftwareOperatingSystem.Length); - dumpMs.WriteByte(0); - } - - foreach(ExtentType extent in dump.Extents) - { - dumpMs.Write(BitConverter.GetBytes(extent.Start), 0, sizeof(ulong)); - dumpMs.Write(BitConverter.GetBytes(extent.End), 0, sizeof(ulong)); - } - } - - idxEntry = new IndexEntry - { - blockType = BlockType.DumpHardwareBlock, - dataType = DataType.NoData, - offset = (ulong)_imageStream.Position - }; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing dump hardware block to position {0}", - idxEntry.offset); - - Crc64Context.Data(dumpMs.ToArray(), out byte[] dumpCrc); - - var dumpBlock = new DumpHardwareHeader - { - identifier = BlockType.DumpHardwareBlock, - entries = (ushort)DumpHardware.Count, - crc64 = BitConverter.ToUInt64(dumpCrc, 0), - length = (uint)dumpMs.Length - }; - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref dumpBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _imageStream.Write(dumpMs.ToArray(), 0, (int)dumpMs.Length); - - _index.RemoveAll(t => t.blockType == BlockType.DumpHardwareBlock && t.dataType == DataType.NoData); - - _index.Add(idxEntry); - } - - // If we have CICM XML metadata, write it - if(CicmMetadata != null) - { - var cicmMs = new MemoryStream(); - var xmlSer = new XmlSerializer(typeof(CICMMetadataType)); - xmlSer.Serialize(cicmMs, CicmMetadata); - - idxEntry = new IndexEntry - { - blockType = BlockType.CicmBlock, - dataType = DataType.NoData, - offset = (ulong)_imageStream.Position - }; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing CICM XML block to position {0}", - idxEntry.offset); - - var cicmBlock = new CicmMetadataBlock - { - identifier = BlockType.CicmBlock, - length = (uint)cicmMs.Length - }; - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref cicmBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _imageStream.Write(cicmMs.ToArray(), 0, (int)cicmMs.Length); - - _index.RemoveAll(t => t.blockType == BlockType.CicmBlock && t.dataType == DataType.NoData); - - _index.Add(idxEntry); - } - - // If we have checksums, write it to disk - if(_md5Provider != null || - _sha1Provider != null || - _sha256Provider != null || - _spamsumProvider != null) - { - var chkMs = new MemoryStream(); - - var chkHeader = new ChecksumHeader - { - identifier = BlockType.ChecksumBlock - }; - - if(_md5Provider != null) - { - byte[] md5 = _md5Provider.Final(); - - var md5Entry = new ChecksumEntry - { - type = ChecksumAlgorithm.Md5, - length = (uint)md5.Length - }; - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref md5Entry); - chkMs.Write(_structureBytes, 0, _structureBytes.Length); - chkMs.Write(md5, 0, md5.Length); - chkHeader.entries++; - } - - if(_sha1Provider != null) - { - byte[] sha1 = _sha1Provider.Final(); - - var sha1Entry = new ChecksumEntry - { - type = ChecksumAlgorithm.Sha1, - length = (uint)sha1.Length - }; - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref sha1Entry); - chkMs.Write(_structureBytes, 0, _structureBytes.Length); - chkMs.Write(sha1, 0, sha1.Length); - chkHeader.entries++; - } - - if(_sha256Provider != null) - { - byte[] sha256 = _sha256Provider.Final(); - - var sha256Entry = new ChecksumEntry - { - type = ChecksumAlgorithm.Sha256, - length = (uint)sha256.Length - }; - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref sha256Entry); - chkMs.Write(_structureBytes, 0, _structureBytes.Length); - chkMs.Write(sha256, 0, sha256.Length); - chkHeader.entries++; - } - - if(_spamsumProvider != null) - { - byte[] spamsum = Encoding.ASCII.GetBytes(_spamsumProvider.End()); - - var spamsumEntry = new ChecksumEntry - { - type = ChecksumAlgorithm.SpamSum, - length = (uint)spamsum.Length - }; - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref spamsumEntry); - chkMs.Write(_structureBytes, 0, _structureBytes.Length); - chkMs.Write(spamsum, 0, spamsum.Length); - chkHeader.entries++; - } - - if(chkHeader.entries > 0) - { - chkHeader.length = (uint)chkMs.Length; - - idxEntry = new IndexEntry - { - blockType = BlockType.ChecksumBlock, - dataType = DataType.NoData, - offset = (ulong)_imageStream.Position - }; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing checksum block to position {0}", - idxEntry.offset); - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref chkHeader); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _imageStream.Write(chkMs.ToArray(), 0, (int)chkMs.Length); - - _index.RemoveAll(t => t.blockType == BlockType.ChecksumBlock && t.dataType == DataType.NoData); - - _index.Add(idxEntry); - } - } - - if(IsTape) - { - ulong latestBlock = _tapeDdt.Max(b => b.Key); - - _userDataDdt = new ulong[latestBlock + 1]; - - foreach(KeyValuePair block in _tapeDdt) - _userDataDdt[block.Key] = block.Value; - - _inMemoryDdt = true; - _tapeDdt.Clear(); - - idxEntry = new IndexEntry - { - blockType = BlockType.TapePartitionBlock, - dataType = DataType.UserData, - offset = (ulong)_imageStream.Position - }; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing tape partitions to position {0}", - idxEntry.offset); - - TapePartitionEntry[] tapePartitionEntries = new TapePartitionEntry[TapePartitions.Count]; - - for(int t = 0; t < TapePartitions.Count; t++) - { - tapePartitionEntries[t] = new TapePartitionEntry - { - Number = TapePartitions[t].Number, - FirstBlock = TapePartitions[t].FirstBlock, - LastBlock = TapePartitions[t].LastBlock - }; - } - - byte[] tapePartitionEntriesData = - MemoryMarshal.Cast(tapePartitionEntries).ToArray(); - - var tapePartitionHeader = new TapePartitionHeader - { - identifier = BlockType.TapePartitionBlock, - entries = (byte)tapePartitionEntries.Length, - length = (ulong)tapePartitionEntriesData.Length - }; - - _crc64 = new Crc64Context(); - _crc64.Update(tapePartitionEntriesData); - tapePartitionHeader.crc64 = BitConverter.ToUInt64(_crc64.Final(), 0); - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref tapePartitionHeader); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _structureBytes = null; - _imageStream.Write(tapePartitionEntriesData, 0, tapePartitionEntriesData.Length); - - _index.RemoveAll(t => t.blockType == BlockType.TapePartitionBlock && t.dataType == DataType.UserData); - _index.Add(idxEntry); - - idxEntry = new IndexEntry - { - blockType = BlockType.TapeFileBlock, - dataType = DataType.UserData, - offset = (ulong)_imageStream.Position - }; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing tape files to position {0}", idxEntry.offset); - - TapeFileEntry[] tapeFileEntries = new TapeFileEntry[Files.Count]; - - for(int t = 0; t < Files.Count; t++) - tapeFileEntries[t] = new TapeFileEntry - { - File = Files[t].File, - FirstBlock = Files[t].FirstBlock, - LastBlock = Files[t].LastBlock - }; - - byte[] tapeFileEntriesData = MemoryMarshal.Cast(tapeFileEntries).ToArray(); - - var tapeFileHeader = new TapeFileHeader - { - identifier = BlockType.TapeFileBlock, - entries = (uint)tapeFileEntries.Length, - length = (ulong)tapeFileEntriesData.Length - }; - - _crc64 = new Crc64Context(); - _crc64.Update(tapeFileEntriesData); - tapeFileHeader.crc64 = BitConverter.ToUInt64(_crc64.Final(), 0); - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref tapeFileHeader); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _structureBytes = null; - _imageStream.Write(tapeFileEntriesData, 0, tapeFileEntriesData.Length); - - _index.RemoveAll(t => t.blockType == BlockType.TapeFileBlock && t.dataType == DataType.UserData); - _index.Add(idxEntry); - } - - // If the DDT is in-memory, write it to disk - if(_inMemoryDdt) - { - idxEntry = new IndexEntry - { - blockType = BlockType.DeDuplicationTable, - dataType = DataType.UserData, - offset = (ulong)_imageStream.Position - }; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing user data DDT to position {0}", - idxEntry.offset); - - var ddtHeader = new DdtHeader - { - identifier = BlockType.DeDuplicationTable, - type = DataType.UserData, - - compression = _compressionAlgorithm, - shift = _shift, - entries = (ulong)_userDataDdt.LongLength, - length = (ulong)(_userDataDdt.LongLength * sizeof(ulong)) - }; - - _crc64 = new Crc64Context(); - byte[] ddtEntries = MemoryMarshal.Cast(_userDataDdt).ToArray(); - _crc64.Update(ddtEntries); - - byte[] cmpBuffer = new byte[ddtEntries.Length + 262144]; - - int cmpLen; - byte[] lzmaProperties = null; - - switch(_compressionAlgorithm) - { - case CompressionType.None: - cmpBuffer = ddtEntries; - cmpLen = cmpBuffer.Length; - - break; - case CompressionType.Lzma: - cmpLen = LZMA.EncodeBuffer(ddtEntries, cmpBuffer, out lzmaProperties, 9, _dictionarySize, 4, 0, - 2, 273); - - break; - default: throw new ArgumentOutOfRangeException(); - } - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - ddtHeader.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma && - cmpBuffer != ddtEntries) - ddtHeader.cmpLength += LZMA_PROPERTIES_LENGTH; - - var cmpCrc64Context = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma && - cmpBuffer != ddtEntries) cmpCrc64Context.Update(lzmaProperties); - cmpCrc64Context.Update(blockStream.ToArray()); - ddtHeader.cmpCrc64 = BitConverter.ToUInt64(cmpCrc64Context.Final(), 0); - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref ddtHeader); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _structureBytes = null; - - if(_compressionAlgorithm == CompressionType.Lzma) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - blockStream.Close(); - - _index.RemoveAll(t => t.blockType == BlockType.DeDuplicationTable && t.dataType == DataType.UserData); - - _index.Add(idxEntry); - } - - // Write the sector prefix, suffix and subchannels if present - switch(_imageInfo.XmlMediaType) - { - case XmlMediaType.OpticalDisc when Tracks != null && Tracks.Count > 0: - DateTime startCompress; - DateTime endCompress; - - // Old format - if(_sectorPrefix != null && - _sectorSuffix != null) - { - idxEntry = new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = DataType.CdSectorPrefix, - offset = (ulong)_imageStream.Position - }; - - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Writing CD sector prefix block to position {0}", idxEntry.offset); - - Crc64Context.Data(_sectorPrefix, out byte[] blockCrc); - - var prefixBlock = new BlockHeader - { - identifier = BlockType.DataBlock, - type = DataType.CdSectorPrefix, - length = (uint)_sectorPrefix.Length, - crc64 = BitConverter.ToUInt64(blockCrc, 0), - sectorSize = 16 - }; - - byte[] lzmaProperties = null; - - if(!_compress) - { - prefixBlock.compression = CompressionType.None; - prefixBlock.cmpCrc64 = prefixBlock.crc64; - prefixBlock.cmpLength = prefixBlock.length; - blockStream = new MemoryStream(_sectorPrefix); - } - else - { - startCompress = DateTime.Now; - - byte[] cmpBuffer = new byte[_sectorPrefix.Length + 262144]; - - int cmpLen = _compressionAlgorithm switch - { - CompressionType.Lzma => LZMA.EncodeBuffer(_sectorPrefix, cmpBuffer, out lzmaProperties, - 9, _dictionarySize, 4, 0, 2, 273), - _ => throw new ArgumentOutOfRangeException() - }; - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - var cmpCrc = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) - cmpCrc.Update(lzmaProperties); - - cmpCrc.Update(blockStream.ToArray()); - blockCrc = cmpCrc.Final(); - prefixBlock.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) - prefixBlock.cmpLength += LZMA_PROPERTIES_LENGTH; - - prefixBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); - prefixBlock.compression = _compressionAlgorithm; - - endCompress = DateTime.Now; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Took {0} seconds to compress prefix", - (endCompress - startCompress).TotalSeconds); - } - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref prefixBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - if(prefixBlock.compression == CompressionType.Lzma) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - blockStream.Close(); - - _index.RemoveAll(t => t.blockType == BlockType.DataBlock && - t.dataType == DataType.CdSectorPrefix); - - _index.Add(idxEntry); - - idxEntry = new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = DataType.CdSectorSuffix, - offset = (ulong)_imageStream.Position - }; - - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Writing CD sector suffix block to position {0}", idxEntry.offset); - - Crc64Context.Data(_sectorSuffix, out blockCrc); - - prefixBlock = new BlockHeader - { - identifier = BlockType.DataBlock, - type = DataType.CdSectorSuffix, - length = (uint)_sectorSuffix.Length, - crc64 = BitConverter.ToUInt64(blockCrc, 0), - sectorSize = 288 - }; - - if(!_compress) - { - prefixBlock.compression = CompressionType.None; - prefixBlock.cmpCrc64 = prefixBlock.crc64; - prefixBlock.cmpLength = prefixBlock.length; - blockStream = new MemoryStream(_sectorSuffix); - } - else - { - startCompress = DateTime.Now; - - byte[] cmpBuffer = new byte[_sectorSuffix.Length + 262144]; - - int cmpLen = _compressionAlgorithm switch - { - CompressionType.Lzma => LZMA.EncodeBuffer(_sectorSuffix, cmpBuffer, out lzmaProperties, - 9, _dictionarySize, 4, 0, 2, 273), - _ => throw new ArgumentOutOfRangeException() - }; - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - var cmpCrc = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) - cmpCrc.Update(lzmaProperties); - - cmpCrc.Update(blockStream.ToArray()); - blockCrc = cmpCrc.Final(); - prefixBlock.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) - prefixBlock.cmpLength += LZMA_PROPERTIES_LENGTH; - - prefixBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); - prefixBlock.compression = CompressionType.Lzma; - - endCompress = DateTime.Now; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Took {0} seconds to compress suffix", - (endCompress - startCompress).TotalSeconds); - } - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref prefixBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - if(prefixBlock.compression == CompressionType.Lzma) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - - _index.RemoveAll(t => t.blockType == BlockType.DataBlock && - t.dataType == DataType.CdSectorSuffix); - - _index.Add(idxEntry); - blockStream.Close(); - } - else if(_sectorSuffixMs != null && - _sectorSuffixDdt != null && - _sectorPrefixMs != null && - _sectorPrefixDdt != null) - { - #if DEBUG - uint notDumpedPrefixes = 0; - uint correctPrefixes = 0; - uint writtenPrefixes = 0; - uint notDumpedSuffixes = 0; - uint correctSuffixes = 0; - uint writtenSuffixes = 0; - uint correctMode2Form1 = 0; - uint correctMode2Form2 = 0; - uint emptyMode2Form1 = 0; - - for(long i = 0; i < _sectorPrefixDdt.LongLength; i++) - if((_sectorPrefixDdt[i] & CD_XFIX_MASK) == (uint)CdFixFlags.NotDumped) - notDumpedPrefixes++; - else if((_sectorPrefixDdt[i] & CD_XFIX_MASK) == (uint)CdFixFlags.Correct) - correctPrefixes++; - else if((_sectorPrefixDdt[i] & CD_DFIX_MASK) > 0) - writtenPrefixes++; - - for(long i = 0; i < _sectorPrefixDdt.LongLength; i++) - if((_sectorSuffixDdt[i] & CD_XFIX_MASK) == (uint)CdFixFlags.NotDumped) - notDumpedSuffixes++; - else if((_sectorSuffixDdt[i] & CD_XFIX_MASK) == (uint)CdFixFlags.Correct) - correctSuffixes++; - else if((_sectorSuffixDdt[i] & CD_XFIX_MASK) == (uint)CdFixFlags.Mode2Form1Ok) - correctMode2Form1++; - else if((_sectorSuffixDdt[i] & CD_XFIX_MASK) == (uint)CdFixFlags.Mode2Form2Ok) - correctMode2Form2++; - else if((_sectorSuffixDdt[i] & CD_XFIX_MASK) == (uint)CdFixFlags.Mode2Form2NoCrc) - emptyMode2Form1++; - else if((_sectorSuffixDdt[i] & CD_DFIX_MASK) > 0) - writtenSuffixes++; - - AaruConsole.DebugWriteLine("Aaru Format plugin", - "{0} ({1:P}% prefixes are correct, {2} ({3:P}%) prefixes have not been dumped, {4} ({5:P}%) prefixes have been written to image", - correctPrefixes, correctPrefixes / _imageInfo.Sectors, - notDumpedPrefixes, notDumpedPrefixes / _imageInfo.Sectors, - writtenPrefixes, writtenPrefixes / _imageInfo.Sectors); - - AaruConsole.DebugWriteLine("Aaru Format plugin", - "{0} ({1:P}% suffixes are correct, {2} ({3:P}%) suffixes have not been dumped, {4} ({5:P}%) suffixes have been written to image", - correctSuffixes, correctSuffixes / _imageInfo.Sectors, - notDumpedSuffixes, notDumpedSuffixes / _imageInfo.Sectors, - writtenSuffixes, writtenSuffixes / _imageInfo.Sectors); - - AaruConsole.DebugWriteLine("Aaru Format plugin", - "{0} ({1:P}% MODE 2 Form 1 are correct, {2} ({3:P}%) MODE 2 Form 2 are correct, {4} ({5:P}%) MODE 2 Form 2 have empty CRC", - correctMode2Form1, correctMode2Form1 / _imageInfo.Sectors, - correctMode2Form2, correctMode2Form2 / _imageInfo.Sectors, - emptyMode2Form1, emptyMode2Form1 / _imageInfo.Sectors); - #endif - - idxEntry = new IndexEntry - { - blockType = BlockType.DeDuplicationTable, - dataType = DataType.CdSectorPrefixCorrected, - offset = (ulong)_imageStream.Position - }; - - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Writing CompactDisc sector prefix DDT to position {0}", - idxEntry.offset); - - var ddtHeader = new DdtHeader - { - identifier = BlockType.DeDuplicationTable, - type = DataType.CdSectorPrefixCorrected, - compression = _compressionAlgorithm, - entries = (ulong)_sectorPrefixDdt.LongLength, - length = (ulong)(_sectorPrefixDdt.LongLength * sizeof(uint)) - }; - - _crc64 = new Crc64Context(); - byte[] ddtEntries = MemoryMarshal.Cast(_sectorPrefixDdt).ToArray(); - _crc64.Update(ddtEntries); - - byte[] cmpBuffer = new byte[ddtEntries.Length + 262144]; - - int cmpLen; - byte[] lzmaProperties; - - cmpLen = _compressionAlgorithm switch - { - CompressionType.Lzma => LZMA.EncodeBuffer(ddtEntries, cmpBuffer, out lzmaProperties, 9, - _dictionarySize, 4, 0, 2, 273), - _ => throw new ArgumentOutOfRangeException() - }; - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - ddtHeader.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) - ddtHeader.cmpLength += LZMA_PROPERTIES_LENGTH; - - var cmpCrc64Context = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) - cmpCrc64Context.Update(lzmaProperties); - - cmpCrc64Context.Update(blockStream.ToArray()); - ddtHeader.cmpCrc64 = BitConverter.ToUInt64(cmpCrc64Context.Final(), 0); - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref ddtHeader); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _structureBytes = null; - - if(_compressionAlgorithm == CompressionType.Lzma) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - blockStream.Close(); - - _index.RemoveAll(t => t.blockType == BlockType.DeDuplicationTable && - t.dataType == DataType.CdSectorPrefixCorrected); - - _index.Add(idxEntry); - - idxEntry = new IndexEntry - { - blockType = BlockType.DeDuplicationTable, - dataType = DataType.CdSectorSuffixCorrected, - offset = (ulong)_imageStream.Position - }; - - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Writing CompactDisc sector suffix DDT to position {0}", - idxEntry.offset); - - ddtHeader = new DdtHeader - { - identifier = BlockType.DeDuplicationTable, - type = DataType.CdSectorSuffixCorrected, - compression = _compressionAlgorithm, - entries = (ulong)_sectorSuffixDdt.LongLength, - length = (ulong)(_sectorSuffixDdt.LongLength * sizeof(uint)) - }; - - _crc64 = new Crc64Context(); - ddtEntries = MemoryMarshal.Cast(_sectorSuffixDdt).ToArray(); - _crc64.Update(ddtEntries); - - cmpBuffer = new byte[ddtEntries.Length + 262144]; - - cmpLen = _compressionAlgorithm switch - { - CompressionType.Lzma => LZMA.EncodeBuffer(ddtEntries, cmpBuffer, out lzmaProperties, 9, - _dictionarySize, 4, 0, 2, 273), - _ => throw new ArgumentOutOfRangeException() - }; - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - ddtHeader.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) - ddtHeader.cmpLength += LZMA_PROPERTIES_LENGTH; - - cmpCrc64Context = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) - cmpCrc64Context.Update(lzmaProperties); - - cmpCrc64Context.Update(blockStream.ToArray()); - ddtHeader.cmpCrc64 = BitConverter.ToUInt64(cmpCrc64Context.Final(), 0); - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref ddtHeader); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _structureBytes = null; - - if(_compressionAlgorithm == CompressionType.Lzma) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - blockStream.Close(); - - _index.RemoveAll(t => t.blockType == BlockType.DeDuplicationTable && - t.dataType == DataType.CdSectorSuffixCorrected); - - _index.Add(idxEntry); - - idxEntry = new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = DataType.CdSectorPrefixCorrected, - offset = (ulong)_imageStream.Position - }; - - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Writing CD sector corrected prefix block to position {0}", - idxEntry.offset); - - Crc64Context.Data(_sectorPrefixMs.GetBuffer(), (uint)_sectorPrefixMs.Length, - out byte[] blockCrc); - - var prefixBlock = new BlockHeader - { - identifier = BlockType.DataBlock, - type = DataType.CdSectorPrefixCorrected, - length = (uint)_sectorPrefixMs.Length, - crc64 = BitConverter.ToUInt64(blockCrc, 0), - sectorSize = 16 - }; - - lzmaProperties = null; - - if(!_compress) - { - prefixBlock.compression = CompressionType.None; - prefixBlock.cmpCrc64 = prefixBlock.crc64; - prefixBlock.cmpLength = prefixBlock.length; - blockStream = _sectorPrefixMs; - } - else - { - startCompress = DateTime.Now; - - byte[] sectorPrefixBuffer = _sectorPrefixMs.ToArray(); - cmpBuffer = new byte[sectorPrefixBuffer.Length + 262144]; - - cmpLen = _compressionAlgorithm switch - { - CompressionType.Lzma => LZMA.EncodeBuffer(sectorPrefixBuffer, cmpBuffer, - out lzmaProperties, 9, _dictionarySize, 4, 0, - 2, 273), - _ => throw new ArgumentOutOfRangeException() - }; - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - var cmpCrc = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) - cmpCrc.Update(lzmaProperties); - - cmpCrc.Update(blockStream.ToArray()); - blockCrc = cmpCrc.Final(); - prefixBlock.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) - prefixBlock.cmpLength += LZMA_PROPERTIES_LENGTH; - - prefixBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); - prefixBlock.compression = _compressionAlgorithm; - - endCompress = DateTime.Now; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Took {0} seconds to compress prefix", - (endCompress - startCompress).TotalSeconds); - } - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref prefixBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - if(prefixBlock.compression == CompressionType.Lzma) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - blockStream.Close(); - - _index.RemoveAll(t => t.blockType == BlockType.DataBlock && - t.dataType == DataType.CdSectorPrefixCorrected); - - _index.Add(idxEntry); - - idxEntry = new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = DataType.CdSectorSuffixCorrected, - offset = (ulong)_imageStream.Position - }; - - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Writing CD sector corrected suffix block to position {0}", - idxEntry.offset); - - Crc64Context.Data(_sectorSuffixMs.GetBuffer(), (uint)_sectorSuffixMs.Length, out blockCrc); - - var suffixBlock = new BlockHeader - { - identifier = BlockType.DataBlock, - type = DataType.CdSectorSuffixCorrected, - length = (uint)_sectorSuffixMs.Length, - crc64 = BitConverter.ToUInt64(blockCrc, 0), - sectorSize = 288 - }; - - lzmaProperties = null; - - if(!_compress) - { - suffixBlock.compression = CompressionType.None; - suffixBlock.cmpCrc64 = suffixBlock.crc64; - suffixBlock.cmpLength = suffixBlock.length; - blockStream = _sectorSuffixMs; - } - else - { - startCompress = DateTime.Now; - - byte[] sectorSuffixBuffer = _sectorPrefixMs.ToArray(); - cmpBuffer = new byte[sectorSuffixBuffer.Length + 262144]; - - cmpLen = _compressionAlgorithm switch - { - CompressionType.Lzma => LZMA.EncodeBuffer(sectorSuffixBuffer, cmpBuffer, - out lzmaProperties, 9, _dictionarySize, 4, 0, - 2, 273), - _ => throw new ArgumentOutOfRangeException() - }; - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - var cmpCrc = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) - cmpCrc.Update(lzmaProperties); - - cmpCrc.Update(blockStream.ToArray()); - blockCrc = cmpCrc.Final(); - suffixBlock.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) - suffixBlock.cmpLength += LZMA_PROPERTIES_LENGTH; - - suffixBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); - suffixBlock.compression = _compressionAlgorithm; - - endCompress = DateTime.Now; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Took {0} seconds to compress suffix", - (endCompress - startCompress).TotalSeconds); - } - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref suffixBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - if(suffixBlock.compression == CompressionType.Lzma) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - blockStream.Close(); - - _index.RemoveAll(t => t.blockType == BlockType.DataBlock && - t.dataType == DataType.CdSectorSuffixCorrected); - - _index.Add(idxEntry); - } - - if(_mode2Subheaders != null) - { - idxEntry = new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = DataType.CompactDiscMode2Subheader, - offset = (ulong)_imageStream.Position - }; - - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Writing CD MODE2 subheaders block to position {0}", - idxEntry.offset); - - Crc64Context.Data(_mode2Subheaders, out byte[] blockCrc); - - var subheaderBlock = new BlockHeader - { - identifier = BlockType.DataBlock, - type = DataType.CompactDiscMode2Subheader, - length = (uint)_mode2Subheaders.Length, - crc64 = BitConverter.ToUInt64(blockCrc, 0), - sectorSize = 8 - }; - - byte[] lzmaProperties = null; - - if(!_compress) - { - subheaderBlock.compression = CompressionType.None; - subheaderBlock.cmpCrc64 = subheaderBlock.crc64; - subheaderBlock.cmpLength = subheaderBlock.length; - blockStream = new MemoryStream(_mode2Subheaders); - } - else - { - startCompress = DateTime.Now; - - byte[] cmpBuffer = new byte[_mode2Subheaders.Length + 262144]; - - int cmpLen = _compressionAlgorithm switch - { - CompressionType.Lzma => LZMA.EncodeBuffer(_mode2Subheaders, cmpBuffer, - out lzmaProperties, 9, _dictionarySize, 4, 0, - 2, 273), - _ => throw new ArgumentOutOfRangeException() - }; - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - var cmpCrc = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) - cmpCrc.Update(lzmaProperties); - - cmpCrc.Update(blockStream.ToArray()); - blockCrc = cmpCrc.Final(); - subheaderBlock.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) - subheaderBlock.cmpLength += LZMA_PROPERTIES_LENGTH; - - subheaderBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); - subheaderBlock.compression = _compressionAlgorithm; - - endCompress = DateTime.Now; - - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Took {0} seconds to compress MODE2 subheaders", - (endCompress - startCompress).TotalSeconds); - } - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref subheaderBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - if(subheaderBlock.compression == CompressionType.Lzma) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - - _index.RemoveAll(t => t.blockType == BlockType.DataBlock && - t.dataType == DataType.CompactDiscMode2Subheader); - - _index.Add(idxEntry); - blockStream.Close(); - } - - if(_sectorSubchannel != null) - { - idxEntry = new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = DataType.CdSectorSubchannel, - offset = (ulong)_imageStream.Position - }; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing CD subchannel block to position {0}", - idxEntry.offset); - - Crc64Context.Data(_sectorSubchannel, out byte[] blockCrc); - - var subchannelBlock = new BlockHeader - { - identifier = BlockType.DataBlock, - type = DataType.CdSectorSubchannel, - length = (uint)_sectorSubchannel.Length, - crc64 = BitConverter.ToUInt64(blockCrc, 0), - sectorSize = 96 - }; - - byte[] lzmaProperties = null; - - if(!_compress) - { - subchannelBlock.compression = CompressionType.None; - subchannelBlock.cmpCrc64 = subchannelBlock.crc64; - subchannelBlock.cmpLength = subchannelBlock.length; - blockStream = new MemoryStream(_sectorSubchannel); - } - else - { - startCompress = DateTime.Now; - byte[] transformedSubchannel = ClauniaSubchannelTransform(_sectorSubchannel); - - byte[] cmpBuffer = new byte[transformedSubchannel.Length + 262144]; - - int cmpLen = _compressionAlgorithm switch - { - CompressionType.Lzma => LZMA.EncodeBuffer(transformedSubchannel, cmpBuffer, - out lzmaProperties, 9, _dictionarySize, 4, 0, - 2, 273), - _ => throw new ArgumentOutOfRangeException() - }; - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - var cmpCrc = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) - cmpCrc.Update(lzmaProperties); - - cmpCrc.Update(blockStream.ToArray()); - blockCrc = cmpCrc.Final(); - subchannelBlock.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) - subchannelBlock.cmpLength += LZMA_PROPERTIES_LENGTH; - - subchannelBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); - - if(_compressionAlgorithm == CompressionType.Lzma) - subchannelBlock.compression = CompressionType.LzmaClauniaSubchannelTransform; - else - subchannelBlock.compression = _compressionAlgorithm; - - endCompress = DateTime.Now; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Took {0} seconds to compress subchannel", - (endCompress - startCompress).TotalSeconds); - } - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref subchannelBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - if(subchannelBlock.compression == CompressionType.Lzma || - subchannelBlock.compression == CompressionType.LzmaClauniaSubchannelTransform) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - - _index.RemoveAll(t => t.blockType == BlockType.DataBlock && - t.dataType == DataType.CdSectorSubchannel); - - _index.Add(idxEntry); - blockStream.Close(); - } - - if(_sectorCpiMai != null) - { - idxEntry = new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = DataType.DvdSectorCpiMai, - offset = (ulong)_imageStream.Position - }; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing DVD CPI_MAI block to position {0}", - idxEntry.offset); - - Crc64Context.Data(_sectorCpiMai, out byte[] blockCrc); - - var cpiMaiBlock = new BlockHeader - { - identifier = BlockType.DataBlock, - type = DataType.DvdSectorCpiMai, - length = (uint)_sectorCpiMai.Length, - crc64 = BitConverter.ToUInt64(blockCrc, 0), - sectorSize = 6 - }; - - byte[] lzmaProperties = null; - - if(!_compress) - { - cpiMaiBlock.compression = CompressionType.None; - cpiMaiBlock.cmpCrc64 = cpiMaiBlock.crc64; - cpiMaiBlock.cmpLength = cpiMaiBlock.length; - blockStream = new MemoryStream(_sectorCpiMai); - } - else - { - startCompress = DateTime.Now; - - byte[] cmpBuffer = new byte[_sectorCpiMai.Length + 262144]; - - int cmpLen = _compressionAlgorithm switch - { - CompressionType.Lzma => LZMA.EncodeBuffer(_sectorCpiMai, cmpBuffer, out lzmaProperties, - 9, _dictionarySize, 4, 0, 2, 273), - _ => throw new ArgumentOutOfRangeException() - }; - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - var cmpCrc = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) - cmpCrc.Update(lzmaProperties); - - cmpCrc.Update(blockStream.ToArray()); - blockCrc = cmpCrc.Final(); - cpiMaiBlock.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) - cpiMaiBlock.cmpLength += LZMA_PROPERTIES_LENGTH; - - cpiMaiBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); - cpiMaiBlock.compression = _compressionAlgorithm; - - endCompress = DateTime.Now; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Took {0} seconds to compress CPI_MAI", - (endCompress - startCompress).TotalSeconds); - } - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref cpiMaiBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - if(cpiMaiBlock.compression == CompressionType.Lzma || - cpiMaiBlock.compression == CompressionType.LzmaClauniaSubchannelTransform) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - - _index.RemoveAll(t => t.blockType == BlockType.DataBlock && - t.dataType == DataType.DvdSectorCpiMai); - - _index.Add(idxEntry); - blockStream.Close(); - } - - if(_sectorDecryptedTitleKey != null) - { - idxEntry = new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = DataType.DvdSectorTitleKeyDecrypted, - offset = (ulong)_imageStream.Position - }; - - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Writing decrypted DVD title key block to position {0}", - idxEntry.offset); - - Crc64Context.Data(_sectorDecryptedTitleKey, out byte[] blockCrc); - - var titleKeyBlock = new BlockHeader - { - identifier = BlockType.DataBlock, - type = DataType.DvdSectorTitleKeyDecrypted, - length = (uint)_sectorDecryptedTitleKey.Length, - crc64 = BitConverter.ToUInt64(blockCrc, 0), - sectorSize = 5 - }; - - byte[] lzmaProperties = null; - - if(!_compress) - { - titleKeyBlock.compression = CompressionType.None; - titleKeyBlock.cmpCrc64 = titleKeyBlock.crc64; - titleKeyBlock.cmpLength = titleKeyBlock.length; - blockStream = new MemoryStream(_sectorDecryptedTitleKey); - } - else - { - startCompress = DateTime.Now; - - byte[] cmpBuffer = new byte[_sectorDecryptedTitleKey.Length + 262144]; - - int cmpLen = _compressionAlgorithm switch - { - CompressionType.Lzma => LZMA.EncodeBuffer(_sectorDecryptedTitleKey, cmpBuffer, - out lzmaProperties, 9, _dictionarySize, 4, 0, - 2, 273), - _ => throw new ArgumentOutOfRangeException() - }; - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - var cmpCrc = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) - cmpCrc.Update(lzmaProperties); - - cmpCrc.Update(blockStream.ToArray()); - blockCrc = cmpCrc.Final(); - titleKeyBlock.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) - titleKeyBlock.cmpLength += LZMA_PROPERTIES_LENGTH; - - titleKeyBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); - titleKeyBlock.compression = _compressionAlgorithm; - - endCompress = DateTime.Now; - - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Took {0} seconds to compress decrypted DVD title keys", - (endCompress - startCompress).TotalSeconds); - } - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref titleKeyBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - if(titleKeyBlock.compression == CompressionType.Lzma || - titleKeyBlock.compression == CompressionType.LzmaClauniaSubchannelTransform) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - - _index.RemoveAll(t => t.blockType == BlockType.DataBlock && - t.dataType == DataType.DvdSectorTitleKeyDecrypted); - - _index.Add(idxEntry); - blockStream.Close(); - } - - List trackEntries = new(); - List compactDiscIndexEntries = new(); - - foreach(Track track in Tracks) - { - _trackFlags.TryGetValue((byte)track.Sequence, out byte flags); - _trackIsrcs.TryGetValue((byte)track.Sequence, out string isrc); - - if((flags & (int)CdFlags.DataTrack) == 0 && - track.Type != TrackType.Audio) - flags += (byte)CdFlags.DataTrack; - - trackEntries.Add(new TrackEntry - { - sequence = (byte)track.Sequence, - type = track.Type, - start = (long)track.StartSector, - end = (long)track.EndSector, - pregap = (long)track.Pregap, - session = (byte)track.Session, - isrc = isrc, - flags = flags - }); - - if(!track.Indexes.ContainsKey(0) && - track.Pregap > 0) - { - track.Indexes[0] = (int)track.StartSector; - track.Indexes[1] = (int)(track.StartSector + track.Pregap); - } - else if(!track.Indexes.ContainsKey(0) && - !track.Indexes.ContainsKey(1)) - track.Indexes[0] = (int)track.StartSector; - - compactDiscIndexEntries.AddRange(track.Indexes.Select(trackIndex => new CompactDiscIndexEntry - { - Index = trackIndex.Key, - Lba = trackIndex.Value, - Track = (ushort)track.Sequence - })); - } - - // If there are tracks build the tracks block - if(trackEntries.Count > 0) - { - blockStream = new MemoryStream(); - - foreach(TrackEntry entry in trackEntries) - { - _structurePointer = - System.Runtime.InteropServices.Marshal.AllocHGlobal(Marshal.SizeOf()); - - _structureBytes = new byte[Marshal.SizeOf()]; - System.Runtime.InteropServices.Marshal.StructureToPtr(entry, _structurePointer, true); - - System.Runtime.InteropServices.Marshal.Copy(_structurePointer, _structureBytes, 0, - _structureBytes.Length); - - System.Runtime.InteropServices.Marshal.FreeHGlobal(_structurePointer); - blockStream.Write(_structureBytes, 0, _structureBytes.Length); - } - - Crc64Context.Data(blockStream.ToArray(), out byte[] trksCrc); - - var trkHeader = new TracksHeader - { - identifier = BlockType.TracksBlock, - entries = (ushort)trackEntries.Count, - crc64 = BitConverter.ToUInt64(trksCrc, 0) - }; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing tracks to position {0}", - _imageStream.Position); - - _index.RemoveAll(t => t.blockType == BlockType.TracksBlock && t.dataType == DataType.NoData); - - _index.Add(new IndexEntry - { - blockType = BlockType.TracksBlock, - dataType = DataType.NoData, - offset = (ulong)_imageStream.Position - }); - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref trkHeader); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - blockStream.Close(); - } - - // If there are track indexes bigger than 1 - if(compactDiscIndexEntries.Any(i => i.Index > 1)) - { - blockStream = new MemoryStream(); - - foreach(CompactDiscIndexEntry entry in compactDiscIndexEntries) - { - _structurePointer = - System.Runtime.InteropServices.Marshal.AllocHGlobal(Marshal. - SizeOf()); - - _structureBytes = new byte[Marshal.SizeOf()]; - System.Runtime.InteropServices.Marshal.StructureToPtr(entry, _structurePointer, true); - - System.Runtime.InteropServices.Marshal.Copy(_structurePointer, _structureBytes, 0, - _structureBytes.Length); - - System.Runtime.InteropServices.Marshal.FreeHGlobal(_structurePointer); - blockStream.Write(_structureBytes, 0, _structureBytes.Length); - } - - Crc64Context.Data(blockStream.ToArray(), out byte[] cdixCrc); - - var cdixHeader = new CompactDiscIndexesHeader - { - identifier = BlockType.CompactDiscIndexesBlock, - entries = (ushort)compactDiscIndexEntries.Count, - crc64 = BitConverter.ToUInt64(cdixCrc, 0) - }; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing compact disc indexes to position {0}", - _imageStream.Position); - - _index.RemoveAll(t => t.blockType == BlockType.CompactDiscIndexesBlock && - t.dataType == DataType.NoData); - - _index.Add(new IndexEntry - { - blockType = BlockType.CompactDiscIndexesBlock, - dataType = DataType.NoData, - offset = (ulong)_imageStream.Position - }); - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref cdixHeader); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - blockStream.Close(); - } - - break; - case XmlMediaType.BlockMedia: - if(_sectorSubchannel != null && - (_imageInfo.MediaType == MediaType.AppleFileWare || - _imageInfo.MediaType == MediaType.AppleSonySS || - _imageInfo.MediaType == MediaType.AppleSonyDS || - _imageInfo.MediaType == MediaType.AppleProfile || - _imageInfo.MediaType == MediaType.AppleWidget || - _imageInfo.MediaType == MediaType.PriamDataTower)) - { - DataType tagType = DataType.NoData; - - switch(_imageInfo.MediaType) - { - case MediaType.AppleSonySS: - case MediaType.AppleSonyDS: - tagType = DataType.AppleSonyTag; - - break; - case MediaType.AppleFileWare: - case MediaType.AppleProfile: - case MediaType.AppleWidget: - tagType = DataType.AppleProfileTag; - - break; - case MediaType.PriamDataTower: - tagType = DataType.PriamDataTowerTag; - - break; - } - - idxEntry = new IndexEntry - { - blockType = BlockType.DataBlock, - dataType = tagType, - offset = (ulong)_imageStream.Position - }; - - AaruConsole.DebugWriteLine("Aaru Format plugin", - "Writing apple sector tag block to position {0}", idxEntry.offset); - - Crc64Context.Data(_sectorSubchannel, out byte[] blockCrc); - - var subchannelBlock = new BlockHeader - { - identifier = BlockType.DataBlock, - type = tagType, - length = (uint)_sectorSubchannel.Length, - crc64 = BitConverter.ToUInt64(blockCrc, 0) - }; - - switch(_imageInfo.MediaType) - { - case MediaType.AppleSonySS: - case MediaType.AppleSonyDS: - subchannelBlock.sectorSize = 12; - - break; - case MediaType.AppleFileWare: - case MediaType.AppleProfile: - case MediaType.AppleWidget: - subchannelBlock.sectorSize = 20; - - break; - case MediaType.PriamDataTower: - subchannelBlock.sectorSize = 24; - - break; - } - - byte[] lzmaProperties = null; - - if(!_compress) - { - subchannelBlock.compression = CompressionType.None; - subchannelBlock.cmpCrc64 = subchannelBlock.crc64; - subchannelBlock.cmpLength = subchannelBlock.length; - blockStream = new MemoryStream(_sectorSubchannel); - } - else - { - byte[] cmpBuffer = new byte[_sectorSubchannel.Length + 262144]; - - int cmpLen = _compressionAlgorithm switch - { - CompressionType.Lzma => LZMA.EncodeBuffer(_sectorSubchannel, cmpBuffer, - out lzmaProperties, 9, _dictionarySize, 4, 0, - 2, 273), - _ => throw new ArgumentOutOfRangeException() - }; - - blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); - - var cmpCrc = new Crc64Context(); - - if(_compressionAlgorithm == CompressionType.Lzma) - cmpCrc.Update(lzmaProperties); - - cmpCrc.Update(blockStream.ToArray()); - blockCrc = cmpCrc.Final(); - subchannelBlock.cmpLength = (uint)blockStream.Length; - - if(_compressionAlgorithm == CompressionType.Lzma) - subchannelBlock.cmpLength += LZMA_PROPERTIES_LENGTH; - - subchannelBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); - subchannelBlock.compression = _compressionAlgorithm; - } - - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref subchannelBlock); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); - - if(subchannelBlock.compression == CompressionType.Lzma) - _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - - _index.RemoveAll(t => t.blockType == BlockType.DataBlock && t.dataType == tagType); - - _index.Add(idxEntry); - blockStream.Close(); - } + if(compressedLength >= _writingBufferPosition) + _currentBlockHeader.compression = CompressionType.None; break; + } + default: throw new ArgumentOutOfRangeException(); } - // Write metadata if present - SetMetadataFromTags(); - var metadataBlock = new MetadataBlock(); - blockStream = new MemoryStream(); - blockStream.Write(new byte[Marshal.SizeOf()], 0, Marshal.SizeOf()); - byte[] tmpUtf16Le; - - if(_imageInfo.MediaSequence > 0 && - _imageInfo.LastMediaSequence > 0) + if(_currentBlockHeader.compression == CompressionType.None) { - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.mediaSequence = _imageInfo.MediaSequence; - metadataBlock.lastMediaSequence = _imageInfo.LastMediaSequence; - } - - if(!string.IsNullOrWhiteSpace(_imageInfo.Creator)) - { - tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.Creator); - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.creatorOffset = (uint)blockStream.Position; - metadataBlock.creatorLength = (uint)(tmpUtf16Le.Length + 2); - blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - - blockStream.Write(new byte[] - { - 0, 0 - }, 0, 2); - } - - if(!string.IsNullOrWhiteSpace(_imageInfo.Comments)) - { - tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.Comments); - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.commentsOffset = (uint)blockStream.Position; - metadataBlock.commentsLength = (uint)(tmpUtf16Le.Length + 2); - blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - - blockStream.Write(new byte[] - { - 0, 0 - }, 0, 2); - } - - if(!string.IsNullOrWhiteSpace(_imageInfo.MediaTitle)) - { - tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.MediaTitle); - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.mediaTitleOffset = (uint)blockStream.Position; - metadataBlock.mediaTitleLength = (uint)(tmpUtf16Le.Length + 2); - blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - - blockStream.Write(new byte[] - { - 0, 0 - }, 0, 2); - } - - if(!string.IsNullOrWhiteSpace(_imageInfo.MediaManufacturer)) - { - tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.MediaManufacturer); - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.mediaManufacturerOffset = (uint)blockStream.Position; - metadataBlock.mediaManufacturerLength = (uint)(tmpUtf16Le.Length + 2); - blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - - blockStream.Write(new byte[] - { - 0, 0 - }, 0, 2); - } - - if(!string.IsNullOrWhiteSpace(_imageInfo.MediaModel)) - { - tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.MediaModel); - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.mediaModelOffset = (uint)blockStream.Position; - metadataBlock.mediaModelLength = (uint)(tmpUtf16Le.Length + 2); - blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - - blockStream.Write(new byte[] - { - 0, 0 - }, 0, 2); - } - - if(!string.IsNullOrWhiteSpace(_imageInfo.MediaSerialNumber)) - { - tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.MediaSerialNumber); - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.mediaSerialNumberOffset = (uint)blockStream.Position; - metadataBlock.mediaSerialNumberLength = (uint)(tmpUtf16Le.Length + 2); - blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - - blockStream.Write(new byte[] - { - 0, 0 - }, 0, 2); - } - - if(!string.IsNullOrWhiteSpace(_imageInfo.MediaBarcode)) - { - tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.MediaBarcode); - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.mediaBarcodeOffset = (uint)blockStream.Position; - metadataBlock.mediaBarcodeLength = (uint)(tmpUtf16Le.Length + 2); - blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - - blockStream.Write(new byte[] - { - 0, 0 - }, 0, 2); - } - - if(!string.IsNullOrWhiteSpace(_imageInfo.MediaPartNumber)) - { - tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.MediaPartNumber); - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.mediaPartNumberOffset = (uint)blockStream.Position; - metadataBlock.mediaPartNumberLength = (uint)(tmpUtf16Le.Length + 2); - blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - - blockStream.Write(new byte[] - { - 0, 0 - }, 0, 2); - } - - if(!string.IsNullOrWhiteSpace(_imageInfo.DriveManufacturer)) - { - tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.DriveManufacturer); - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.driveManufacturerOffset = (uint)blockStream.Position; - metadataBlock.driveManufacturerLength = (uint)(tmpUtf16Le.Length + 2); - blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - - blockStream.Write(new byte[] - { - 0, 0 - }, 0, 2); - } - - if(!string.IsNullOrWhiteSpace(_imageInfo.DriveModel)) - { - tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.DriveModel); - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.driveModelOffset = (uint)blockStream.Position; - metadataBlock.driveModelLength = (uint)(tmpUtf16Le.Length + 2); - blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - - blockStream.Write(new byte[] - { - 0, 0 - }, 0, 2); - } - - if(!string.IsNullOrWhiteSpace(_imageInfo.DriveSerialNumber)) - { - tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.DriveSerialNumber); - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.driveSerialNumberOffset = (uint)blockStream.Position; - metadataBlock.driveSerialNumberLength = (uint)(tmpUtf16Le.Length + 2); - blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - - blockStream.Write(new byte[] - { - 0, 0 - }, 0, 2); - } - - if(!string.IsNullOrWhiteSpace(_imageInfo.DriveFirmwareRevision)) - { - tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.DriveFirmwareRevision); - metadataBlock.identifier = BlockType.MetadataBlock; - metadataBlock.driveFirmwareRevisionOffset = (uint)blockStream.Position; - metadataBlock.driveFirmwareRevisionLength = (uint)(tmpUtf16Le.Length + 2); - blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - - blockStream.Write(new byte[] - { - 0, 0 - }, 0, 2); - } - - // Check if we set up any metadata earlier, then write its block - if(metadataBlock.identifier == BlockType.MetadataBlock) - { - AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing metadata to position {0}", - _imageStream.Position); - - metadataBlock.blockSize = (uint)blockStream.Length; - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref metadataBlock); - blockStream.Position = 0; - blockStream.Write(_structureBytes, 0, _structureBytes.Length); - _index.RemoveAll(t => t.blockType == BlockType.MetadataBlock && t.dataType == DataType.NoData); - - _index.Add(new IndexEntry - { - blockType = BlockType.MetadataBlock, - dataType = DataType.NoData, - offset = (ulong)_imageStream.Position - }); - - _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); - blockStream.Close(); - } - - _header.indexOffset = (ulong)_imageStream.Position; - - AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing index to position {0}", _header.indexOffset); - - blockStream = new MemoryStream(); - - // Write index to memory - foreach(IndexEntry entry in _index) - { - _structureBytes = new byte[Marshal.SizeOf()]; - IndexEntry indexEntry = entry; - MemoryMarshal.Write(_structureBytes, ref indexEntry); - blockStream.Write(_structureBytes, 0, _structureBytes.Length); - } - - Crc64Context.Data(blockStream.ToArray(), out byte[] idxCrc); - - if(_index.Count > ushort.MaxValue) - { - _header.imageMajorVersion = AARUFMT_VERSION; - - var idxHeader = new IndexHeader2 - { - identifier = BlockType.Index2, - entries = (ulong)_index.Count, - crc64 = BitConverter.ToUInt64(idxCrc, 0) - }; - - // Write index header to disk - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref idxHeader); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + _currentBlockHeader.cmpCrc64 = _currentBlockHeader.crc64; + _currentBlockHeader.cmpLength = (uint)_writingBufferPosition; } else { - var idxHeader = new IndexHeader - { - identifier = BlockType.Index, - entries = (ushort)_index.Count, - crc64 = BitConverter.ToUInt64(idxCrc, 0) - }; - - // Write index header to disk - _structureBytes = new byte[Marshal.SizeOf()]; - MemoryMarshal.Write(_structureBytes, ref idxHeader); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + cmpCrc64Context.Update(_compressedBuffer, (uint)compressedLength); + _currentBlockHeader.cmpCrc64 = BitConverter.ToUInt64(cmpCrc64Context.Final(), 0); + _currentBlockHeader.cmpLength = (uint)compressedLength; } - // Write index to disk + if(_currentBlockHeader.compression == CompressionType.Lzma) + _currentBlockHeader.cmpLength += LZMA_PROPERTIES_LENGTH; + + _index.Add(new IndexEntry + { + blockType = BlockType.DataBlock, + dataType = DataType.UserData, + offset = (ulong)_imageStream.Position + }); + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref _currentBlockHeader); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + _structureBytes = null; + + if(_currentBlockHeader.compression == CompressionType.Lzma) + _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); + + if(_currentBlockHeader.compression == CompressionType.None) + _imageStream.Write(_writingBuffer, 0, _writingBufferPosition); + else + _imageStream.Write(_compressedBuffer, 0, compressedLength); + + _writingBuffer = null; + } + + if(_deduplicate) + AaruConsole.DebugWriteLine("Aaru Format plugin", "Of {0} sectors written, {1} are unique ({2:P})", + _writtenSectors, _deduplicationTable.Count, + (double)_deduplicationTable.Count / _writtenSectors); + + IndexEntry idxEntry; + + // TODO: Reuse buffer + MemoryStream blockStream; + + // Write media tag blocks + foreach(KeyValuePair mediaTag in _mediaTags) + { + DataType dataType = GetDataTypeForMediaTag(mediaTag.Key); + + if(mediaTag.Value is null) + { + AaruConsole.ErrorWriteLine("Tag type {0} is null, skipping...", dataType); + + continue; + } + + idxEntry = new IndexEntry + { + blockType = BlockType.DataBlock, + dataType = dataType, + offset = (ulong)_imageStream.Position + }; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing tag type {0} to position {1}", mediaTag.Key, + idxEntry.offset); + + Crc64Context.Data(mediaTag.Value, out byte[] tagCrc); + + var tagBlock = new BlockHeader + { + identifier = BlockType.DataBlock, + type = dataType, + length = (uint)mediaTag.Value.Length, + crc64 = BitConverter.ToUInt64(tagCrc, 0) + }; + + var cmpBuffer = new byte[mediaTag.Value.Length + 262144]; + + int cmpLen; + byte[] lzmaProperties = null; + var doNotCompress = false; + + switch(_compressionAlgorithm) + { + case CompressionType.Lzma: + cmpLen = LZMA.EncodeBuffer(mediaTag.Value, cmpBuffer, out lzmaProperties, 9, _dictionarySize, 4, 0, + 2, 273); + + if(cmpLen + LZMA_PROPERTIES_LENGTH > mediaTag.Value.Length) + doNotCompress = true; + + break; + case CompressionType.None: + doNotCompress = true; + + break; + default: throw new ArgumentOutOfRangeException(); + } + + byte[] tagData; + + // Not compressible + if(doNotCompress) + { + tagBlock.cmpLength = tagBlock.length; + tagBlock.cmpCrc64 = tagBlock.crc64; + tagData = mediaTag.Value; + tagBlock.compression = CompressionType.None; + } + else + { + tagData = cmpBuffer; + var crc64Ctx = new Crc64Context(); + + if(_compressionAlgorithm == CompressionType.Lzma) + crc64Ctx.Update(lzmaProperties); + + crc64Ctx.Update(tagData); + tagCrc = crc64Ctx.Final(); + tagBlock.cmpLength = (uint)tagData.Length; + tagBlock.cmpCrc64 = BitConverter.ToUInt64(tagCrc, 0); + tagBlock.compression = _compressionAlgorithm; + + if(_compressionAlgorithm == CompressionType.Lzma) + tagBlock.cmpLength += LZMA_PROPERTIES_LENGTH; + } + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref tagBlock); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + + if(tagBlock.compression == CompressionType.Lzma) + _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); + + _imageStream.Write(tagData, 0, tagData.Length); + + _index.RemoveAll(t => t.blockType == BlockType.DataBlock && t.dataType == dataType); + + _index.Add(idxEntry); + } + + // If we have set the geometry block, write it + if(_geometryBlock.identifier == BlockType.GeometryBlock) + { + idxEntry = new IndexEntry + { + blockType = BlockType.GeometryBlock, + dataType = DataType.NoData, + offset = (ulong)_imageStream.Position + }; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing geometry block to position {0}", idxEntry.offset); + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref _geometryBlock); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + + _index.RemoveAll(t => t.blockType == BlockType.GeometryBlock && t.dataType == DataType.NoData); + + _index.Add(idxEntry); + } + + // If we have dump hardware, write it + if(DumpHardware != null) + { + var dumpMs = new MemoryStream(); + + foreach(DumpHardwareType dump in DumpHardware) + { + byte[] dumpManufacturer = null; + byte[] dumpModel = null; + byte[] dumpRevision = null; + byte[] dumpFirmware = null; + byte[] dumpSerial = null; + byte[] dumpSoftwareName = null; + byte[] dumpSoftwareVersion = null; + byte[] dumpSoftwareOperatingSystem = null; + + if(!string.IsNullOrWhiteSpace(dump.Manufacturer)) + dumpManufacturer = Encoding.UTF8.GetBytes(dump.Manufacturer); + + if(!string.IsNullOrWhiteSpace(dump.Model)) + dumpModel = Encoding.UTF8.GetBytes(dump.Model); + + if(!string.IsNullOrWhiteSpace(dump.Revision)) + dumpRevision = Encoding.UTF8.GetBytes(dump.Revision); + + if(!string.IsNullOrWhiteSpace(dump.Firmware)) + dumpFirmware = Encoding.UTF8.GetBytes(dump.Firmware); + + if(!string.IsNullOrWhiteSpace(dump.Serial)) + dumpSerial = Encoding.UTF8.GetBytes(dump.Serial); + + if(!string.IsNullOrWhiteSpace(dump.Software?.Name)) + dumpSoftwareName = Encoding.UTF8.GetBytes(dump.Software.Name); + + if(!string.IsNullOrWhiteSpace(dump.Software?.Version)) + dumpSoftwareVersion = Encoding.UTF8.GetBytes(dump.Software.Version); + + if(!string.IsNullOrWhiteSpace(dump.Software?.OperatingSystem)) + dumpSoftwareOperatingSystem = Encoding.UTF8.GetBytes(dump.Software.OperatingSystem); + + var dumpEntry = new DumpHardwareEntry + { + manufacturerLength = (uint)(dumpManufacturer?.Length + 1 ?? 0), + modelLength = (uint)(dumpModel?.Length + 1 ?? 0), + revisionLength = (uint)(dumpRevision?.Length + 1 ?? 0), + firmwareLength = (uint)(dumpFirmware?.Length + 1 ?? 0), + serialLength = (uint)(dumpSerial?.Length + 1 ?? 0), + softwareNameLength = (uint)(dumpSoftwareName?.Length + 1 ?? 0), + softwareVersionLength = (uint)(dumpSoftwareVersion?.Length + 1 ?? 0), + softwareOperatingSystemLength = (uint)(dumpSoftwareOperatingSystem?.Length + 1 ?? 0), + extents = (uint)dump.Extents.Length + }; + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref dumpEntry); + dumpMs.Write(_structureBytes, 0, _structureBytes.Length); + + if(dumpManufacturer != null) + { + dumpMs.Write(dumpManufacturer, 0, dumpManufacturer.Length); + dumpMs.WriteByte(0); + } + + if(dumpModel != null) + { + dumpMs.Write(dumpModel, 0, dumpModel.Length); + dumpMs.WriteByte(0); + } + + if(dumpRevision != null) + { + dumpMs.Write(dumpRevision, 0, dumpRevision.Length); + dumpMs.WriteByte(0); + } + + if(dumpFirmware != null) + { + dumpMs.Write(dumpFirmware, 0, dumpFirmware.Length); + dumpMs.WriteByte(0); + } + + if(dumpSerial != null) + { + dumpMs.Write(dumpSerial, 0, dumpSerial.Length); + dumpMs.WriteByte(0); + } + + if(dumpSoftwareName != null) + { + dumpMs.Write(dumpSoftwareName, 0, dumpSoftwareName.Length); + dumpMs.WriteByte(0); + } + + if(dumpSoftwareVersion != null) + { + dumpMs.Write(dumpSoftwareVersion, 0, dumpSoftwareVersion.Length); + dumpMs.WriteByte(0); + } + + if(dumpSoftwareOperatingSystem != null) + { + dumpMs.Write(dumpSoftwareOperatingSystem, 0, dumpSoftwareOperatingSystem.Length); + dumpMs.WriteByte(0); + } + + foreach(ExtentType extent in dump.Extents) + { + dumpMs.Write(BitConverter.GetBytes(extent.Start), 0, sizeof(ulong)); + dumpMs.Write(BitConverter.GetBytes(extent.End), 0, sizeof(ulong)); + } + } + + idxEntry = new IndexEntry + { + blockType = BlockType.DumpHardwareBlock, + dataType = DataType.NoData, + offset = (ulong)_imageStream.Position + }; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing dump hardware block to position {0}", + idxEntry.offset); + + Crc64Context.Data(dumpMs.ToArray(), out byte[] dumpCrc); + + var dumpBlock = new DumpHardwareHeader + { + identifier = BlockType.DumpHardwareBlock, + entries = (ushort)DumpHardware.Count, + crc64 = BitConverter.ToUInt64(dumpCrc, 0), + length = (uint)dumpMs.Length + }; + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref dumpBlock); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + _imageStream.Write(dumpMs.ToArray(), 0, (int)dumpMs.Length); + + _index.RemoveAll(t => t.blockType == BlockType.DumpHardwareBlock && t.dataType == DataType.NoData); + + _index.Add(idxEntry); + } + + // If we have CICM XML metadata, write it + if(CicmMetadata != null) + { + var cicmMs = new MemoryStream(); + var xmlSer = new XmlSerializer(typeof(CICMMetadataType)); + xmlSer.Serialize(cicmMs, CicmMetadata); + + idxEntry = new IndexEntry + { + blockType = BlockType.CicmBlock, + dataType = DataType.NoData, + offset = (ulong)_imageStream.Position + }; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing CICM XML block to position {0}", idxEntry.offset); + + var cicmBlock = new CicmMetadataBlock + { + identifier = BlockType.CicmBlock, + length = (uint)cicmMs.Length + }; + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref cicmBlock); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + _imageStream.Write(cicmMs.ToArray(), 0, (int)cicmMs.Length); + + _index.RemoveAll(t => t.blockType == BlockType.CicmBlock && t.dataType == DataType.NoData); + + _index.Add(idxEntry); + } + + // If we have checksums, write it to disk + if(_md5Provider != null || + _sha1Provider != null || + _sha256Provider != null || + _spamsumProvider != null) + { + var chkMs = new MemoryStream(); + + var chkHeader = new ChecksumHeader + { + identifier = BlockType.ChecksumBlock + }; + + if(_md5Provider != null) + { + byte[] md5 = _md5Provider.Final(); + + var md5Entry = new ChecksumEntry + { + type = ChecksumAlgorithm.Md5, + length = (uint)md5.Length + }; + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref md5Entry); + chkMs.Write(_structureBytes, 0, _structureBytes.Length); + chkMs.Write(md5, 0, md5.Length); + chkHeader.entries++; + } + + if(_sha1Provider != null) + { + byte[] sha1 = _sha1Provider.Final(); + + var sha1Entry = new ChecksumEntry + { + type = ChecksumAlgorithm.Sha1, + length = (uint)sha1.Length + }; + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref sha1Entry); + chkMs.Write(_structureBytes, 0, _structureBytes.Length); + chkMs.Write(sha1, 0, sha1.Length); + chkHeader.entries++; + } + + if(_sha256Provider != null) + { + byte[] sha256 = _sha256Provider.Final(); + + var sha256Entry = new ChecksumEntry + { + type = ChecksumAlgorithm.Sha256, + length = (uint)sha256.Length + }; + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref sha256Entry); + chkMs.Write(_structureBytes, 0, _structureBytes.Length); + chkMs.Write(sha256, 0, sha256.Length); + chkHeader.entries++; + } + + if(_spamsumProvider != null) + { + byte[] spamsum = Encoding.ASCII.GetBytes(_spamsumProvider.End()); + + var spamsumEntry = new ChecksumEntry + { + type = ChecksumAlgorithm.SpamSum, + length = (uint)spamsum.Length + }; + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref spamsumEntry); + chkMs.Write(_structureBytes, 0, _structureBytes.Length); + chkMs.Write(spamsum, 0, spamsum.Length); + chkHeader.entries++; + } + + if(chkHeader.entries > 0) + { + chkHeader.length = (uint)chkMs.Length; + + idxEntry = new IndexEntry + { + blockType = BlockType.ChecksumBlock, + dataType = DataType.NoData, + offset = (ulong)_imageStream.Position + }; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing checksum block to position {0}", + idxEntry.offset); + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref chkHeader); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + _imageStream.Write(chkMs.ToArray(), 0, (int)chkMs.Length); + + _index.RemoveAll(t => t.blockType == BlockType.ChecksumBlock && t.dataType == DataType.NoData); + + _index.Add(idxEntry); + } + } + + if(IsTape) + { + ulong latestBlock = _tapeDdt.Max(b => b.Key); + + _userDataDdt = new ulong[latestBlock + 1]; + + foreach(KeyValuePair block in _tapeDdt) + _userDataDdt[block.Key] = block.Value; + + _inMemoryDdt = true; + _tapeDdt.Clear(); + + idxEntry = new IndexEntry + { + blockType = BlockType.TapePartitionBlock, + dataType = DataType.UserData, + offset = (ulong)_imageStream.Position + }; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing tape partitions to position {0}", + idxEntry.offset); + + var tapePartitionEntries = new TapePartitionEntry[TapePartitions.Count]; + + for(var t = 0; t < TapePartitions.Count; t++) + tapePartitionEntries[t] = new TapePartitionEntry + { + Number = TapePartitions[t].Number, + FirstBlock = TapePartitions[t].FirstBlock, + LastBlock = TapePartitions[t].LastBlock + }; + + byte[] tapePartitionEntriesData = + MemoryMarshal.Cast(tapePartitionEntries).ToArray(); + + var tapePartitionHeader = new TapePartitionHeader + { + identifier = BlockType.TapePartitionBlock, + entries = (byte)tapePartitionEntries.Length, + length = (ulong)tapePartitionEntriesData.Length + }; + + _crc64 = new Crc64Context(); + _crc64.Update(tapePartitionEntriesData); + tapePartitionHeader.crc64 = BitConverter.ToUInt64(_crc64.Final(), 0); + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref tapePartitionHeader); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + _structureBytes = null; + _imageStream.Write(tapePartitionEntriesData, 0, tapePartitionEntriesData.Length); + + _index.RemoveAll(t => t.blockType == BlockType.TapePartitionBlock && t.dataType == DataType.UserData); + _index.Add(idxEntry); + + idxEntry = new IndexEntry + { + blockType = BlockType.TapeFileBlock, + dataType = DataType.UserData, + offset = (ulong)_imageStream.Position + }; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing tape files to position {0}", idxEntry.offset); + + var tapeFileEntries = new TapeFileEntry[Files.Count]; + + for(var t = 0; t < Files.Count; t++) + tapeFileEntries[t] = new TapeFileEntry + { + File = Files[t].File, + FirstBlock = Files[t].FirstBlock, + LastBlock = Files[t].LastBlock + }; + + byte[] tapeFileEntriesData = MemoryMarshal.Cast(tapeFileEntries).ToArray(); + + var tapeFileHeader = new TapeFileHeader + { + identifier = BlockType.TapeFileBlock, + entries = (uint)tapeFileEntries.Length, + length = (ulong)tapeFileEntriesData.Length + }; + + _crc64 = new Crc64Context(); + _crc64.Update(tapeFileEntriesData); + tapeFileHeader.crc64 = BitConverter.ToUInt64(_crc64.Final(), 0); + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref tapeFileHeader); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + _structureBytes = null; + _imageStream.Write(tapeFileEntriesData, 0, tapeFileEntriesData.Length); + + _index.RemoveAll(t => t.blockType == BlockType.TapeFileBlock && t.dataType == DataType.UserData); + _index.Add(idxEntry); + } + + // If the DDT is in-memory, write it to disk + if(_inMemoryDdt) + { + idxEntry = new IndexEntry + { + blockType = BlockType.DeDuplicationTable, + dataType = DataType.UserData, + offset = (ulong)_imageStream.Position + }; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing user data DDT to position {0}", idxEntry.offset); + + var ddtHeader = new DdtHeader + { + identifier = BlockType.DeDuplicationTable, + type = DataType.UserData, + + compression = _compressionAlgorithm, + shift = _shift, + entries = (ulong)_userDataDdt.LongLength, + length = (ulong)(_userDataDdt.LongLength * sizeof(ulong)) + }; + + _crc64 = new Crc64Context(); + byte[] ddtEntries = MemoryMarshal.Cast(_userDataDdt).ToArray(); + _crc64.Update(ddtEntries); + + var cmpBuffer = new byte[ddtEntries.Length + 262144]; + + int cmpLen; + byte[] lzmaProperties = null; + + switch(_compressionAlgorithm) + { + case CompressionType.None: + cmpBuffer = ddtEntries; + cmpLen = cmpBuffer.Length; + + break; + case CompressionType.Lzma: + cmpLen = LZMA.EncodeBuffer(ddtEntries, cmpBuffer, out lzmaProperties, 9, _dictionarySize, 4, 0, 2, + 273); + + break; + default: throw new ArgumentOutOfRangeException(); + } + + blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); + + ddtHeader.cmpLength = (uint)blockStream.Length; + + if(_compressionAlgorithm == CompressionType.Lzma && + cmpBuffer != ddtEntries) + ddtHeader.cmpLength += LZMA_PROPERTIES_LENGTH; + + var cmpCrc64Context = new Crc64Context(); + + if(_compressionAlgorithm == CompressionType.Lzma && + cmpBuffer != ddtEntries) + cmpCrc64Context.Update(lzmaProperties); + + cmpCrc64Context.Update(blockStream.ToArray()); + ddtHeader.cmpCrc64 = BitConverter.ToUInt64(cmpCrc64Context.Final(), 0); + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref ddtHeader); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + _structureBytes = null; + + if(_compressionAlgorithm == CompressionType.Lzma) + _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); + _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); blockStream.Close(); - AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing header"); - _header.lastWrittenTime = DateTime.UtcNow.ToFileTimeUtc(); - _imageStream.Position = 0; - _structurePointer = System.Runtime.InteropServices.Marshal.AllocHGlobal(Marshal.SizeOf()); - _structureBytes = new byte[Marshal.SizeOf()]; - System.Runtime.InteropServices.Marshal.StructureToPtr(_header, _structurePointer, true); - System.Runtime.InteropServices.Marshal.Copy(_structurePointer, _structureBytes, 0, _structureBytes.Length); - System.Runtime.InteropServices.Marshal.FreeHGlobal(_structurePointer); - _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + _index.RemoveAll(t => t.blockType == BlockType.DeDuplicationTable && t.dataType == DataType.UserData); - _imageStream.Flush(); - _imageStream.Close(); - GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true); - - IsWriting = false; - ErrorMessage = ""; - - return true; + _index.Add(idxEntry); } - /// - public bool SetMetadata(ImageInfo metadata) + // Write the sector prefix, suffix and subchannels if present + switch(_imageInfo.XmlMediaType) { - _imageInfo.Creator = metadata.Creator; - _imageInfo.Comments = metadata.Comments; - _imageInfo.MediaManufacturer = metadata.MediaManufacturer; - _imageInfo.MediaModel = metadata.MediaModel; - _imageInfo.MediaSerialNumber = metadata.MediaSerialNumber; - _imageInfo.MediaBarcode = metadata.MediaBarcode; - _imageInfo.MediaPartNumber = metadata.MediaPartNumber; - _imageInfo.MediaSequence = metadata.MediaSequence; - _imageInfo.LastMediaSequence = metadata.LastMediaSequence; - _imageInfo.DriveManufacturer = metadata.DriveManufacturer; - _imageInfo.DriveModel = metadata.DriveModel; - _imageInfo.DriveSerialNumber = metadata.DriveSerialNumber; - _imageInfo.DriveFirmwareRevision = metadata.DriveFirmwareRevision; - _imageInfo.MediaTitle = metadata.MediaTitle; + case XmlMediaType.OpticalDisc when Tracks != null && Tracks.Count > 0: + DateTime startCompress; + DateTime endCompress; - return true; + // Old format + if(_sectorPrefix != null && + _sectorSuffix != null) + { + idxEntry = new IndexEntry + { + blockType = BlockType.DataBlock, + dataType = DataType.CdSectorPrefix, + offset = (ulong)_imageStream.Position + }; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing CD sector prefix block to position {0}", + idxEntry.offset); + + Crc64Context.Data(_sectorPrefix, out byte[] blockCrc); + + var prefixBlock = new BlockHeader + { + identifier = BlockType.DataBlock, + type = DataType.CdSectorPrefix, + length = (uint)_sectorPrefix.Length, + crc64 = BitConverter.ToUInt64(blockCrc, 0), + sectorSize = 16 + }; + + byte[] lzmaProperties = null; + + if(!_compress) + { + prefixBlock.compression = CompressionType.None; + prefixBlock.cmpCrc64 = prefixBlock.crc64; + prefixBlock.cmpLength = prefixBlock.length; + blockStream = new MemoryStream(_sectorPrefix); + } + else + { + startCompress = DateTime.Now; + + var cmpBuffer = new byte[_sectorPrefix.Length + 262144]; + + int cmpLen = _compressionAlgorithm switch + { + CompressionType.Lzma => LZMA.EncodeBuffer(_sectorPrefix, cmpBuffer, + out lzmaProperties, 9, _dictionarySize, 4, 0, 2, 273), + _ => throw new ArgumentOutOfRangeException() + }; + + blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); + + var cmpCrc = new Crc64Context(); + + if(_compressionAlgorithm == CompressionType.Lzma) + cmpCrc.Update(lzmaProperties); + + cmpCrc.Update(blockStream.ToArray()); + blockCrc = cmpCrc.Final(); + prefixBlock.cmpLength = (uint)blockStream.Length; + + if(_compressionAlgorithm == CompressionType.Lzma) + prefixBlock.cmpLength += LZMA_PROPERTIES_LENGTH; + + prefixBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); + prefixBlock.compression = _compressionAlgorithm; + + endCompress = DateTime.Now; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Took {0} seconds to compress prefix", + (endCompress - startCompress).TotalSeconds); + } + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref prefixBlock); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + + if(prefixBlock.compression == CompressionType.Lzma) + _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); + + _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); + blockStream.Close(); + + _index.RemoveAll(t => t.blockType == BlockType.DataBlock && t.dataType == DataType.CdSectorPrefix); + + _index.Add(idxEntry); + + idxEntry = new IndexEntry + { + blockType = BlockType.DataBlock, + dataType = DataType.CdSectorSuffix, + offset = (ulong)_imageStream.Position + }; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing CD sector suffix block to position {0}", + idxEntry.offset); + + Crc64Context.Data(_sectorSuffix, out blockCrc); + + prefixBlock = new BlockHeader + { + identifier = BlockType.DataBlock, + type = DataType.CdSectorSuffix, + length = (uint)_sectorSuffix.Length, + crc64 = BitConverter.ToUInt64(blockCrc, 0), + sectorSize = 288 + }; + + if(!_compress) + { + prefixBlock.compression = CompressionType.None; + prefixBlock.cmpCrc64 = prefixBlock.crc64; + prefixBlock.cmpLength = prefixBlock.length; + blockStream = new MemoryStream(_sectorSuffix); + } + else + { + startCompress = DateTime.Now; + + var cmpBuffer = new byte[_sectorSuffix.Length + 262144]; + + int cmpLen = _compressionAlgorithm switch + { + CompressionType.Lzma => LZMA.EncodeBuffer(_sectorSuffix, cmpBuffer, + out lzmaProperties, 9, _dictionarySize, 4, 0, 2, 273), + _ => throw new ArgumentOutOfRangeException() + }; + + blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); + + var cmpCrc = new Crc64Context(); + + if(_compressionAlgorithm == CompressionType.Lzma) + cmpCrc.Update(lzmaProperties); + + cmpCrc.Update(blockStream.ToArray()); + blockCrc = cmpCrc.Final(); + prefixBlock.cmpLength = (uint)blockStream.Length; + + if(_compressionAlgorithm == CompressionType.Lzma) + prefixBlock.cmpLength += LZMA_PROPERTIES_LENGTH; + + prefixBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); + prefixBlock.compression = CompressionType.Lzma; + + endCompress = DateTime.Now; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Took {0} seconds to compress suffix", + (endCompress - startCompress).TotalSeconds); + } + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref prefixBlock); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + + if(prefixBlock.compression == CompressionType.Lzma) + _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); + + _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); + + _index.RemoveAll(t => t.blockType == BlockType.DataBlock && t.dataType == DataType.CdSectorSuffix); + + _index.Add(idxEntry); + blockStream.Close(); + } + else if(_sectorSuffixMs != null && + _sectorSuffixDdt != null && + _sectorPrefixMs != null && + _sectorPrefixDdt != null) + { + #if DEBUG + uint notDumpedPrefixes = 0; + uint correctPrefixes = 0; + uint writtenPrefixes = 0; + uint notDumpedSuffixes = 0; + uint correctSuffixes = 0; + uint writtenSuffixes = 0; + uint correctMode2Form1 = 0; + uint correctMode2Form2 = 0; + uint emptyMode2Form1 = 0; + + for(long i = 0; i < _sectorPrefixDdt.LongLength; i++) + if((_sectorPrefixDdt[i] & CD_XFIX_MASK) == (uint)CdFixFlags.NotDumped) + notDumpedPrefixes++; + else if((_sectorPrefixDdt[i] & CD_XFIX_MASK) == (uint)CdFixFlags.Correct) + correctPrefixes++; + else if((_sectorPrefixDdt[i] & CD_DFIX_MASK) > 0) + writtenPrefixes++; + + for(long i = 0; i < _sectorPrefixDdt.LongLength; i++) + if((_sectorSuffixDdt[i] & CD_XFIX_MASK) == (uint)CdFixFlags.NotDumped) + notDumpedSuffixes++; + else if((_sectorSuffixDdt[i] & CD_XFIX_MASK) == (uint)CdFixFlags.Correct) + correctSuffixes++; + else if((_sectorSuffixDdt[i] & CD_XFIX_MASK) == (uint)CdFixFlags.Mode2Form1Ok) + correctMode2Form1++; + else if((_sectorSuffixDdt[i] & CD_XFIX_MASK) == (uint)CdFixFlags.Mode2Form2Ok) + correctMode2Form2++; + else if((_sectorSuffixDdt[i] & CD_XFIX_MASK) == (uint)CdFixFlags.Mode2Form2NoCrc) + emptyMode2Form1++; + else if((_sectorSuffixDdt[i] & CD_DFIX_MASK) > 0) + writtenSuffixes++; + + AaruConsole.DebugWriteLine("Aaru Format plugin", + "{0} ({1:P}% prefixes are correct, {2} ({3:P}%) prefixes have not been dumped, {4} ({5:P}%) prefixes have been written to image", + correctPrefixes, correctPrefixes / _imageInfo.Sectors, notDumpedPrefixes, + notDumpedPrefixes / _imageInfo.Sectors, writtenPrefixes, + writtenPrefixes / _imageInfo.Sectors); + + AaruConsole.DebugWriteLine("Aaru Format plugin", + "{0} ({1:P}% suffixes are correct, {2} ({3:P}%) suffixes have not been dumped, {4} ({5:P}%) suffixes have been written to image", + correctSuffixes, correctSuffixes / _imageInfo.Sectors, notDumpedSuffixes, + notDumpedSuffixes / _imageInfo.Sectors, writtenSuffixes, + writtenSuffixes / _imageInfo.Sectors); + + AaruConsole.DebugWriteLine("Aaru Format plugin", + "{0} ({1:P}% MODE 2 Form 1 are correct, {2} ({3:P}%) MODE 2 Form 2 are correct, {4} ({5:P}%) MODE 2 Form 2 have empty CRC", + correctMode2Form1, correctMode2Form1 / _imageInfo.Sectors, + correctMode2Form2, correctMode2Form2 / _imageInfo.Sectors, + emptyMode2Form1, emptyMode2Form1 / _imageInfo.Sectors); + #endif + + idxEntry = new IndexEntry + { + blockType = BlockType.DeDuplicationTable, + dataType = DataType.CdSectorPrefixCorrected, + offset = (ulong)_imageStream.Position + }; + + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Writing CompactDisc sector prefix DDT to position {0}", + idxEntry.offset); + + var ddtHeader = new DdtHeader + { + identifier = BlockType.DeDuplicationTable, + type = DataType.CdSectorPrefixCorrected, + compression = _compressionAlgorithm, + entries = (ulong)_sectorPrefixDdt.LongLength, + length = (ulong)(_sectorPrefixDdt.LongLength * sizeof(uint)) + }; + + _crc64 = new Crc64Context(); + byte[] ddtEntries = MemoryMarshal.Cast(_sectorPrefixDdt).ToArray(); + _crc64.Update(ddtEntries); + + var cmpBuffer = new byte[ddtEntries.Length + 262144]; + + int cmpLen; + byte[] lzmaProperties; + + cmpLen = _compressionAlgorithm switch + { + CompressionType.Lzma => LZMA.EncodeBuffer(ddtEntries, cmpBuffer, out lzmaProperties, 9, + _dictionarySize, 4, 0, 2, 273), + _ => throw new ArgumentOutOfRangeException() + }; + + blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); + + ddtHeader.cmpLength = (uint)blockStream.Length; + + if(_compressionAlgorithm == CompressionType.Lzma) + ddtHeader.cmpLength += LZMA_PROPERTIES_LENGTH; + + var cmpCrc64Context = new Crc64Context(); + + if(_compressionAlgorithm == CompressionType.Lzma) + cmpCrc64Context.Update(lzmaProperties); + + cmpCrc64Context.Update(blockStream.ToArray()); + ddtHeader.cmpCrc64 = BitConverter.ToUInt64(cmpCrc64Context.Final(), 0); + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref ddtHeader); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + _structureBytes = null; + + if(_compressionAlgorithm == CompressionType.Lzma) + _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); + + _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); + blockStream.Close(); + + _index.RemoveAll(t => t.blockType == BlockType.DeDuplicationTable && + t.dataType == DataType.CdSectorPrefixCorrected); + + _index.Add(idxEntry); + + idxEntry = new IndexEntry + { + blockType = BlockType.DeDuplicationTable, + dataType = DataType.CdSectorSuffixCorrected, + offset = (ulong)_imageStream.Position + }; + + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Writing CompactDisc sector suffix DDT to position {0}", + idxEntry.offset); + + ddtHeader = new DdtHeader + { + identifier = BlockType.DeDuplicationTable, + type = DataType.CdSectorSuffixCorrected, + compression = _compressionAlgorithm, + entries = (ulong)_sectorSuffixDdt.LongLength, + length = (ulong)(_sectorSuffixDdt.LongLength * sizeof(uint)) + }; + + _crc64 = new Crc64Context(); + ddtEntries = MemoryMarshal.Cast(_sectorSuffixDdt).ToArray(); + _crc64.Update(ddtEntries); + + cmpBuffer = new byte[ddtEntries.Length + 262144]; + + cmpLen = _compressionAlgorithm switch + { + CompressionType.Lzma => LZMA.EncodeBuffer(ddtEntries, cmpBuffer, out lzmaProperties, 9, + _dictionarySize, 4, 0, 2, 273), + _ => throw new ArgumentOutOfRangeException() + }; + + blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); + + ddtHeader.cmpLength = (uint)blockStream.Length; + + if(_compressionAlgorithm == CompressionType.Lzma) + ddtHeader.cmpLength += LZMA_PROPERTIES_LENGTH; + + cmpCrc64Context = new Crc64Context(); + + if(_compressionAlgorithm == CompressionType.Lzma) + cmpCrc64Context.Update(lzmaProperties); + + cmpCrc64Context.Update(blockStream.ToArray()); + ddtHeader.cmpCrc64 = BitConverter.ToUInt64(cmpCrc64Context.Final(), 0); + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref ddtHeader); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + _structureBytes = null; + + if(_compressionAlgorithm == CompressionType.Lzma) + _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); + + _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); + blockStream.Close(); + + _index.RemoveAll(t => t.blockType == BlockType.DeDuplicationTable && + t.dataType == DataType.CdSectorSuffixCorrected); + + _index.Add(idxEntry); + + idxEntry = new IndexEntry + { + blockType = BlockType.DataBlock, + dataType = DataType.CdSectorPrefixCorrected, + offset = (ulong)_imageStream.Position + }; + + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Writing CD sector corrected prefix block to position {0}", + idxEntry.offset); + + Crc64Context.Data(_sectorPrefixMs.GetBuffer(), (uint)_sectorPrefixMs.Length, out byte[] blockCrc); + + var prefixBlock = new BlockHeader + { + identifier = BlockType.DataBlock, + type = DataType.CdSectorPrefixCorrected, + length = (uint)_sectorPrefixMs.Length, + crc64 = BitConverter.ToUInt64(blockCrc, 0), + sectorSize = 16 + }; + + lzmaProperties = null; + + if(!_compress) + { + prefixBlock.compression = CompressionType.None; + prefixBlock.cmpCrc64 = prefixBlock.crc64; + prefixBlock.cmpLength = prefixBlock.length; + blockStream = _sectorPrefixMs; + } + else + { + startCompress = DateTime.Now; + + byte[] sectorPrefixBuffer = _sectorPrefixMs.ToArray(); + cmpBuffer = new byte[sectorPrefixBuffer.Length + 262144]; + + cmpLen = _compressionAlgorithm switch + { + CompressionType.Lzma => LZMA.EncodeBuffer(sectorPrefixBuffer, cmpBuffer, + out lzmaProperties, 9, _dictionarySize, + 4, 0, 2, 273), + _ => throw new ArgumentOutOfRangeException() + }; + + blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); + + var cmpCrc = new Crc64Context(); + + if(_compressionAlgorithm == CompressionType.Lzma) + cmpCrc.Update(lzmaProperties); + + cmpCrc.Update(blockStream.ToArray()); + blockCrc = cmpCrc.Final(); + prefixBlock.cmpLength = (uint)blockStream.Length; + + if(_compressionAlgorithm == CompressionType.Lzma) + prefixBlock.cmpLength += LZMA_PROPERTIES_LENGTH; + + prefixBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); + prefixBlock.compression = _compressionAlgorithm; + + endCompress = DateTime.Now; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Took {0} seconds to compress prefix", + (endCompress - startCompress).TotalSeconds); + } + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref prefixBlock); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + + if(prefixBlock.compression == CompressionType.Lzma) + _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); + + _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); + blockStream.Close(); + + _index.RemoveAll(t => t.blockType == BlockType.DataBlock && + t.dataType == DataType.CdSectorPrefixCorrected); + + _index.Add(idxEntry); + + idxEntry = new IndexEntry + { + blockType = BlockType.DataBlock, + dataType = DataType.CdSectorSuffixCorrected, + offset = (ulong)_imageStream.Position + }; + + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Writing CD sector corrected suffix block to position {0}", + idxEntry.offset); + + Crc64Context.Data(_sectorSuffixMs.GetBuffer(), (uint)_sectorSuffixMs.Length, out blockCrc); + + var suffixBlock = new BlockHeader + { + identifier = BlockType.DataBlock, + type = DataType.CdSectorSuffixCorrected, + length = (uint)_sectorSuffixMs.Length, + crc64 = BitConverter.ToUInt64(blockCrc, 0), + sectorSize = 288 + }; + + lzmaProperties = null; + + if(!_compress) + { + suffixBlock.compression = CompressionType.None; + suffixBlock.cmpCrc64 = suffixBlock.crc64; + suffixBlock.cmpLength = suffixBlock.length; + blockStream = _sectorSuffixMs; + } + else + { + startCompress = DateTime.Now; + + byte[] sectorSuffixBuffer = _sectorPrefixMs.ToArray(); + cmpBuffer = new byte[sectorSuffixBuffer.Length + 262144]; + + cmpLen = _compressionAlgorithm switch + { + CompressionType.Lzma => LZMA.EncodeBuffer(sectorSuffixBuffer, cmpBuffer, + out lzmaProperties, 9, _dictionarySize, + 4, 0, 2, 273), + _ => throw new ArgumentOutOfRangeException() + }; + + blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); + + var cmpCrc = new Crc64Context(); + + if(_compressionAlgorithm == CompressionType.Lzma) + cmpCrc.Update(lzmaProperties); + + cmpCrc.Update(blockStream.ToArray()); + blockCrc = cmpCrc.Final(); + suffixBlock.cmpLength = (uint)blockStream.Length; + + if(_compressionAlgorithm == CompressionType.Lzma) + suffixBlock.cmpLength += LZMA_PROPERTIES_LENGTH; + + suffixBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); + suffixBlock.compression = _compressionAlgorithm; + + endCompress = DateTime.Now; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Took {0} seconds to compress suffix", + (endCompress - startCompress).TotalSeconds); + } + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref suffixBlock); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + + if(suffixBlock.compression == CompressionType.Lzma) + _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); + + _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); + blockStream.Close(); + + _index.RemoveAll(t => t.blockType == BlockType.DataBlock && + t.dataType == DataType.CdSectorSuffixCorrected); + + _index.Add(idxEntry); + } + + if(_mode2Subheaders != null) + { + idxEntry = new IndexEntry + { + blockType = BlockType.DataBlock, + dataType = DataType.CompactDiscMode2Subheader, + offset = (ulong)_imageStream.Position + }; + + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Writing CD MODE2 subheaders block to position {0}", idxEntry.offset); + + Crc64Context.Data(_mode2Subheaders, out byte[] blockCrc); + + var subheaderBlock = new BlockHeader + { + identifier = BlockType.DataBlock, + type = DataType.CompactDiscMode2Subheader, + length = (uint)_mode2Subheaders.Length, + crc64 = BitConverter.ToUInt64(blockCrc, 0), + sectorSize = 8 + }; + + byte[] lzmaProperties = null; + + if(!_compress) + { + subheaderBlock.compression = CompressionType.None; + subheaderBlock.cmpCrc64 = subheaderBlock.crc64; + subheaderBlock.cmpLength = subheaderBlock.length; + blockStream = new MemoryStream(_mode2Subheaders); + } + else + { + startCompress = DateTime.Now; + + var cmpBuffer = new byte[_mode2Subheaders.Length + 262144]; + + int cmpLen = _compressionAlgorithm switch + { + CompressionType.Lzma => LZMA.EncodeBuffer(_mode2Subheaders, cmpBuffer, + out lzmaProperties, 9, _dictionarySize, 4, 0, 2, 273), + _ => throw new ArgumentOutOfRangeException() + }; + + blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); + + var cmpCrc = new Crc64Context(); + + if(_compressionAlgorithm == CompressionType.Lzma) + cmpCrc.Update(lzmaProperties); + + cmpCrc.Update(blockStream.ToArray()); + blockCrc = cmpCrc.Final(); + subheaderBlock.cmpLength = (uint)blockStream.Length; + + if(_compressionAlgorithm == CompressionType.Lzma) + subheaderBlock.cmpLength += LZMA_PROPERTIES_LENGTH; + + subheaderBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); + subheaderBlock.compression = _compressionAlgorithm; + + endCompress = DateTime.Now; + + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Took {0} seconds to compress MODE2 subheaders", + (endCompress - startCompress).TotalSeconds); + } + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref subheaderBlock); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + + if(subheaderBlock.compression == CompressionType.Lzma) + _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); + + _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); + + _index.RemoveAll(t => t.blockType == BlockType.DataBlock && + t.dataType == DataType.CompactDiscMode2Subheader); + + _index.Add(idxEntry); + blockStream.Close(); + } + + if(_sectorSubchannel != null) + { + idxEntry = new IndexEntry + { + blockType = BlockType.DataBlock, + dataType = DataType.CdSectorSubchannel, + offset = (ulong)_imageStream.Position + }; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing CD subchannel block to position {0}", + idxEntry.offset); + + Crc64Context.Data(_sectorSubchannel, out byte[] blockCrc); + + var subchannelBlock = new BlockHeader + { + identifier = BlockType.DataBlock, + type = DataType.CdSectorSubchannel, + length = (uint)_sectorSubchannel.Length, + crc64 = BitConverter.ToUInt64(blockCrc, 0), + sectorSize = 96 + }; + + byte[] lzmaProperties = null; + + if(!_compress) + { + subchannelBlock.compression = CompressionType.None; + subchannelBlock.cmpCrc64 = subchannelBlock.crc64; + subchannelBlock.cmpLength = subchannelBlock.length; + blockStream = new MemoryStream(_sectorSubchannel); + } + else + { + startCompress = DateTime.Now; + byte[] transformedSubchannel = ClauniaSubchannelTransform(_sectorSubchannel); + + var cmpBuffer = new byte[transformedSubchannel.Length + 262144]; + + int cmpLen = _compressionAlgorithm switch + { + CompressionType.Lzma => LZMA.EncodeBuffer(transformedSubchannel, cmpBuffer, + out lzmaProperties, 9, _dictionarySize, 4, 0, 2, 273), + _ => throw new ArgumentOutOfRangeException() + }; + + blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); + + var cmpCrc = new Crc64Context(); + + if(_compressionAlgorithm == CompressionType.Lzma) + cmpCrc.Update(lzmaProperties); + + cmpCrc.Update(blockStream.ToArray()); + blockCrc = cmpCrc.Final(); + subchannelBlock.cmpLength = (uint)blockStream.Length; + + if(_compressionAlgorithm == CompressionType.Lzma) + subchannelBlock.cmpLength += LZMA_PROPERTIES_LENGTH; + + subchannelBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); + + if(_compressionAlgorithm == CompressionType.Lzma) + subchannelBlock.compression = CompressionType.LzmaClauniaSubchannelTransform; + else + subchannelBlock.compression = _compressionAlgorithm; + + endCompress = DateTime.Now; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Took {0} seconds to compress subchannel", + (endCompress - startCompress).TotalSeconds); + } + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref subchannelBlock); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + + if(subchannelBlock.compression is CompressionType.Lzma + or CompressionType.LzmaClauniaSubchannelTransform) + _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); + + _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); + + _index.RemoveAll(t => t.blockType == BlockType.DataBlock && + t.dataType == DataType.CdSectorSubchannel); + + _index.Add(idxEntry); + blockStream.Close(); + } + + if(_sectorCpiMai != null) + { + idxEntry = new IndexEntry + { + blockType = BlockType.DataBlock, + dataType = DataType.DvdSectorCpiMai, + offset = (ulong)_imageStream.Position + }; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing DVD CPI_MAI block to position {0}", + idxEntry.offset); + + Crc64Context.Data(_sectorCpiMai, out byte[] blockCrc); + + var cpiMaiBlock = new BlockHeader + { + identifier = BlockType.DataBlock, + type = DataType.DvdSectorCpiMai, + length = (uint)_sectorCpiMai.Length, + crc64 = BitConverter.ToUInt64(blockCrc, 0), + sectorSize = 6 + }; + + byte[] lzmaProperties = null; + + if(!_compress) + { + cpiMaiBlock.compression = CompressionType.None; + cpiMaiBlock.cmpCrc64 = cpiMaiBlock.crc64; + cpiMaiBlock.cmpLength = cpiMaiBlock.length; + blockStream = new MemoryStream(_sectorCpiMai); + } + else + { + startCompress = DateTime.Now; + + var cmpBuffer = new byte[_sectorCpiMai.Length + 262144]; + + int cmpLen = _compressionAlgorithm switch + { + CompressionType.Lzma => LZMA.EncodeBuffer(_sectorCpiMai, cmpBuffer, + out lzmaProperties, 9, _dictionarySize, 4, 0, 2, 273), + _ => throw new ArgumentOutOfRangeException() + }; + + blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); + + var cmpCrc = new Crc64Context(); + + if(_compressionAlgorithm == CompressionType.Lzma) + cmpCrc.Update(lzmaProperties); + + cmpCrc.Update(blockStream.ToArray()); + blockCrc = cmpCrc.Final(); + cpiMaiBlock.cmpLength = (uint)blockStream.Length; + + if(_compressionAlgorithm == CompressionType.Lzma) + cpiMaiBlock.cmpLength += LZMA_PROPERTIES_LENGTH; + + cpiMaiBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); + cpiMaiBlock.compression = _compressionAlgorithm; + + endCompress = DateTime.Now; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Took {0} seconds to compress CPI_MAI", + (endCompress - startCompress).TotalSeconds); + } + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref cpiMaiBlock); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + + if(cpiMaiBlock.compression is CompressionType.Lzma + or CompressionType.LzmaClauniaSubchannelTransform) + _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); + + _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); + + _index.RemoveAll(t => t.blockType == BlockType.DataBlock && t.dataType == DataType.DvdSectorCpiMai); + + _index.Add(idxEntry); + blockStream.Close(); + } + + if(_sectorDecryptedTitleKey != null) + { + idxEntry = new IndexEntry + { + blockType = BlockType.DataBlock, + dataType = DataType.DvdSectorTitleKeyDecrypted, + offset = (ulong)_imageStream.Position + }; + + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Writing decrypted DVD title key block to position {0}", + idxEntry.offset); + + Crc64Context.Data(_sectorDecryptedTitleKey, out byte[] blockCrc); + + var titleKeyBlock = new BlockHeader + { + identifier = BlockType.DataBlock, + type = DataType.DvdSectorTitleKeyDecrypted, + length = (uint)_sectorDecryptedTitleKey.Length, + crc64 = BitConverter.ToUInt64(blockCrc, 0), + sectorSize = 5 + }; + + byte[] lzmaProperties = null; + + if(!_compress) + { + titleKeyBlock.compression = CompressionType.None; + titleKeyBlock.cmpCrc64 = titleKeyBlock.crc64; + titleKeyBlock.cmpLength = titleKeyBlock.length; + blockStream = new MemoryStream(_sectorDecryptedTitleKey); + } + else + { + startCompress = DateTime.Now; + + var cmpBuffer = new byte[_sectorDecryptedTitleKey.Length + 262144]; + + int cmpLen = _compressionAlgorithm switch + { + CompressionType.Lzma => LZMA.EncodeBuffer(_sectorDecryptedTitleKey, cmpBuffer, + out lzmaProperties, 9, _dictionarySize, 4, 0, 2, 273), + _ => throw new ArgumentOutOfRangeException() + }; + + blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); + + var cmpCrc = new Crc64Context(); + + if(_compressionAlgorithm == CompressionType.Lzma) + cmpCrc.Update(lzmaProperties); + + cmpCrc.Update(blockStream.ToArray()); + blockCrc = cmpCrc.Final(); + titleKeyBlock.cmpLength = (uint)blockStream.Length; + + if(_compressionAlgorithm == CompressionType.Lzma) + titleKeyBlock.cmpLength += LZMA_PROPERTIES_LENGTH; + + titleKeyBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); + titleKeyBlock.compression = _compressionAlgorithm; + + endCompress = DateTime.Now; + + AaruConsole.DebugWriteLine("Aaru Format plugin", + "Took {0} seconds to compress decrypted DVD title keys", + (endCompress - startCompress).TotalSeconds); + } + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref titleKeyBlock); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + + if(titleKeyBlock.compression is CompressionType.Lzma + or CompressionType.LzmaClauniaSubchannelTransform) + _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); + + _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); + + _index.RemoveAll(t => t.blockType == BlockType.DataBlock && + t.dataType == DataType.DvdSectorTitleKeyDecrypted); + + _index.Add(idxEntry); + blockStream.Close(); + } + + List trackEntries = new(); + List compactDiscIndexEntries = new(); + + foreach(Track track in Tracks) + { + _trackFlags.TryGetValue((byte)track.Sequence, out byte flags); + _trackIsrcs.TryGetValue((byte)track.Sequence, out string isrc); + + if((flags & (int)CdFlags.DataTrack) == 0 && + track.Type != TrackType.Audio) + flags += (byte)CdFlags.DataTrack; + + trackEntries.Add(new TrackEntry + { + sequence = (byte)track.Sequence, + type = track.Type, + start = (long)track.StartSector, + end = (long)track.EndSector, + pregap = (long)track.Pregap, + session = (byte)track.Session, + isrc = isrc, + flags = flags + }); + + if(!track.Indexes.ContainsKey(0) && + track.Pregap > 0) + { + track.Indexes[0] = (int)track.StartSector; + track.Indexes[1] = (int)(track.StartSector + track.Pregap); + } + else if(!track.Indexes.ContainsKey(0) && + !track.Indexes.ContainsKey(1)) + track.Indexes[0] = (int)track.StartSector; + + compactDiscIndexEntries.AddRange(track.Indexes.Select(trackIndex => new CompactDiscIndexEntry + { + Index = trackIndex.Key, + Lba = trackIndex.Value, + Track = (ushort)track.Sequence + })); + } + + // If there are tracks build the tracks block + if(trackEntries.Count > 0) + { + blockStream = new MemoryStream(); + + foreach(TrackEntry entry in trackEntries) + { + _structurePointer = + System.Runtime.InteropServices.Marshal.AllocHGlobal(Marshal.SizeOf()); + + _structureBytes = new byte[Marshal.SizeOf()]; + System.Runtime.InteropServices.Marshal.StructureToPtr(entry, _structurePointer, true); + + System.Runtime.InteropServices.Marshal.Copy(_structurePointer, _structureBytes, 0, + _structureBytes.Length); + + System.Runtime.InteropServices.Marshal.FreeHGlobal(_structurePointer); + blockStream.Write(_structureBytes, 0, _structureBytes.Length); + } + + Crc64Context.Data(blockStream.ToArray(), out byte[] trksCrc); + + var trkHeader = new TracksHeader + { + identifier = BlockType.TracksBlock, + entries = (ushort)trackEntries.Count, + crc64 = BitConverter.ToUInt64(trksCrc, 0) + }; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing tracks to position {0}", + _imageStream.Position); + + _index.RemoveAll(t => t.blockType == BlockType.TracksBlock && t.dataType == DataType.NoData); + + _index.Add(new IndexEntry + { + blockType = BlockType.TracksBlock, + dataType = DataType.NoData, + offset = (ulong)_imageStream.Position + }); + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref trkHeader); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); + blockStream.Close(); + } + + // If there are track indexes bigger than 1 + if(compactDiscIndexEntries.Any(i => i.Index > 1)) + { + blockStream = new MemoryStream(); + + foreach(CompactDiscIndexEntry entry in compactDiscIndexEntries) + { + _structurePointer = + System.Runtime.InteropServices.Marshal. + AllocHGlobal(Marshal.SizeOf()); + + _structureBytes = new byte[Marshal.SizeOf()]; + System.Runtime.InteropServices.Marshal.StructureToPtr(entry, _structurePointer, true); + + System.Runtime.InteropServices.Marshal.Copy(_structurePointer, _structureBytes, 0, + _structureBytes.Length); + + System.Runtime.InteropServices.Marshal.FreeHGlobal(_structurePointer); + blockStream.Write(_structureBytes, 0, _structureBytes.Length); + } + + Crc64Context.Data(blockStream.ToArray(), out byte[] cdixCrc); + + var cdixHeader = new CompactDiscIndexesHeader + { + identifier = BlockType.CompactDiscIndexesBlock, + entries = (ushort)compactDiscIndexEntries.Count, + crc64 = BitConverter.ToUInt64(cdixCrc, 0) + }; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing compact disc indexes to position {0}", + _imageStream.Position); + + _index.RemoveAll(t => t.blockType == BlockType.CompactDiscIndexesBlock && + t.dataType == DataType.NoData); + + _index.Add(new IndexEntry + { + blockType = BlockType.CompactDiscIndexesBlock, + dataType = DataType.NoData, + offset = (ulong)_imageStream.Position + }); + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref cdixHeader); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); + blockStream.Close(); + } + + break; + case XmlMediaType.BlockMedia: + if(_sectorSubchannel != null && + _imageInfo.MediaType is MediaType.AppleFileWare or MediaType.AppleSonySS or MediaType.AppleSonyDS + or MediaType.AppleProfile or MediaType.AppleWidget or MediaType.PriamDataTower) + { + DataType tagType = DataType.NoData; + + switch(_imageInfo.MediaType) + { + case MediaType.AppleSonySS: + case MediaType.AppleSonyDS: + tagType = DataType.AppleSonyTag; + + break; + case MediaType.AppleFileWare: + case MediaType.AppleProfile: + case MediaType.AppleWidget: + tagType = DataType.AppleProfileTag; + + break; + case MediaType.PriamDataTower: + tagType = DataType.PriamDataTowerTag; + + break; + } + + idxEntry = new IndexEntry + { + blockType = BlockType.DataBlock, + dataType = tagType, + offset = (ulong)_imageStream.Position + }; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing apple sector tag block to position {0}", + idxEntry.offset); + + Crc64Context.Data(_sectorSubchannel, out byte[] blockCrc); + + var subchannelBlock = new BlockHeader + { + identifier = BlockType.DataBlock, + type = tagType, + length = (uint)_sectorSubchannel.Length, + crc64 = BitConverter.ToUInt64(blockCrc, 0) + }; + + switch(_imageInfo.MediaType) + { + case MediaType.AppleSonySS: + case MediaType.AppleSonyDS: + subchannelBlock.sectorSize = 12; + + break; + case MediaType.AppleFileWare: + case MediaType.AppleProfile: + case MediaType.AppleWidget: + subchannelBlock.sectorSize = 20; + + break; + case MediaType.PriamDataTower: + subchannelBlock.sectorSize = 24; + + break; + } + + byte[] lzmaProperties = null; + + if(!_compress) + { + subchannelBlock.compression = CompressionType.None; + subchannelBlock.cmpCrc64 = subchannelBlock.crc64; + subchannelBlock.cmpLength = subchannelBlock.length; + blockStream = new MemoryStream(_sectorSubchannel); + } + else + { + var cmpBuffer = new byte[_sectorSubchannel.Length + 262144]; + + int cmpLen = _compressionAlgorithm switch + { + CompressionType.Lzma => LZMA.EncodeBuffer(_sectorSubchannel, cmpBuffer, + out lzmaProperties, 9, _dictionarySize, 4, 0, 2, 273), + _ => throw new ArgumentOutOfRangeException() + }; + + blockStream = new MemoryStream(cmpBuffer, 0, cmpLen); + + var cmpCrc = new Crc64Context(); + + if(_compressionAlgorithm == CompressionType.Lzma) + cmpCrc.Update(lzmaProperties); + + cmpCrc.Update(blockStream.ToArray()); + blockCrc = cmpCrc.Final(); + subchannelBlock.cmpLength = (uint)blockStream.Length; + + if(_compressionAlgorithm == CompressionType.Lzma) + subchannelBlock.cmpLength += LZMA_PROPERTIES_LENGTH; + + subchannelBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0); + subchannelBlock.compression = _compressionAlgorithm; + } + + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref subchannelBlock); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + + if(subchannelBlock.compression == CompressionType.Lzma) + _imageStream.Write(lzmaProperties, 0, lzmaProperties.Length); + + _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); + + _index.RemoveAll(t => t.blockType == BlockType.DataBlock && t.dataType == tagType); + + _index.Add(idxEntry); + blockStream.Close(); + } + + break; } - /// - public bool SetGeometry(uint cylinders, uint heads, uint sectorsPerTrack) + // Write metadata if present + SetMetadataFromTags(); + var metadataBlock = new MetadataBlock(); + blockStream = new MemoryStream(); + blockStream.Write(new byte[Marshal.SizeOf()], 0, Marshal.SizeOf()); + byte[] tmpUtf16Le; + + if(_imageInfo.MediaSequence > 0 && + _imageInfo.LastMediaSequence > 0) { - if(!IsWriting) + metadataBlock.identifier = BlockType.MetadataBlock; + metadataBlock.mediaSequence = _imageInfo.MediaSequence; + metadataBlock.lastMediaSequence = _imageInfo.LastMediaSequence; + } + + if(!string.IsNullOrWhiteSpace(_imageInfo.Creator)) + { + tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.Creator); + metadataBlock.identifier = BlockType.MetadataBlock; + metadataBlock.creatorOffset = (uint)blockStream.Position; + metadataBlock.creatorLength = (uint)(tmpUtf16Le.Length + 2); + blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); + + blockStream.Write(new byte[] { - ErrorMessage = "Tried to write on a non-writable image"; + 0, 0 + }, 0, 2); + } - return false; - } + if(!string.IsNullOrWhiteSpace(_imageInfo.Comments)) + { + tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.Comments); + metadataBlock.identifier = BlockType.MetadataBlock; + metadataBlock.commentsOffset = (uint)blockStream.Position; + metadataBlock.commentsLength = (uint)(tmpUtf16Le.Length + 2); + blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - if(_imageInfo.XmlMediaType != XmlMediaType.BlockMedia) + blockStream.Write(new byte[] { - ErrorMessage = "Tried to set geometry on a media that doesn't support it"; + 0, 0 + }, 0, 2); + } - return false; - } + if(!string.IsNullOrWhiteSpace(_imageInfo.MediaTitle)) + { + tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.MediaTitle); + metadataBlock.identifier = BlockType.MetadataBlock; + metadataBlock.mediaTitleOffset = (uint)blockStream.Position; + metadataBlock.mediaTitleLength = (uint)(tmpUtf16Le.Length + 2); + blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); - _geometryBlock = new GeometryBlock + blockStream.Write(new byte[] { - identifier = BlockType.GeometryBlock, - cylinders = cylinders, - heads = heads, - sectorsPerTrack = sectorsPerTrack + 0, 0 + }, 0, 2); + } + + if(!string.IsNullOrWhiteSpace(_imageInfo.MediaManufacturer)) + { + tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.MediaManufacturer); + metadataBlock.identifier = BlockType.MetadataBlock; + metadataBlock.mediaManufacturerOffset = (uint)blockStream.Position; + metadataBlock.mediaManufacturerLength = (uint)(tmpUtf16Le.Length + 2); + blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); + + blockStream.Write(new byte[] + { + 0, 0 + }, 0, 2); + } + + if(!string.IsNullOrWhiteSpace(_imageInfo.MediaModel)) + { + tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.MediaModel); + metadataBlock.identifier = BlockType.MetadataBlock; + metadataBlock.mediaModelOffset = (uint)blockStream.Position; + metadataBlock.mediaModelLength = (uint)(tmpUtf16Le.Length + 2); + blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); + + blockStream.Write(new byte[] + { + 0, 0 + }, 0, 2); + } + + if(!string.IsNullOrWhiteSpace(_imageInfo.MediaSerialNumber)) + { + tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.MediaSerialNumber); + metadataBlock.identifier = BlockType.MetadataBlock; + metadataBlock.mediaSerialNumberOffset = (uint)blockStream.Position; + metadataBlock.mediaSerialNumberLength = (uint)(tmpUtf16Le.Length + 2); + blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); + + blockStream.Write(new byte[] + { + 0, 0 + }, 0, 2); + } + + if(!string.IsNullOrWhiteSpace(_imageInfo.MediaBarcode)) + { + tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.MediaBarcode); + metadataBlock.identifier = BlockType.MetadataBlock; + metadataBlock.mediaBarcodeOffset = (uint)blockStream.Position; + metadataBlock.mediaBarcodeLength = (uint)(tmpUtf16Le.Length + 2); + blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); + + blockStream.Write(new byte[] + { + 0, 0 + }, 0, 2); + } + + if(!string.IsNullOrWhiteSpace(_imageInfo.MediaPartNumber)) + { + tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.MediaPartNumber); + metadataBlock.identifier = BlockType.MetadataBlock; + metadataBlock.mediaPartNumberOffset = (uint)blockStream.Position; + metadataBlock.mediaPartNumberLength = (uint)(tmpUtf16Le.Length + 2); + blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); + + blockStream.Write(new byte[] + { + 0, 0 + }, 0, 2); + } + + if(!string.IsNullOrWhiteSpace(_imageInfo.DriveManufacturer)) + { + tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.DriveManufacturer); + metadataBlock.identifier = BlockType.MetadataBlock; + metadataBlock.driveManufacturerOffset = (uint)blockStream.Position; + metadataBlock.driveManufacturerLength = (uint)(tmpUtf16Le.Length + 2); + blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); + + blockStream.Write(new byte[] + { + 0, 0 + }, 0, 2); + } + + if(!string.IsNullOrWhiteSpace(_imageInfo.DriveModel)) + { + tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.DriveModel); + metadataBlock.identifier = BlockType.MetadataBlock; + metadataBlock.driveModelOffset = (uint)blockStream.Position; + metadataBlock.driveModelLength = (uint)(tmpUtf16Le.Length + 2); + blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); + + blockStream.Write(new byte[] + { + 0, 0 + }, 0, 2); + } + + if(!string.IsNullOrWhiteSpace(_imageInfo.DriveSerialNumber)) + { + tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.DriveSerialNumber); + metadataBlock.identifier = BlockType.MetadataBlock; + metadataBlock.driveSerialNumberOffset = (uint)blockStream.Position; + metadataBlock.driveSerialNumberLength = (uint)(tmpUtf16Le.Length + 2); + blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); + + blockStream.Write(new byte[] + { + 0, 0 + }, 0, 2); + } + + if(!string.IsNullOrWhiteSpace(_imageInfo.DriveFirmwareRevision)) + { + tmpUtf16Le = Encoding.Unicode.GetBytes(_imageInfo.DriveFirmwareRevision); + metadataBlock.identifier = BlockType.MetadataBlock; + metadataBlock.driveFirmwareRevisionOffset = (uint)blockStream.Position; + metadataBlock.driveFirmwareRevisionLength = (uint)(tmpUtf16Le.Length + 2); + blockStream.Write(tmpUtf16Le, 0, tmpUtf16Le.Length); + + blockStream.Write(new byte[] + { + 0, 0 + }, 0, 2); + } + + // Check if we set up any metadata earlier, then write its block + if(metadataBlock.identifier == BlockType.MetadataBlock) + { + AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing metadata to position {0}", _imageStream.Position); + + metadataBlock.blockSize = (uint)blockStream.Length; + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref metadataBlock); + blockStream.Position = 0; + blockStream.Write(_structureBytes, 0, _structureBytes.Length); + _index.RemoveAll(t => t.blockType == BlockType.MetadataBlock && t.dataType == DataType.NoData); + + _index.Add(new IndexEntry + { + blockType = BlockType.MetadataBlock, + dataType = DataType.NoData, + offset = (ulong)_imageStream.Position + }); + + _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); + blockStream.Close(); + } + + _header.indexOffset = (ulong)_imageStream.Position; + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing index to position {0}", _header.indexOffset); + + blockStream = new MemoryStream(); + + // Write index to memory + foreach(IndexEntry entry in _index) + { + _structureBytes = new byte[Marshal.SizeOf()]; + IndexEntry indexEntry = entry; + MemoryMarshal.Write(_structureBytes, ref indexEntry); + blockStream.Write(_structureBytes, 0, _structureBytes.Length); + } + + Crc64Context.Data(blockStream.ToArray(), out byte[] idxCrc); + + if(_index.Count > ushort.MaxValue) + { + _header.imageMajorVersion = AARUFMT_VERSION; + + var idxHeader = new IndexHeader2 + { + identifier = BlockType.Index2, + entries = (ulong)_index.Count, + crc64 = BitConverter.ToUInt64(idxCrc, 0) }; - ErrorMessage = ""; + // Write index header to disk + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref idxHeader); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + } + else + { + var idxHeader = new IndexHeader + { + identifier = BlockType.Index, + entries = (ushort)_index.Count, + crc64 = BitConverter.ToUInt64(idxCrc, 0) + }; - return true; + // Write index header to disk + _structureBytes = new byte[Marshal.SizeOf()]; + MemoryMarshal.Write(_structureBytes, ref idxHeader); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); } - /// - public bool WriteSectorTag(byte[] data, ulong sectorAddress, SectorTagType tag) + // Write index to disk + _imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length); + blockStream.Close(); + + AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing header"); + _header.lastWrittenTime = DateTime.UtcNow.ToFileTimeUtc(); + _imageStream.Position = 0; + _structurePointer = System.Runtime.InteropServices.Marshal.AllocHGlobal(Marshal.SizeOf()); + _structureBytes = new byte[Marshal.SizeOf()]; + System.Runtime.InteropServices.Marshal.StructureToPtr(_header, _structurePointer, true); + System.Runtime.InteropServices.Marshal.Copy(_structurePointer, _structureBytes, 0, _structureBytes.Length); + System.Runtime.InteropServices.Marshal.FreeHGlobal(_structurePointer); + _imageStream.Write(_structureBytes, 0, _structureBytes.Length); + + _imageStream.Flush(); + _imageStream.Close(); + GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true); + + IsWriting = false; + ErrorMessage = ""; + + return true; + } + + /// + public bool SetMetadata(ImageInfo metadata) + { + _imageInfo.Creator = metadata.Creator; + _imageInfo.Comments = metadata.Comments; + _imageInfo.MediaManufacturer = metadata.MediaManufacturer; + _imageInfo.MediaModel = metadata.MediaModel; + _imageInfo.MediaSerialNumber = metadata.MediaSerialNumber; + _imageInfo.MediaBarcode = metadata.MediaBarcode; + _imageInfo.MediaPartNumber = metadata.MediaPartNumber; + _imageInfo.MediaSequence = metadata.MediaSequence; + _imageInfo.LastMediaSequence = metadata.LastMediaSequence; + _imageInfo.DriveManufacturer = metadata.DriveManufacturer; + _imageInfo.DriveModel = metadata.DriveModel; + _imageInfo.DriveSerialNumber = metadata.DriveSerialNumber; + _imageInfo.DriveFirmwareRevision = metadata.DriveFirmwareRevision; + _imageInfo.MediaTitle = metadata.MediaTitle; + + return true; + } + + /// + public bool SetGeometry(uint cylinders, uint heads, uint sectorsPerTrack) + { + if(!IsWriting) { - if(!IsWriting) - { - ErrorMessage = "Tried to write on a non-writable image"; + ErrorMessage = "Tried to write on a non-writable image"; - return false; - } + return false; + } - if(sectorAddress >= _imageInfo.Sectors) - { - ErrorMessage = "Tried to write past image size"; + if(_imageInfo.XmlMediaType != XmlMediaType.BlockMedia) + { + ErrorMessage = "Tried to set geometry on a media that doesn't support it"; - return false; - } + return false; + } - Track track; + _geometryBlock = new GeometryBlock + { + identifier = BlockType.GeometryBlock, + cylinders = cylinders, + heads = heads, + sectorsPerTrack = sectorsPerTrack + }; - switch(tag) - { - case SectorTagType.CdTrackFlags: - case SectorTagType.CdTrackIsrc: - if(_imageInfo.XmlMediaType != XmlMediaType.OpticalDisc) - { - ErrorMessage = "Incorrect tag for disk type"; + ErrorMessage = ""; - return false; - } + return true; + } - track = Tracks.FirstOrDefault(trk => sectorAddress == trk.Sequence); + /// + public bool WriteSectorTag(byte[] data, ulong sectorAddress, SectorTagType tag) + { + if(!IsWriting) + { + ErrorMessage = "Tried to write on a non-writable image"; - if(track is null || - (track.Sequence == 0 && track.StartSector == 0 && track.EndSector == 0)) - { - ErrorMessage = $"Can't find track {sectorAddress}"; + return false; + } - return false; - } + if(sectorAddress >= _imageInfo.Sectors) + { + ErrorMessage = "Tried to write past image size"; - break; - case SectorTagType.CdSectorSubchannel: - if(_imageInfo.XmlMediaType != XmlMediaType.OpticalDisc) - { - ErrorMessage = "Incorrect tag for disk type"; + return false; + } - return false; - } + Track track; - track = Tracks.FirstOrDefault(trk => sectorAddress >= trk.StartSector && - sectorAddress <= trk.EndSector); - - if(track is { Sequence: 0, StartSector: 0, EndSector: 0 }) - track.Type = TrackType.Data; - - break; - } - - switch(tag) - { - case SectorTagType.CdTrackFlags: + switch(tag) + { + case SectorTagType.CdTrackFlags: + case SectorTagType.CdTrackIsrc: + if(_imageInfo.XmlMediaType != XmlMediaType.OpticalDisc) { - if(data.Length != 1) - { - ErrorMessage = "Incorrect data size for track flags"; - - return false; - } - - _trackFlags[(byte)sectorAddress] = data[0]; - - return true; - } - - case SectorTagType.CdTrackIsrc: - { - if(data != null) - _trackIsrcs[(byte)sectorAddress] = Encoding.UTF8.GetString(data); - - return true; - } - - case SectorTagType.CdSectorSubchannel: - { - if(data.Length != 96) - { - ErrorMessage = "Incorrect data size for subchannel"; - - return false; - } - - _sectorSubchannel ??= new byte[_imageInfo.Sectors * 96]; - - Array.Copy(data, 0, _sectorSubchannel, (int)(96 * sectorAddress), 96); - - return true; - } - - case SectorTagType.DvdCmi: - { - if(data.Length != 1) - { - ErrorMessage = "Incorrect data size for CMI"; - - return false; - } - - _sectorCpiMai ??= new byte[_imageInfo.Sectors * 6]; - - Array.Copy(data, 0, _sectorCpiMai, (int)(6 * sectorAddress), 1); - - return true; - } - case SectorTagType.DvdTitleKey: - { - if(data.Length != 5) - { - ErrorMessage = "Incorrect data size for title key"; - - return false; - } - - _sectorCpiMai ??= new byte[_imageInfo.Sectors * 6]; - - Array.Copy(data, 0, _sectorCpiMai, (int)(1 + (6 * sectorAddress)), 5); - - return true; - } - case SectorTagType.DvdTitleKeyDecrypted: - { - if(data.Length != 5) - { - ErrorMessage = "Incorrect data size for decrypted title key"; - - return false; - } - - _sectorDecryptedTitleKey ??= new byte[_imageInfo.Sectors * 5]; - - Array.Copy(data, 0, _sectorDecryptedTitleKey, (int)(5 * sectorAddress), 5); - - return true; - } - - default: - ErrorMessage = $"Don't know how to write sector tag type {tag}"; + ErrorMessage = "Incorrect tag for disk type"; return false; - } - } - - /// - public bool WriteSectorsTag(byte[] data, ulong sectorAddress, uint length, SectorTagType tag) - { - if(!IsWriting) - { - ErrorMessage = "Tried to write on a non-writable image"; - - return false; - } - - if(sectorAddress + length > _imageInfo.Sectors) - { - ErrorMessage = "Tried to write past image size"; - - return false; - } - - switch(tag) - { - case SectorTagType.CdTrackFlags: - case SectorTagType.CdTrackIsrc: return WriteSectorTag(data, sectorAddress, tag); - case SectorTagType.CdSectorSubchannel: - { - if(data.Length % 96 != 0) - { - ErrorMessage = "Incorrect data size for subchannel"; - - return false; - } - - _sectorSubchannel ??= new byte[_imageInfo.Sectors * 96]; - - if((sectorAddress * 96) + (length * 96) > (ulong)_sectorSubchannel.LongLength) - { - ErrorMessage = "Tried to write more data than possible"; - - return false; - } - - Array.Copy(data, 0, _sectorSubchannel, (int)(96 * sectorAddress), 96 * length); - - return true; } - default: - ErrorMessage = $"Don't know how to write sector tag type {tag}"; + track = Tracks.FirstOrDefault(trk => sectorAddress == trk.Sequence); + + if(track is null || + track.Sequence == 0 && track.StartSector == 0 && track.EndSector == 0) + { + ErrorMessage = $"Can't find track {sectorAddress}"; return false; + } + + break; + case SectorTagType.CdSectorSubchannel: + if(_imageInfo.XmlMediaType != XmlMediaType.OpticalDisc) + { + ErrorMessage = "Incorrect tag for disk type"; + + return false; + } + + track = Tracks.FirstOrDefault(trk => sectorAddress >= trk.StartSector && + sectorAddress <= trk.EndSector); + + if(track is { Sequence: 0, StartSector: 0, EndSector: 0 }) + track.Type = TrackType.Data; + + break; + } + + switch(tag) + { + case SectorTagType.CdTrackFlags: + { + if(data.Length != 1) + { + ErrorMessage = "Incorrect data size for track flags"; + + return false; + } + + _trackFlags[(byte)sectorAddress] = data[0]; + + return true; } - } - /// - public bool SetDumpHardware(List dumpHardware) - { - DumpHardware = dumpHardware; + case SectorTagType.CdTrackIsrc: + { + if(data != null) + _trackIsrcs[(byte)sectorAddress] = Encoding.UTF8.GetString(data); - return true; - } + return true; + } - /// - public bool SetCicmMetadata(CICMMetadataType metadata) - { - CicmMetadata = metadata; + case SectorTagType.CdSectorSubchannel: + { + if(data.Length != 96) + { + ErrorMessage = "Incorrect data size for subchannel"; - return true; + return false; + } + + _sectorSubchannel ??= new byte[_imageInfo.Sectors * 96]; + + Array.Copy(data, 0, _sectorSubchannel, (int)(96 * sectorAddress), 96); + + return true; + } + + case SectorTagType.DvdCmi: + { + if(data.Length != 1) + { + ErrorMessage = "Incorrect data size for CMI"; + + return false; + } + + _sectorCpiMai ??= new byte[_imageInfo.Sectors * 6]; + + Array.Copy(data, 0, _sectorCpiMai, (int)(6 * sectorAddress), 1); + + return true; + } + case SectorTagType.DvdTitleKey: + { + if(data.Length != 5) + { + ErrorMessage = "Incorrect data size for title key"; + + return false; + } + + _sectorCpiMai ??= new byte[_imageInfo.Sectors * 6]; + + Array.Copy(data, 0, _sectorCpiMai, (int)(1 + 6 * sectorAddress), 5); + + return true; + } + case SectorTagType.DvdTitleKeyDecrypted: + { + if(data.Length != 5) + { + ErrorMessage = "Incorrect data size for decrypted title key"; + + return false; + } + + _sectorDecryptedTitleKey ??= new byte[_imageInfo.Sectors * 5]; + + Array.Copy(data, 0, _sectorDecryptedTitleKey, (int)(5 * sectorAddress), 5); + + return true; + } + + default: + ErrorMessage = $"Don't know how to write sector tag type {tag}"; + + return false; } } + + /// + public bool WriteSectorsTag(byte[] data, ulong sectorAddress, uint length, SectorTagType tag) + { + if(!IsWriting) + { + ErrorMessage = "Tried to write on a non-writable image"; + + return false; + } + + if(sectorAddress + length > _imageInfo.Sectors) + { + ErrorMessage = "Tried to write past image size"; + + return false; + } + + switch(tag) + { + case SectorTagType.CdTrackFlags: + case SectorTagType.CdTrackIsrc: return WriteSectorTag(data, sectorAddress, tag); + case SectorTagType.CdSectorSubchannel: + { + if(data.Length % 96 != 0) + { + ErrorMessage = "Incorrect data size for subchannel"; + + return false; + } + + _sectorSubchannel ??= new byte[_imageInfo.Sectors * 96]; + + if(sectorAddress * 96 + length * 96 > (ulong)_sectorSubchannel.LongLength) + { + ErrorMessage = "Tried to write more data than possible"; + + return false; + } + + Array.Copy(data, 0, _sectorSubchannel, (int)(96 * sectorAddress), 96 * length); + + return true; + } + + default: + ErrorMessage = $"Don't know how to write sector tag type {tag}"; + + return false; + } + } + + /// + public bool SetDumpHardware(List dumpHardware) + { + DumpHardware = dumpHardware; + + return true; + } + + /// + public bool SetCicmMetadata(CICMMetadataType metadata) + { + CicmMetadata = metadata; + + return true; + } } \ No newline at end of file diff --git a/Aaru.Images/Alcohol120/Read.cs b/Aaru.Images/Alcohol120/Read.cs index 0340c0c76..56eff102a 100644 --- a/Aaru.Images/Alcohol120/Read.cs +++ b/Aaru.Images/Alcohol120/Read.cs @@ -150,8 +150,7 @@ public sealed partial class Alcohol120 stream.Read(trkHdr, 0, 80); Track track = Marshal.ByteArrayToStructureLittleEndian(trkHdr); - if(track.mode == TrackMode.Mode2F1Alt || - track.mode == TrackMode.Mode2F1Alt) + if(track.mode is TrackMode.Mode2F1Alt or TrackMode.Mode2F1Alt) oldIncorrectImage = true; // Solve our own mistake here, sorry, but anyway seems Alcohol doesn't support DDCD @@ -495,20 +494,17 @@ public sealed partial class Alcohol120 foreach(Track alcoholTrack in _alcTracks.Values) { // First track is audio - firstAudio |= alcoholTrack.point == 1 && - (alcoholTrack.mode == TrackMode.Audio || alcoholTrack.mode == TrackMode.AudioAlt); + firstAudio |= alcoholTrack.point == 1 && alcoholTrack.mode is TrackMode.Audio or TrackMode.AudioAlt; // First track is data firstData |= alcoholTrack.point == 1 && - (alcoholTrack.mode != TrackMode.Audio || alcoholTrack.mode != TrackMode.AudioAlt); + alcoholTrack.mode is not (TrackMode.Audio and TrackMode.AudioAlt); // Any non first track is data - data |= alcoholTrack.point != 1 && - (alcoholTrack.mode != TrackMode.Audio || alcoholTrack.mode != TrackMode.AudioAlt); + data |= alcoholTrack.point != 1 && alcoholTrack.mode is not (TrackMode.Audio and TrackMode.AudioAlt); // Any non first track is audio - audio |= alcoholTrack.point != 1 && - (alcoholTrack.mode == TrackMode.Audio || alcoholTrack.mode == TrackMode.AudioAlt); + audio |= alcoholTrack.point != 1 && alcoholTrack.mode is TrackMode.Audio or TrackMode.AudioAlt; switch(alcoholTrack.mode) { @@ -726,9 +722,7 @@ public sealed partial class Alcohol120 } if(_imageInfo.MediaType == MediaType.XGD2) - if(_imageInfo.Sectors == 25063 || // Locked (or non compatible drive) - _imageInfo.Sectors == 4229664 || // Xtreme unlock - _imageInfo.Sectors == 4246304) // Wxripper unlock + if(_imageInfo.Sectors is 25063 or 4229664 or 4246304) // Wxripper unlock _imageInfo.MediaType = MediaType.XGD3; AaruConsole.VerboseWriteLine("Alcohol 120% image describes a disc of type {0}", _imageInfo.MediaType); diff --git a/Aaru.Images/Alcohol120/Write.cs b/Aaru.Images/Alcohol120/Write.cs index 5fc04d95e..be4d3686e 100644 --- a/Aaru.Images/Alcohol120/Write.cs +++ b/Aaru.Images/Alcohol120/Write.cs @@ -685,9 +685,9 @@ public sealed partial class Alcohol120 unknown2 = new byte[24], psec = (byte)(_imageInfo.MediaType == MediaType.CDI ? 0x10 - : _writingTracks.Any(t => t.Type == TrackType.CdMode2Form1 || - t.Type == TrackType.CdMode2Form2 || - t.Type == TrackType.CdMode2Formless) + : _writingTracks.Any(t => t.Type is TrackType.CdMode2Form1 + or TrackType.CdMode2Form2 + or TrackType.CdMode2Formless) ? 0x20 : 0), extraOffset = (uint)currentExtraOffset diff --git a/Aaru.Images/Anex86/Write.cs b/Aaru.Images/Anex86/Write.cs index f14797bbf..bb4ba8f1a 100644 --- a/Aaru.Images/Anex86/Write.cs +++ b/Aaru.Images/Anex86/Write.cs @@ -199,11 +199,9 @@ public sealed partial class Anex86 return false; } - if((_imageInfo.MediaType == MediaType.Unknown || _imageInfo.MediaType == MediaType.GENERIC_HDD || - _imageInfo.MediaType == MediaType.FlashDrive || _imageInfo.MediaType == MediaType.CompactFlash || - _imageInfo.MediaType == MediaType.CompactFlashType2 || _imageInfo.MediaType == MediaType.PCCardTypeI || - _imageInfo.MediaType == MediaType.PCCardTypeII || _imageInfo.MediaType == MediaType.PCCardTypeIII || - _imageInfo.MediaType == MediaType.PCCardTypeIV) && + if(_imageInfo.MediaType is MediaType.Unknown or MediaType.GENERIC_HDD or MediaType.FlashDrive + or MediaType.CompactFlash or MediaType.CompactFlashType2 or MediaType.PCCardTypeI + or MediaType.PCCardTypeII or MediaType.PCCardTypeIII or MediaType.PCCardTypeIV && _header.cylinders == 0) { _header.cylinders = (int)(_imageInfo.Sectors / 8 / 33); diff --git a/Aaru.Images/AppleDOS/Identify.cs b/Aaru.Images/AppleDOS/Identify.cs index 61d59fa43..de0e3cc1c 100644 --- a/Aaru.Images/AppleDOS/Identify.cs +++ b/Aaru.Images/AppleDOS/Identify.cs @@ -42,6 +42,6 @@ public sealed partial class AppleDos { _extension = Path.GetExtension(imageFilter.Filename)?.ToLower(); - return imageFilter.DataForkLength == 143360 && (_extension == ".po" || _extension == ".do"); + return imageFilter.DataForkLength == 143360 && _extension is ".po" or ".do"; } } \ No newline at end of file diff --git a/Aaru.Images/AppleDOS/Read.cs b/Aaru.Images/AppleDOS/Read.cs index 6282f83a9..f4c6ec568 100644 --- a/Aaru.Images/AppleDOS/Read.cs +++ b/Aaru.Images/AppleDOS/Read.cs @@ -51,7 +51,7 @@ public sealed partial class AppleDos _extension = Path.GetExtension(imageFilter.Filename)?.ToLower(); - if((_extension == ".d13" || _extension == ".do") && + if(_extension is ".d13" or ".do" && tmp.Length == 116480) { _dos32 = true; diff --git a/Aaru.Images/BlindWrite5/Read.cs b/Aaru.Images/BlindWrite5/Read.cs index 4e9cda78e..c643f82a7 100644 --- a/Aaru.Images/BlindWrite5/Read.cs +++ b/Aaru.Images/BlindWrite5/Read.cs @@ -343,8 +343,7 @@ public sealed partial class BlindWrite5 stream.Read(trk, 0, 72); session.Tracks[tSeq] = Marshal.ByteArrayToStructureLittleEndian(trk); - if(session.Tracks[tSeq].type == TrackType.Dvd || - session.Tracks[tSeq].type == TrackType.NotData) + if(session.Tracks[tSeq].type is TrackType.Dvd or TrackType.NotData) { session.Tracks[tSeq].unknown9[0] = 0; session.Tracks[tSeq].unknown9[1] = 0; @@ -426,8 +425,7 @@ public sealed partial class BlindWrite5 AaruConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].unknown8 = 0x{2:X4}", ses, tSeq, session.Tracks[tSeq].unknown8); - if(session.Tracks[tSeq].type == TrackType.Dvd || - session.Tracks[tSeq].type == TrackType.NotData) + if(session.Tracks[tSeq].type is TrackType.Dvd or TrackType.NotData) continue; { @@ -1173,8 +1171,7 @@ public sealed partial class BlindWrite5 _imageInfo.MediaType = MediaType.XGD2; } } - else if(_imageInfo.MediaType == MediaType.CD || - _imageInfo.MediaType == MediaType.CDROM) + else if(_imageInfo.MediaType is MediaType.CD or MediaType.CDROM) { var data = false; var mode2 = false; @@ -1271,9 +1268,7 @@ public sealed partial class BlindWrite5 var isBd = false; - if(_imageInfo.MediaType == MediaType.BDR || - _imageInfo.MediaType == MediaType.BDRE || - _imageInfo.MediaType == MediaType.BDROM) + if(_imageInfo.MediaType is MediaType.BDR or MediaType.BDRE or MediaType.BDROM) { isDvd = false; isBd = true; @@ -1334,9 +1329,7 @@ public sealed partial class BlindWrite5 _imageInfo.ReadableMediaTags.Add(MediaTagType.CD_FullTOC); if(_imageInfo.MediaType == MediaType.XGD2) - if(_imageInfo.Sectors == 25063 || // Locked (or non compatible drive) - _imageInfo.Sectors == 4229664 || // Xtreme unlock - _imageInfo.Sectors == 4246304) // Wxripper unlock + if(_imageInfo.Sectors is 25063 or 4229664 or 4246304) // Wxripper unlock _imageInfo.MediaType = MediaType.XGD3; AaruConsole.VerboseWriteLine("BlindWrite image describes a disc of type {0}", _imageInfo.MediaType); diff --git a/Aaru.Images/CDRDAO/Read.cs b/Aaru.Images/CDRDAO/Read.cs index 4654f94ae..12ef9fabb 100644 --- a/Aaru.Images/CDRDAO/Read.cs +++ b/Aaru.Images/CDRDAO/Read.cs @@ -1097,8 +1097,7 @@ public sealed partial class Cdrdao { buffer = null; - if(tag == SectorTagType.CdTrackFlags || - tag == SectorTagType.CdTrackIsrc) + if(tag is SectorTagType.CdTrackFlags or SectorTagType.CdTrackIsrc) track = (uint)sectorAddress; var aaruTrack = new CdrdaoTrack diff --git a/Aaru.Images/CDRDAO/Write.cs b/Aaru.Images/CDRDAO/Write.cs index 267c5189b..99b6e6557 100644 --- a/Aaru.Images/CDRDAO/Write.cs +++ b/Aaru.Images/CDRDAO/Write.cs @@ -461,8 +461,7 @@ public sealed partial class Cdrdao foreach(Track track in tracks.OrderBy(t => t.Sequence)) { - if(track.SubchannelType == TrackSubchannelType.Q16 || - track.SubchannelType == TrackSubchannelType.Q16Interleaved) + if(track.SubchannelType is TrackSubchannelType.Q16 or TrackSubchannelType.Q16Interleaved) { ErrorMessage = $"Unsupported subchannel type {track.SubchannelType} for track {track.Sequence}"; @@ -526,8 +525,9 @@ public sealed partial class Cdrdao bool data = _writingTracks.Count(t => t.Type != TrackType.Audio) > 0; - bool mode2 = _writingTracks.Count(t => t.Type == TrackType.CdMode2Form1 || t.Type == TrackType.CdMode2Form2 || - t.Type == TrackType.CdMode2Formless) > 0; + bool mode2 = + _writingTracks.Count(t => t.Type is TrackType.CdMode2Form1 or TrackType.CdMode2Form2 + or TrackType.CdMode2Formless) > 0; if(mode2) _descriptorStream.WriteLine("CD_ROM_XA"); diff --git a/Aaru.Images/CDRWin/Read.cs b/Aaru.Images/CDRWin/Read.cs index 2fe3732cc..37d4be426 100644 --- a/Aaru.Images/CDRWin/Read.cs +++ b/Aaru.Images/CDRWin/Read.cs @@ -1071,8 +1071,7 @@ public sealed partial class CdrWin else if(_discImage.MediaType == MediaType.Unknown) _discImage.MediaType = CdrWinIsoBusterDiscTypeToMediaType(_discImage.OriginalMediaType); - if(_discImage.MediaType == MediaType.Unknown || - _discImage.MediaType == MediaType.CD) + if(_discImage.MediaType is MediaType.Unknown or MediaType.CD) { var data = false; var cdg = false; @@ -1553,8 +1552,8 @@ public sealed partial class CdrWin var mediaTypeAsInt = (int)_discImage.MediaType; - _isCd = mediaTypeAsInt >= 10 && mediaTypeAsInt <= 39 || mediaTypeAsInt == 112 || mediaTypeAsInt == 113 || - mediaTypeAsInt >= 150 && mediaTypeAsInt <= 152 || mediaTypeAsInt == 154 || mediaTypeAsInt == 155 || + _isCd = mediaTypeAsInt >= 10 && mediaTypeAsInt <= 39 || mediaTypeAsInt is 112 or 113 || + mediaTypeAsInt >= 150 && mediaTypeAsInt <= 152 || mediaTypeAsInt is 154 or 155 || mediaTypeAsInt >= 171 && mediaTypeAsInt <= 179 || mediaTypeAsInt >= 740 && mediaTypeAsInt <= 749; if(currentSession > 1 && @@ -1670,8 +1669,7 @@ public sealed partial class CdrWin { buffer = null; - if(tag == SectorTagType.CdTrackFlags || - tag == SectorTagType.CdTrackIsrc) + if(tag is SectorTagType.CdTrackFlags or SectorTagType.CdTrackIsrc) return ReadSectorsTag(sectorAddress, length, 0, tag, out buffer); foreach(KeyValuePair kvp in from kvp in _offsetMap where sectorAddress >= kvp.Value @@ -1863,8 +1861,7 @@ public sealed partial class CdrWin { buffer = null; - if(tag == SectorTagType.CdTrackFlags || - tag == SectorTagType.CdTrackIsrc) + if(tag is SectorTagType.CdTrackFlags or SectorTagType.CdTrackIsrc) track = (uint)sectorAddress; CdrWinTrack? aaruTrack = _discImage.Tracks.FirstOrDefault(cdrwinTrack => cdrwinTrack.Sequence == track); diff --git a/Aaru.Images/CDRWin/Write.cs b/Aaru.Images/CDRWin/Write.cs index 733431d29..27096d9d7 100644 --- a/Aaru.Images/CDRWin/Write.cs +++ b/Aaru.Images/CDRWin/Write.cs @@ -107,8 +107,8 @@ public sealed partial class CdrWin var mediaTypeAsInt = (int)_discImage.MediaType; - _isCd = mediaTypeAsInt >= 10 && mediaTypeAsInt <= 39 || mediaTypeAsInt == 112 || mediaTypeAsInt == 113 || - mediaTypeAsInt >= 150 && mediaTypeAsInt <= 152 || mediaTypeAsInt == 154 || mediaTypeAsInt == 155 || + _isCd = mediaTypeAsInt >= 10 && mediaTypeAsInt <= 39 || mediaTypeAsInt is 112 or 113 || + mediaTypeAsInt >= 150 && mediaTypeAsInt <= 152 || mediaTypeAsInt is 154 or 155 || mediaTypeAsInt >= 171 && mediaTypeAsInt <= 179 || mediaTypeAsInt >= 740 && mediaTypeAsInt <= 749; if(_isCd) diff --git a/Aaru.Images/CisCopy/Read.cs b/Aaru.Images/CisCopy/Read.cs index ee5f19195..2e43b3c0b 100644 --- a/Aaru.Images/CisCopy/Read.cs +++ b/Aaru.Images/CisCopy/Read.cs @@ -111,8 +111,7 @@ public sealed partial class CisCopy var headStep = 1; - if(type == DiskType.MD1DD || - type == DiskType.MD1DD8) + if(type is DiskType.MD1DD or DiskType.MD1DD8) headStep = 2; var decodedImage = new MemoryStream(); diff --git a/Aaru.Images/CisCopy/Write.cs b/Aaru.Images/CisCopy/Write.cs index 40ac7de6a..eb2579afc 100644 --- a/Aaru.Images/CisCopy/Write.cs +++ b/Aaru.Images/CisCopy/Write.cs @@ -139,8 +139,7 @@ public sealed partial class CisCopy var headStep = 1; - if(diskType == DiskType.MD1DD || - diskType == DiskType.MD1DD8) + if(diskType is DiskType.MD1DD or DiskType.MD1DD8) headStep = 2; for(var i = 0; i < tracks; i += headStep) diff --git a/Aaru.Images/CopyQM/Read.cs b/Aaru.Images/CopyQM/Read.cs index 64d360f63..beb5b2fd1 100644 --- a/Aaru.Images/CopyQM/Read.cs +++ b/Aaru.Images/CopyQM/Read.cs @@ -163,15 +163,15 @@ public sealed partial class CopyQm switch(_imageInfo.MediaType) { - case MediaType.NEC_525_HD when _header.drive == COPYQM_35_HD || _header.drive == COPYQM_35_ED: + case MediaType.NEC_525_HD when _header.drive is COPYQM_35_HD or COPYQM_35_ED: _imageInfo.MediaType = MediaType.NEC_35_HD_8; break; - case MediaType.DOS_525_HD when _header.drive == COPYQM_35_HD || _header.drive == COPYQM_35_ED: + case MediaType.DOS_525_HD when _header.drive is COPYQM_35_HD or COPYQM_35_ED: _imageInfo.MediaType = MediaType.NEC_35_HD_15; break; - case MediaType.RX50 when _header.drive == COPYQM_525_DD || _header.drive == COPYQM_525_HD: + case MediaType.RX50 when _header.drive is COPYQM_525_DD or COPYQM_525_HD: _imageInfo.MediaType = MediaType.ATARI_35_SS_DD; break; diff --git a/Aaru.Images/DART/Read.cs b/Aaru.Images/DART/Read.cs index 62a16f417..c2437fd8c 100644 --- a/Aaru.Images/DART/Read.cs +++ b/Aaru.Images/DART/Read.cs @@ -111,8 +111,7 @@ public sealed partial class Dart short[] bLength; - if(header.srcType == DISK_MAC_HD || - header.srcType == DISK_DOS_HD) + if(header.srcType is DISK_MAC_HD or DISK_DOS_HD) bLength = new short[BLOCK_ARRAY_LEN_HIGH]; else bLength = new short[BLOCK_ARRAY_LEN_LOW]; @@ -167,9 +166,7 @@ public sealed partial class Dart _dataCache = dataMs.ToArray(); - if(header.srcType == DISK_LISA || - header.srcType == DISK_MAC || - header.srcType == DISK_APPLE2) + if(header.srcType is DISK_LISA or DISK_MAC or DISK_APPLE2) { _imageInfo.ReadableSectorTags.Add(SectorTagType.AppleSectorTag); _tagCache = tagMs.ToArray(); diff --git a/Aaru.Images/DiscFerret/Identify.cs b/Aaru.Images/DiscFerret/Identify.cs index 84b2277f5..c55ca05e4 100644 --- a/Aaru.Images/DiscFerret/Identify.cs +++ b/Aaru.Images/DiscFerret/Identify.cs @@ -46,6 +46,6 @@ public sealed partial class DiscFerret stream.Read(magicB, 0, 4); var magic = BitConverter.ToUInt32(magicB, 0); - return magic == DFI_MAGIC || magic == DFI_MAGIC2; + return magic is DFI_MAGIC or DFI_MAGIC2; } } \ No newline at end of file diff --git a/Aaru.Images/DiskDupe/Helpers.cs b/Aaru.Images/DiskDupe/Helpers.cs index 43ace6d37..d918e2912 100644 --- a/Aaru.Images/DiskDupe/Helpers.cs +++ b/Aaru.Images/DiskDupe/Helpers.cs @@ -64,8 +64,7 @@ public sealed partial class DiskDupe // read and check disk type byte fHeader.diskType = (byte)stream.ReadByte(); - if(fHeader.diskType < 1 || - fHeader.diskType > 4) + if(fHeader.diskType is < 1 or > 4) return false; // seek to start of the trackmap diff --git a/Aaru.Images/DriDiskCopy/Read.cs b/Aaru.Images/DriDiskCopy/Read.cs index f5369ac16..e33769d6b 100644 --- a/Aaru.Images/DriDiskCopy/Read.cs +++ b/Aaru.Images/DriDiskCopy/Read.cs @@ -91,7 +91,7 @@ public sealed partial class DriDiskCopy _imageInfo.Heads == 2 && _imageInfo.SectorsPerTrack == 16 && _imageInfo.SectorSize == 512 && - (_footer.bpb._driveCode == DriveCode.md2hd || _footer.bpb._driveCode == DriveCode.mf2hd)) + _footer.bpb._driveCode is DriveCode.md2hd or DriveCode.mf2hd) { _imageInfo.SectorsPerTrack = 8; _imageInfo.SectorSize = 1024; @@ -103,18 +103,15 @@ public sealed partial class DriDiskCopy switch(_imageInfo.MediaType) { - case MediaType.NEC_525_HD when _footer.bpb._driveCode == DriveCode.mf2hd || - _footer.bpb._driveCode == DriveCode.mf2ed: + case MediaType.NEC_525_HD when _footer.bpb._driveCode is DriveCode.mf2hd or DriveCode.mf2ed: _imageInfo.MediaType = MediaType.NEC_35_HD_8; break; - case MediaType.DOS_525_HD when _footer.bpb._driveCode == DriveCode.mf2hd || - _footer.bpb._driveCode == DriveCode.mf2ed: + case MediaType.DOS_525_HD when _footer.bpb._driveCode is DriveCode.mf2hd or DriveCode.mf2ed: _imageInfo.MediaType = MediaType.NEC_35_HD_15; break; - case MediaType.RX50 when _footer.bpb._driveCode == DriveCode.md2dd || - _footer.bpb._driveCode == DriveCode.md2hd: + case MediaType.RX50 when _footer.bpb._driveCode is DriveCode.md2dd or DriveCode.md2hd: _imageInfo.MediaType = MediaType.ATARI_35_SS_DD; break; diff --git a/Aaru.Images/HDCopy/Helpers.cs b/Aaru.Images/HDCopy/Helpers.cs index 16e8f8a03..939db51e5 100644 --- a/Aaru.Images/HDCopy/Helpers.cs +++ b/Aaru.Images/HDCopy/Helpers.cs @@ -74,12 +74,10 @@ public sealed partial class HdCopy * We know the image is from a DOS floppy disk, so assume * some sane cylinder and sectors-per-track count. */ - if(fheader.sectorsPerTrack < 8 || - fheader.sectorsPerTrack > 40) + if(fheader.sectorsPerTrack is < 8 or > 40) return false; - if(fheader.lastCylinder < 37 || - fheader.lastCylinder >= 84) + if(fheader.lastCylinder is < 37 or >= 84) return false; // Validate the trackmap. First two tracks need to be present diff --git a/Aaru.Images/IMD/Read.cs b/Aaru.Images/IMD/Read.cs index dbdaa7e3d..200ce1967 100644 --- a/Aaru.Images/IMD/Read.cs +++ b/Aaru.Images/IMD/Read.cs @@ -183,9 +183,7 @@ public sealed partial class Imd MediaEncoding mediaEncoding = MediaEncoding.MFM; - if(mode == TransferRate.TwoHundred || - mode == TransferRate.ThreeHundred || - mode == TransferRate.FiveHundred) + if(mode is TransferRate.TwoHundred or TransferRate.ThreeHundred or TransferRate.FiveHundred) mediaEncoding = MediaEncoding.FM; _imageInfo.MediaType = Geometry.GetMediaType(((ushort)_imageInfo.Cylinders, (byte)_imageInfo.Heads, diff --git a/Aaru.Images/MaxiDisk/Identify.cs b/Aaru.Images/MaxiDisk/Identify.cs index 0a3773291..31bd006d7 100644 --- a/Aaru.Images/MaxiDisk/Identify.cs +++ b/Aaru.Images/MaxiDisk/Identify.cs @@ -70,8 +70,7 @@ public sealed partial class MaxiDisk // return false; // Only floppies supported - if(tmpHeader.heads == 0 || - tmpHeader.heads > 2) + if(tmpHeader.heads is 0 or > 2) return false; // No floppies with more than this? diff --git a/Aaru.Images/MaxiDisk/Read.cs b/Aaru.Images/MaxiDisk/Read.cs index 1b125e44a..552127429 100644 --- a/Aaru.Images/MaxiDisk/Read.cs +++ b/Aaru.Images/MaxiDisk/Read.cs @@ -60,8 +60,7 @@ public sealed partial class MaxiDisk // return false; // Only floppies supported - if(tmpHeader.heads == 0 || - tmpHeader.heads > 2) + if(tmpHeader.heads is 0 or > 2) return ErrorNumber.InvalidArgument; // No floppies with more than this? diff --git a/Aaru.Images/Nero/Read.cs b/Aaru.Images/Nero/Read.cs index be410380f..76d960ade 100644 --- a/Aaru.Images/Nero/Read.cs +++ b/Aaru.Images/Nero/Read.cs @@ -302,8 +302,7 @@ public sealed partial class Nero corruptedTrackMode = true; entry.Mode = 0x0005; } - else if(entry.Mode == 0x0002 || - entry.Mode == 0x0003) + else if(entry.Mode is 0x0002 or 0x0003) { corruptedTrackMode = true; entry.Mode = 0x0006; @@ -418,8 +417,7 @@ public sealed partial class Nero corruptedTrackMode = true; entry.Mode = 0x0005; } - else if(entry.Mode == 0x0002 || - entry.Mode == 0x0003) + else if(entry.Mode is 0x0002 or 0x0003) { corruptedTrackMode = true; entry.Mode = 0x0006; @@ -935,7 +933,7 @@ public sealed partial class Nero AaruConsole.DebugWriteLine("Nero plugin", "Building offset, track and session maps"); - bool onlyOneSession = currentSession == 1 || currentSession == 2; + bool onlyOneSession = currentSession is 1 or 2; currentSession = 1; _neroSessions.TryGetValue(1, out uint currentSessionMaxTrack); uint currentSessionCurrentTrack = 1; @@ -1425,8 +1423,7 @@ public sealed partial class Nero _neroFilter = imageFilter; - if(_imageInfo.MediaType == CommonTypes.MediaType.Unknown || - _imageInfo.MediaType == CommonTypes.MediaType.CD) + if(_imageInfo.MediaType is CommonTypes.MediaType.Unknown or CommonTypes.MediaType.CD) { var data = false; var mode2 = false; @@ -1489,46 +1486,45 @@ public sealed partial class Nero _sectorBuilder = new SectorBuilder(); - _isCd = _imageInfo.MediaType == CommonTypes.MediaType.CD || - _imageInfo.MediaType == CommonTypes.MediaType.CDDA || - _imageInfo.MediaType == CommonTypes.MediaType.CDG || - _imageInfo.MediaType == CommonTypes.MediaType.CDEG || - _imageInfo.MediaType == CommonTypes.MediaType.CDI || - _imageInfo.MediaType == CommonTypes.MediaType.CDROM || - _imageInfo.MediaType == CommonTypes.MediaType.CDROMXA || - _imageInfo.MediaType == CommonTypes.MediaType.CDPLUS || - _imageInfo.MediaType == CommonTypes.MediaType.CDMO || - _imageInfo.MediaType == CommonTypes.MediaType.CDR || - _imageInfo.MediaType == CommonTypes.MediaType.CDRW || - _imageInfo.MediaType == CommonTypes.MediaType.CDMRW || - _imageInfo.MediaType == CommonTypes.MediaType.VCD || - _imageInfo.MediaType == CommonTypes.MediaType.SVCD || - _imageInfo.MediaType == CommonTypes.MediaType.PCD || - _imageInfo.MediaType == CommonTypes.MediaType.DTSCD || - _imageInfo.MediaType == CommonTypes.MediaType.CDMIDI || - _imageInfo.MediaType == CommonTypes.MediaType.CDV || - _imageInfo.MediaType == CommonTypes.MediaType.CDIREADY || - _imageInfo.MediaType == CommonTypes.MediaType.FMTOWNS || - _imageInfo.MediaType == CommonTypes.MediaType.PS1CD || - _imageInfo.MediaType == CommonTypes.MediaType.PS2CD || - _imageInfo.MediaType == CommonTypes.MediaType.MEGACD || - _imageInfo.MediaType == CommonTypes.MediaType.SATURNCD || - _imageInfo.MediaType == CommonTypes.MediaType.GDROM || - _imageInfo.MediaType == CommonTypes.MediaType.GDR || - _imageInfo.MediaType == CommonTypes.MediaType.MilCD || - _imageInfo.MediaType == CommonTypes.MediaType.SuperCDROM2 || - _imageInfo.MediaType == CommonTypes.MediaType.JaguarCD || - _imageInfo.MediaType == CommonTypes.MediaType.ThreeDO || - _imageInfo.MediaType == CommonTypes.MediaType.PCFX || - _imageInfo.MediaType == CommonTypes.MediaType.NeoGeoCD || - _imageInfo.MediaType == CommonTypes.MediaType.CDTV || - _imageInfo.MediaType == CommonTypes.MediaType.CD32 || - _imageInfo.MediaType == CommonTypes.MediaType.Playdia || - _imageInfo.MediaType == CommonTypes.MediaType.Pippin || - _imageInfo.MediaType == CommonTypes.MediaType.VideoNow || - _imageInfo.MediaType == CommonTypes.MediaType.VideoNowColor || - _imageInfo.MediaType == CommonTypes.MediaType.VideoNowXp || - _imageInfo.MediaType == CommonTypes.MediaType.CVD; + _isCd = _imageInfo.MediaType is CommonTypes.MediaType.CD or CommonTypes.MediaType.CDDA + or CommonTypes.MediaType.CDG + or CommonTypes.MediaType.CDEG + or CommonTypes.MediaType.CDI + or CommonTypes.MediaType.CDROM + or CommonTypes.MediaType.CDROMXA + or CommonTypes.MediaType.CDPLUS + or CommonTypes.MediaType.CDMO + or CommonTypes.MediaType.CDR + or CommonTypes.MediaType.CDRW + or CommonTypes.MediaType.CDMRW + or CommonTypes.MediaType.VCD + or CommonTypes.MediaType.SVCD + or CommonTypes.MediaType.PCD + or CommonTypes.MediaType.DTSCD + or CommonTypes.MediaType.CDMIDI + or CommonTypes.MediaType.CDV + or CommonTypes.MediaType.CDIREADY + or CommonTypes.MediaType.FMTOWNS + or CommonTypes.MediaType.PS1CD + or CommonTypes.MediaType.PS2CD + or CommonTypes.MediaType.MEGACD + or CommonTypes.MediaType.SATURNCD + or CommonTypes.MediaType.GDROM + or CommonTypes.MediaType.GDR + or CommonTypes.MediaType.MilCD + or CommonTypes.MediaType.SuperCDROM2 + or CommonTypes.MediaType.JaguarCD + or CommonTypes.MediaType.ThreeDO + or CommonTypes.MediaType.PCFX + or CommonTypes.MediaType.NeoGeoCD + or CommonTypes.MediaType.CDTV + or CommonTypes.MediaType.CD32 + or CommonTypes.MediaType.Playdia + or CommonTypes.MediaType.Pippin + or CommonTypes.MediaType.VideoNow + or CommonTypes.MediaType.VideoNowColor + or CommonTypes.MediaType.VideoNowXp + or CommonTypes.MediaType.CVD; if(_isCd) return ErrorNumber.NoError; @@ -1760,8 +1756,7 @@ public sealed partial class Nero { buffer = null; - if(tag == SectorTagType.CdTrackFlags || - tag == SectorTagType.CdTrackIsrc) + if(tag is SectorTagType.CdTrackFlags or SectorTagType.CdTrackIsrc) track = (uint)sectorAddress; if(!_neroTracks.TryGetValue(track, out NeroTrack aaruTrack)) diff --git a/Aaru.Images/QCOW/Read.cs b/Aaru.Images/QCOW/Read.cs index f0b6428e7..3f27e9246 100644 --- a/Aaru.Images/QCOW/Read.cs +++ b/Aaru.Images/QCOW/Read.cs @@ -79,16 +79,14 @@ public sealed partial class Qcow return ErrorNumber.InvalidArgument; } - if(_qHdr.cluster_bits < 9 || - _qHdr.cluster_bits > 16) + if(_qHdr.cluster_bits is < 9 or > 16) { AaruConsole.ErrorWriteLine("Cluster size must be between 512 bytes and 64 Kbytes"); return ErrorNumber.InvalidArgument; } - if(_qHdr.l2_bits < 9 - 3 || - _qHdr.l2_bits > 16 - 3) + if(_qHdr.l2_bits is < 9 - 3 or > 16 - 3) { AaruConsole.ErrorWriteLine("L2 size must be between 512 bytes and 64 Kbytes"); diff --git a/Aaru.Images/QCOW2/Identify.cs b/Aaru.Images/QCOW2/Identify.cs index 9100e2e20..479b1e931 100644 --- a/Aaru.Images/QCOW2/Identify.cs +++ b/Aaru.Images/QCOW2/Identify.cs @@ -55,6 +55,6 @@ public sealed partial class Qcow2 AaruConsole.DebugWriteLine("QCOW plugin", "qHdr.magic = 0x{0:X8}", _qHdr.magic); AaruConsole.DebugWriteLine("QCOW plugin", "qHdr.version = {0}", _qHdr.version); - return _qHdr.magic == QCOW_MAGIC && (_qHdr.version == QCOW_VERSION2 || _qHdr.version == QCOW_VERSION3); + return _qHdr.magic == QCOW_MAGIC && _qHdr.version is QCOW_VERSION2 or QCOW_VERSION3; } } \ No newline at end of file diff --git a/Aaru.Images/QCOW2/Read.cs b/Aaru.Images/QCOW2/Read.cs index 0e9746a57..fecdd5887 100644 --- a/Aaru.Images/QCOW2/Read.cs +++ b/Aaru.Images/QCOW2/Read.cs @@ -100,8 +100,7 @@ public sealed partial class Qcow2 return ErrorNumber.InvalidArgument; } - if(_qHdr.cluster_bits < 9 || - _qHdr.cluster_bits > 16) + if(_qHdr.cluster_bits is < 9 or > 16) { AaruConsole.ErrorWriteLine("Cluster size must be between 512 bytes and 64 Kbytes"); diff --git a/Aaru.Images/QCOW2/Write.cs b/Aaru.Images/QCOW2/Write.cs index 5331d9da3..7d0a44e3a 100644 --- a/Aaru.Images/QCOW2/Write.cs +++ b/Aaru.Images/QCOW2/Write.cs @@ -91,7 +91,7 @@ public sealed partial class Qcow2 } string extension = Path.GetExtension(path); - bool version3 = extension == ".qcow3" || extension == ".qc3"; + bool version3 = extension is ".qcow3" or ".qc3"; _qHdr = new Header { diff --git a/Aaru.Images/QED/Read.cs b/Aaru.Images/QED/Read.cs index b0e735fdd..12b8ccdcd 100644 --- a/Aaru.Images/QED/Read.cs +++ b/Aaru.Images/QED/Read.cs @@ -83,8 +83,7 @@ public sealed partial class Qed return ErrorNumber.InvalidArgument; } - if(_qHdr.cluster_size < 4096 || - _qHdr.cluster_size > 67108864) + if(_qHdr.cluster_size is < 4096 or > 67108864) { AaruConsole.ErrorWriteLine("Cluster size must be between 4 Kbytes and 64 Mbytes"); @@ -98,8 +97,7 @@ public sealed partial class Qed return ErrorNumber.InvalidArgument; } - if(_qHdr.table_size < 1 || - _qHdr.table_size > 16) + if(_qHdr.table_size is < 1 or > 16) { AaruConsole.ErrorWriteLine("Table size must be between 1 and 16 clusters"); diff --git a/Aaru.Images/RayDIM/Read.cs b/Aaru.Images/RayDIM/Read.cs index 21e5549bc..d4511a878 100644 --- a/Aaru.Images/RayDIM/Read.cs +++ b/Aaru.Images/RayDIM/Read.cs @@ -87,17 +87,15 @@ public sealed partial class RayDim switch(_imageInfo.MediaType) { - case MediaType.NEC_525_HD - when header.diskType == RayDiskTypes.Mf2hd || header.diskType == RayDiskTypes.Mf2ed: + case MediaType.NEC_525_HD when header.diskType is RayDiskTypes.Mf2hd or RayDiskTypes.Mf2ed: _imageInfo.MediaType = MediaType.NEC_35_HD_8; break; - case MediaType.DOS_525_HD - when header.diskType == RayDiskTypes.Mf2hd || header.diskType == RayDiskTypes.Mf2ed: + case MediaType.DOS_525_HD when header.diskType is RayDiskTypes.Mf2hd or RayDiskTypes.Mf2ed: _imageInfo.MediaType = MediaType.NEC_35_HD_15; break; - case MediaType.RX50 when header.diskType == RayDiskTypes.Md2dd || header.diskType == RayDiskTypes.Md2hd: + case MediaType.RX50 when header.diskType is RayDiskTypes.Md2dd or RayDiskTypes.Md2hd: _imageInfo.MediaType = MediaType.ATARI_35_SS_DD; break; diff --git a/Aaru.Images/SaveDskF/Identify.cs b/Aaru.Images/SaveDskF/Identify.cs index 8c0ab6011..9498ec958 100644 --- a/Aaru.Images/SaveDskF/Identify.cs +++ b/Aaru.Images/SaveDskF/Identify.cs @@ -52,8 +52,7 @@ public sealed partial class SaveDskF _header = Marshal.ByteArrayToStructureLittleEndian
(hdr); - return (_header.magic == SDF_MAGIC || _header.magic == SDF_MAGIC_COMPRESSED || - _header.magic == SDF_MAGIC_OLD) && _header.fatCopies <= 2 && _header.padding == 0 && - _header.commentOffset < stream.Length && _header.dataOffset < stream.Length; + return _header.magic is SDF_MAGIC or SDF_MAGIC_COMPRESSED or SDF_MAGIC_OLD && _header.fatCopies <= 2 && + _header.padding == 0 && _header.commentOffset < stream.Length && _header.dataOffset < stream.Length; } } \ No newline at end of file diff --git a/Aaru.Images/TeleDisk/Identify.cs b/Aaru.Images/TeleDisk/Identify.cs index 55c7c87ed..76a166f7a 100644 --- a/Aaru.Images/TeleDisk/Identify.cs +++ b/Aaru.Images/TeleDisk/Identify.cs @@ -96,9 +96,7 @@ public sealed partial class TeleDisk _header.DataRate != DATA_RATE_500_KBPS) return false; - return _header.DriveType == DRIVE_TYPE_35_DD || _header.DriveType == DRIVE_TYPE_35_ED || - _header.DriveType == DRIVE_TYPE_35_HD || _header.DriveType == DRIVE_TYPE_525_DD || - _header.DriveType == DRIVE_TYPE_525_HD || _header.DriveType == DRIVE_TYPE_525_HD_DD_DISK || - _header.DriveType == DRIVE_TYPE_8_INCH; + return _header.DriveType is DRIVE_TYPE_35_DD or DRIVE_TYPE_35_ED or DRIVE_TYPE_35_HD or DRIVE_TYPE_525_DD + or DRIVE_TYPE_525_HD or DRIVE_TYPE_525_HD_DD_DISK or DRIVE_TYPE_8_INCH; } } \ No newline at end of file diff --git a/Aaru.Images/VHD/Read.cs b/Aaru.Images/VHD/Read.cs index db6388a7f..31cf1f6ed 100644 --- a/Aaru.Images/VHD/Read.cs +++ b/Aaru.Images/VHD/Read.cs @@ -342,8 +342,7 @@ public sealed partial class Vhd _imageInfo.Heads = (_thisFooter.DiskGeometry & 0xFF00) >> 8; _imageInfo.SectorsPerTrack = _thisFooter.DiskGeometry & 0xFF; - if(_thisFooter.DiskType == TYPE_DYNAMIC || - _thisFooter.DiskType == TYPE_DIFFERENCING) + if(_thisFooter.DiskType is TYPE_DYNAMIC or TYPE_DIFFERENCING) { imageStream.Seek((long)_thisFooter.Offset, SeekOrigin.Begin); var dynamicBytes = new byte[1024]; diff --git a/Aaru.Images/VMware/Read.cs b/Aaru.Images/VMware/Read.cs index 778fc2042..2a78f2829 100644 --- a/Aaru.Images/VMware/Read.cs +++ b/Aaru.Images/VMware/Read.cs @@ -333,10 +333,7 @@ public sealed partial class VMware return ErrorNumber.InvalidArgument; } - if(extent.Type == "FLAT" || - extent.Type == "ZERO" || - extent.Type == "VMFS" || - cowD) + if(extent.Type is "FLAT" or "ZERO" or "VMFS" || cowD) continue; Stream extentStream = extent.Filter.GetDataForkStream(); @@ -642,8 +639,7 @@ public sealed partial class VMware if(grainOff == 0 && _hasParent) return _parentImage.ReadSector(sectorAddress, out buffer); - if(grainOff == 0 || - grainOff == 1) + if(grainOff is 0 or 1) { buffer = new byte[SECTOR_SIZE]; diff --git a/Aaru.Images/WCDiskImage/Identify.cs b/Aaru.Images/WCDiskImage/Identify.cs index 8ac181e43..62ffe69ee 100644 --- a/Aaru.Images/WCDiskImage/Identify.cs +++ b/Aaru.Images/WCDiskImage/Identify.cs @@ -62,16 +62,13 @@ public sealed partial class WCDiskImage if(fheader.version > 1) return false; - if(fheader.heads < 1 || - fheader.heads > 2) + if(fheader.heads is < 1 or > 2) return false; - if(fheader.sectorsPerTrack < 8 || - fheader.sectorsPerTrack > 18) + if(fheader.sectorsPerTrack is < 8 or > 18) return false; - if(fheader.cylinders < 1 || - fheader.cylinders > 80) + if(fheader.cylinders is < 1 or > 80) return false; if(fheader.extraTracks[0] > 1 || diff --git a/Aaru.Images/ZZZRawImage/Helpers.cs b/Aaru.Images/ZZZRawImage/Helpers.cs index b8e328ce5..5ffb81e6a 100644 --- a/Aaru.Images/ZZZRawImage/Helpers.cs +++ b/Aaru.Images/ZZZRawImage/Helpers.cs @@ -117,7 +117,7 @@ public sealed partial class ZZZRawImage if(_imageInfo.SectorSize == 256) return MediaType.CBM_35_DD; - if((_extension == ".adf" || _extension == ".adl") && + if(_extension is ".adf" or ".adl" && _imageInfo.SectorSize == 1024) return MediaType.ACORN_35_DS_DD; diff --git a/Aaru.Images/ZZZRawImage/Properties.cs b/Aaru.Images/ZZZRawImage/Properties.cs index 251bbacff..f49cc2c1f 100644 --- a/Aaru.Images/ZZZRawImage/Properties.cs +++ b/Aaru.Images/ZZZRawImage/Properties.cs @@ -86,9 +86,7 @@ public sealed partial class ZZZRawImage Session = 1 }; - if(_imageInfo.MediaType == MediaType.CD || - _imageInfo.MediaType == MediaType.CDRW || - _imageInfo.MediaType == MediaType.CDR) + if(_imageInfo.MediaType is MediaType.CD or MediaType.CDRW or MediaType.CDR) { trk.Pregap = 150; trk.Indexes[0] = -150; @@ -153,7 +151,7 @@ public sealed partial class ZZZRawImage ? _mode2 ? "MODE2/2352" : "MODE1/2352" - : _imageInfo.MediaType == MediaType.PD650 || _imageInfo.MediaType == MediaType.PD650_WORM + : _imageInfo.MediaType is MediaType.PD650 or MediaType.PD650_WORM ? "DATA/512" : "MODE1/2048", Size = _imageInfo.Sectors * _imageInfo.SectorSize diff --git a/Aaru.Images/ZZZRawImage/Read.cs b/Aaru.Images/ZZZRawImage/Read.cs index 3c7cf175d..e66ee4547 100644 --- a/Aaru.Images/ZZZRawImage/Read.cs +++ b/Aaru.Images/ZZZRawImage/Read.cs @@ -137,11 +137,10 @@ public sealed partial class ZZZRawImage break; default: - if((_extension == ".adf" || _extension == ".adl" || _extension == ".ssd" || _extension == ".dsd") && - (imageFilter.DataForkLength == 163840 || imageFilter.DataForkLength == 327680 || - imageFilter.DataForkLength == 655360)) + if(_extension is ".adf" or ".adl" or ".ssd" or ".dsd" && + imageFilter.DataForkLength is 163840 or 327680 or 655360) _imageInfo.SectorSize = 256; - else if((_extension == ".adf" || _extension == ".adl") && + else if(_extension is ".adf" or ".adl" && imageFilter.DataForkLength == 819200) _imageInfo.SectorSize = 1024; else @@ -489,8 +488,7 @@ public sealed partial class ZZZRawImage break; } - if((_imageInfo.MediaType == MediaType.DVDR || _imageInfo.MediaType == MediaType.DVDRW || - _imageInfo.MediaType == MediaType.HDDVDR) && + if(_imageInfo.MediaType is MediaType.DVDR or MediaType.DVDRW or MediaType.HDDVDR && _mediaTags.TryGetValue(MediaTagType.DVD_MediaIdentifier, out byte[] mid)) { _mediaTags.Remove(MediaTagType.DVD_MediaIdentifier); @@ -508,9 +506,7 @@ public sealed partial class ZZZRawImage _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 is 25063 or 4229664 or 4246304) // Wxripper unlock _imageInfo.MediaType = MediaType.XGD3; } } diff --git a/Aaru.Partitions/AppleMap.cs b/Aaru.Partitions/AppleMap.cs index eccc74fb0..fdda5526b 100644 --- a/Aaru.Partitions/AppleMap.cs +++ b/Aaru.Partitions/AppleMap.cs @@ -72,8 +72,7 @@ public sealed class AppleMap : IPartition { uint sectorSize; - if(imagePlugin.Info.SectorSize == 2352 || - imagePlugin.Info.SectorSize == 2448) + if(imagePlugin.Info.SectorSize is 2352 or 2448) sectorSize = 2048; else sectorSize = imagePlugin.Info.SectorSize; diff --git a/Aaru.Partitions/Atari.cs b/Aaru.Partitions/Atari.cs index 54e14aea6..d41efa44c 100644 --- a/Aaru.Partitions/Atari.cs +++ b/Aaru.Partitions/Atari.cs @@ -180,8 +180,7 @@ public sealed class AtariPartitions : IPartition ulong sectorSize = imagePlugin.Info.SectorSize; - if(sectorSize == 2448 || - sectorSize == 2352) + if(sectorSize is 2448 or 2352) sectorSize = 2048; var partType = new byte[3]; @@ -304,8 +303,7 @@ public sealed class AtariPartitions : IPartition ulong sectorSize = imagePlugin.Info.SectorSize; - if(sectorSize == 2448 || - sectorSize == 2352) + if(sectorSize is 2448 or 2352) sectorSize = 2048; var partType = new byte[3]; @@ -411,8 +409,7 @@ public sealed class AtariPartitions : IPartition ulong sectorSize = imagePlugin.Info.SectorSize; - if(sectorSize == 2448 || - sectorSize == 2352) + if(sectorSize is 2448 or 2352) sectorSize = 2048; var partType = new byte[3]; diff --git a/Aaru.Partitions/MBR.cs b/Aaru.Partitions/MBR.cs index 7ab8994d3..525425e31 100644 --- a/Aaru.Partitions/MBR.cs +++ b/Aaru.Partitions/MBR.cs @@ -359,22 +359,13 @@ public sealed class MBR : IPartition valid &= entry.type != 0x00; - if(entry.type == 0x05 || - entry.type == 0x0F || - entry.type == 0x15 || - entry.type == 0x1F || - entry.type == 0x85 || - entry.type == 0x91 || - entry.type == 0x9B || - entry.type == 0xC5 || - entry.type == 0xCF || - entry.type == 0xD5) + if(entry.type is 0x05 or 0x0F or 0x15 or 0x1F or 0x85 or 0x91 or 0x9B or 0xC5 or 0xCF or 0xD5) { valid = false; extended = true; // Extended partition } - minix |= entry.type == 0x81 || entry.type == 0x80; // MINIX partition + minix |= entry.type is 0x81 or 0x80; // MINIX partition valid &= entry.lba_start != 0 || entry.lba_sectors != 0 || entry.start_cylinder != 0 || entry.start_head != 0 || entry.start_sector != 0 || entry.end_cylinder != 0 || @@ -506,7 +497,7 @@ public sealed class MBR : IPartition AaruConsole.DebugWriteLine("MBR plugin", "ebr_entry.end_sector {0}", endSector); // Let's start the fun... - extValid &= ebrEntry.status == 0x00 || ebrEntry.status == 0x80; + extValid &= ebrEntry.status is 0x00 or 0x80; extValid &= ebrEntry.type != 0x00; extValid &= ebrEntry.lba_start != 0 || ebrEntry.lba_sectors != 0 || ebrEntry.start_cylinder != 0 || @@ -524,7 +515,7 @@ public sealed class MBR : IPartition imagePlugin.Info.Heads, imagePlugin.Info.SectorsPerTrack) - extStart; } - extMinix |= ebrEntry.type == 0x81 || ebrEntry.type == 0x80; + extMinix |= ebrEntry.type is 0x81 or 0x80; // For optical media extStart /= divider; @@ -533,16 +524,7 @@ public sealed class MBR : IPartition AaruConsole.DebugWriteLine("MBR plugin", "ext_start {0}", extStart); AaruConsole.DebugWriteLine("MBR plugin", "ext_sectors {0}", extSectors); - if(ebrEntry.type == 0x05 || - ebrEntry.type == 0x0F || - ebrEntry.type == 0x15 || - ebrEntry.type == 0x1F || - ebrEntry.type == 0x85 || - ebrEntry.type == 0x91 || - ebrEntry.type == 0x9B || - ebrEntry.type == 0xC5 || - ebrEntry.type == 0xCF || - ebrEntry.type == 0xD5) + if(ebrEntry.type is 0x05 or 0x0F or 0x15 or 0x1F or 0x85 or 0x91 or 0x9B or 0xC5 or 0xCF or 0xD5) { extValid = false; nextStart = chainStart + extStart; @@ -642,8 +624,8 @@ public sealed class MBR : IPartition AaruConsole.DebugWriteLine("MBR plugin", "mnx_entry.end_head {0}", mnxEntry.end_head); AaruConsole.DebugWriteLine("MBR plugin", "mnx_entry.end_sector {0}", endSector); - mnxValid &= mnxEntry.status == 0x00 || mnxEntry.status == 0x80; - mnxValid &= mnxEntry.type == 0x81 || mnxEntry.type == 0x80; + mnxValid &= mnxEntry.status is 0x00 or 0x80; + mnxValid &= mnxEntry.type is 0x81 or 0x80; mnxValid &= mnxEntry.lba_start != 0 || mnxEntry.lba_sectors != 0 || mnxEntry.start_cylinder != 0 || mnxEntry.start_head != 0 || mnxEntry.start_sector != 0 || mnxEntry.end_cylinder != 0 || diff --git a/Aaru.Partitions/NeXT.cs b/Aaru.Partitions/NeXT.cs index 3e7562660..44db56232 100644 --- a/Aaru.Partitions/NeXT.cs +++ b/Aaru.Partitions/NeXT.cs @@ -30,9 +30,8 @@ // Copyright © 2011-2022 Natalia Portillo // ****************************************************************************/ - - // Information learnt from XNU source and testing against real disks + namespace Aaru.Partitions; using System; @@ -79,8 +78,7 @@ public sealed class NeXTDisklabel : IPartition uint sectorSize; - if(imagePlugin.Info.SectorSize == 2352 || - imagePlugin.Info.SectorSize == 2448) + if(imagePlugin.Info.SectorSize is 2352 or 2448) sectorSize = 2048; else sectorSize = imagePlugin.Info.SectorSize; diff --git a/Aaru.Partitions/SGI.cs b/Aaru.Partitions/SGI.cs index 5b51b61e5..f02b382da 100644 --- a/Aaru.Partitions/SGI.cs +++ b/Aaru.Partitions/SGI.cs @@ -155,9 +155,8 @@ public sealed class SGI : IPartition Scheme = Name }; - if(part.Size <= 0 || - dvh.partitions[i].type == SGIType.Header || - dvh.partitions[i].type == SGIType.Volume) + if(part.Size <= 0 || + dvh.partitions[i].type is SGIType.Header or SGIType.Volume) continue; partitions.Add(part); diff --git a/Aaru.Partitions/Sun.cs b/Aaru.Partitions/Sun.cs index 3329bd186..0f0742aef 100644 --- a/Aaru.Partitions/Sun.cs +++ b/Aaru.Partitions/Sun.cs @@ -108,13 +108,10 @@ public sealed class SunDisklabel : IPartition AaruConsole.DebugWriteLine("Sun plugin", "dkl8.dkl_vtoc.v_sanity = 0x{0:X8}", dkl8.dkl_vtoc.v_sanity); AaruConsole.DebugWriteLine("Sun plugin", "dkl16.dkl_vtoc.v_sanity = 0x{0:X8}", dkl16.dkl_vtoc.v_sanity); - if(dkl.dkl_magic == DKL_MAGIC || - dkl.dkl_magic == DKL_CIGAM) - if(dkl16.dkl_vtoc.v_sanity == VTOC_SANE || - dkl16.dkl_vtoc.v_sanity == VTOC_ENAS) + if(dkl.dkl_magic is DKL_MAGIC or DKL_CIGAM) + if(dkl16.dkl_vtoc.v_sanity is VTOC_SANE or VTOC_ENAS) useDkl16 = true; - else if(dkl8.dkl_vtoc.v_sanity == VTOC_SANE || - dkl8.dkl_vtoc.v_sanity == VTOC_ENAS) + else if(dkl8.dkl_vtoc.v_sanity is VTOC_SANE or VTOC_ENAS) useDkl8 = true; else useDkl = true; @@ -131,13 +128,10 @@ public sealed class SunDisklabel : IPartition dkl8 = Marshal.ByteArrayToStructureLittleEndian(sunSector); dkl16 = Marshal.ByteArrayToStructureLittleEndian(sunSector); - if(dkl.dkl_magic == DKL_MAGIC || - dkl.dkl_magic == DKL_CIGAM) - if(dkl16.dkl_vtoc.v_sanity == VTOC_SANE || - dkl16.dkl_vtoc.v_sanity == VTOC_ENAS) + if(dkl.dkl_magic is DKL_MAGIC or DKL_CIGAM) + if(dkl16.dkl_vtoc.v_sanity is VTOC_SANE or VTOC_ENAS) useDkl16 = true; - else if(dkl8.dkl_vtoc.v_sanity == VTOC_SANE || - dkl8.dkl_vtoc.v_sanity == VTOC_ENAS) + else if(dkl8.dkl_vtoc.v_sanity is VTOC_SANE or VTOC_ENAS) useDkl8 = true; else useDkl = true; diff --git a/Aaru.Partitions/VTOC.cs b/Aaru.Partitions/VTOC.cs index 737b4df61..276171315 100644 --- a/Aaru.Partitions/VTOC.cs +++ b/Aaru.Partitions/VTOC.cs @@ -172,8 +172,7 @@ public sealed class VTOC : IPartition var vtocOld = new vtocold(); magic = BitConverter.ToUInt32(vtocsector, 0); - if(magic == VTOC_SANE || - magic == VTOC_ENAS) + if(magic is VTOC_SANE or VTOC_ENAS) { magicFound = true; AaruConsole.DebugWriteLine("VTOC plugin", "New VTOC found at {0}", pdloc + sectorOffset + 1); @@ -200,8 +199,7 @@ public sealed class VTOC : IPartition { magic = BitConverter.ToUInt32(vtocsector, 12); - if(magic == VTOC_SANE || - magic == VTOC_ENAS) + if(magic is VTOC_SANE or VTOC_ENAS) { magicFound = true; useOld = true; @@ -255,8 +253,7 @@ public sealed class VTOC : IPartition Array.Copy(tmp, relSecOff, vtocsector, 0, pd.vtoc_len); magic = BitConverter.ToUInt32(vtocsector, 0); - if(magic == VTOC_SANE || - magic == VTOC_ENAS) + if(magic is VTOC_SANE or VTOC_ENAS) { magicFound = true; AaruConsole.DebugWriteLine("VTOC plugin", "New VTOC found."); @@ -451,6 +448,7 @@ public sealed class VTOC : IPartition } [StructLayout(LayoutKind.Sequential, Pack = 1)] + // ReSharper disable once InconsistentNaming struct PDInfo { @@ -494,6 +492,7 @@ public sealed class VTOC : IPartition } [StructLayout(LayoutKind.Sequential, Pack = 1)] + // ReSharper disable once InconsistentNaming struct PDInfoOld { @@ -522,6 +521,7 @@ public sealed class VTOC : IPartition } [StructLayout(LayoutKind.Sequential, Pack = 1)] + // ReSharper disable once InconsistentNaming struct vtocold { @@ -542,6 +542,7 @@ public sealed class VTOC : IPartition } [StructLayout(LayoutKind.Sequential, Pack = 1)] + // ReSharper disable once InconsistentNaming struct vtoc { diff --git a/Aaru.Tests/WritableImages/WritableOpticalMediaImageTest.cs b/Aaru.Tests/WritableImages/WritableOpticalMediaImageTest.cs index 0431e7ba7..31f48c4a6 100644 --- a/Aaru.Tests/WritableImages/WritableOpticalMediaImageTest.cs +++ b/Aaru.Tests/WritableImages/WritableOpticalMediaImageTest.cs @@ -429,46 +429,19 @@ public abstract class WritableOpticalMediaImageTest : BaseWritableMediaImageTest outputFormat.WriteMediaTag(Encoding.UTF8.GetBytes(mcn), MediaTagType.CD_MCN); // TODO: Progress - if(inputFormat.Info.MediaType == MediaType.CD || - inputFormat.Info.MediaType == MediaType.CDDA || - inputFormat.Info.MediaType == MediaType.CDG || - inputFormat.Info.MediaType == MediaType.CDEG || - inputFormat.Info.MediaType == MediaType.CDI || - inputFormat.Info.MediaType == MediaType.CDROM || - inputFormat.Info.MediaType == MediaType.CDROMXA || - inputFormat.Info.MediaType == MediaType.CDPLUS || - inputFormat.Info.MediaType == MediaType.CDMO || - inputFormat.Info.MediaType == MediaType.CDR || - inputFormat.Info.MediaType == MediaType.CDRW || - inputFormat.Info.MediaType == MediaType.CDMRW || - inputFormat.Info.MediaType == MediaType.VCD || - inputFormat.Info.MediaType == MediaType.SVCD || - inputFormat.Info.MediaType == MediaType.PCD || - inputFormat.Info.MediaType == MediaType.DTSCD || - inputFormat.Info.MediaType == MediaType.CDMIDI || - inputFormat.Info.MediaType == MediaType.CDV || - inputFormat.Info.MediaType == MediaType.CDIREADY || - inputFormat.Info.MediaType == MediaType.FMTOWNS || - inputFormat.Info.MediaType == MediaType.PS1CD || - inputFormat.Info.MediaType == MediaType.PS2CD || - inputFormat.Info.MediaType == MediaType.MEGACD || - inputFormat.Info.MediaType == MediaType.SATURNCD || - inputFormat.Info.MediaType == MediaType.GDROM || - inputFormat.Info.MediaType == MediaType.GDR || - inputFormat.Info.MediaType == MediaType.MilCD || - inputFormat.Info.MediaType == MediaType.SuperCDROM2 || - inputFormat.Info.MediaType == MediaType.JaguarCD || - inputFormat.Info.MediaType == MediaType.ThreeDO || - inputFormat.Info.MediaType == MediaType.PCFX || - inputFormat.Info.MediaType == MediaType.NeoGeoCD || - inputFormat.Info.MediaType == MediaType.CDTV || - inputFormat.Info.MediaType == MediaType.CD32 || - inputFormat.Info.MediaType == MediaType.Playdia || - inputFormat.Info.MediaType == MediaType.Pippin || - inputFormat.Info.MediaType == MediaType.VideoNow || - inputFormat.Info.MediaType == MediaType.VideoNowColor || - inputFormat.Info.MediaType == MediaType.VideoNowXp || - inputFormat.Info.MediaType == MediaType.CVD) + if(inputFormat.Info.MediaType is MediaType.CD or MediaType.CDDA or MediaType.CDG or MediaType.CDEG + or MediaType.CDI or MediaType.CDROM or MediaType.CDROMXA + or MediaType.CDPLUS or MediaType.CDMO or MediaType.CDR or MediaType.CDRW + or MediaType.CDMRW or MediaType.VCD or MediaType.SVCD or MediaType.PCD + or MediaType.DTSCD or MediaType.CDMIDI or MediaType.CDV + or MediaType.CDIREADY or MediaType.FMTOWNS or MediaType.PS1CD + or MediaType.PS2CD or MediaType.MEGACD or MediaType.SATURNCD + or MediaType.GDROM or MediaType.GDR or MediaType.MilCD + or MediaType.SuperCDROM2 or MediaType.JaguarCD or MediaType.ThreeDO + or MediaType.PCFX or MediaType.NeoGeoCD or MediaType.CDTV + or MediaType.CD32 or MediaType.Playdia or MediaType.Pippin + or MediaType.VideoNow or MediaType.VideoNowColor or MediaType.VideoNowXp + or MediaType.CVD) CompactDisc.GenerateSubchannels(subchannelExtents, tracks, trackFlags, inputFormat.Info.Sectors, null, null, null, null, null, outputFormat); diff --git a/Aaru/Commands/Device/DeviceReport.cs b/Aaru/Commands/Device/DeviceReport.cs index bec43f09a..3fa1881f7 100644 --- a/Aaru/Commands/Device/DeviceReport.cs +++ b/Aaru/Commands/Device/DeviceReport.cs @@ -408,9 +408,8 @@ sealed class DeviceReportCommand : Command case PeripheralDeviceTypes.MultiMediaDevice: { if(dev.IsUsb && - (mediumType == MediumTypes.UnknownBlockDevice || - mediumType == MediumTypes.ReadOnlyBlockDevice || - mediumType == MediumTypes.ReadWriteBlockDevice)) + mediumType is MediumTypes.UnknownBlockDevice or MediumTypes.ReadOnlyBlockDevice + or MediumTypes.ReadWriteBlockDevice) goto default; bool iomegaRev = dev.Manufacturer.ToLowerInvariant() == "iomega" && dev.Model. diff --git a/Aaru/Commands/Device/Info.cs b/Aaru/Commands/Device/Info.cs index ecb1b0b00..6b6b504be 100644 --- a/Aaru/Commands/Device/Info.cs +++ b/Aaru/Commands/Device/Info.cs @@ -518,7 +518,7 @@ sealed class DeviceInfoCommand : Command DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value); } - else if((page.Key == 0xC0 || page.Key == 0xC1) && + else if(page.Key is 0xC0 or 0xC1 && StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification).ToLowerInvariant(). Trim() == "certance") { @@ -527,8 +527,7 @@ sealed class DeviceInfoCommand : Command DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value); } - else if((page.Key == 0xC2 || page.Key == 0xC3 || page.Key == 0xC4 || page.Key == 0xC5 || - page.Key == 0xC6) && + else if(page.Key is 0xC2 or 0xC3 or 0xC4 or 0xC5 or 0xC6 && StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification).ToLowerInvariant(). Trim() == "certance") { @@ -537,8 +536,7 @@ sealed class DeviceInfoCommand : Command DataFile.WriteTo("Device-Info command", outputPrefix, $"_scsi_evpd_{page.Key:X2}h.bin", $"SCSI INQUIRY EVPD {page.Key:X2}h", page.Value); } - else if((page.Key == 0xC0 || page.Key == 0xC1 || page.Key == 0xC2 || page.Key == 0xC3 || - page.Key == 0xC4 || page.Key == 0xC5) && + else if(page.Key is 0xC0 or 0xC1 or 0xC2 or 0xC3 or 0xC4 or 0xC5 && StringHandlers.CToString(devInfo.ScsiInquiry.Value.VendorIdentification).ToLowerInvariant(). Trim() == "hp") { diff --git a/Aaru/Commands/Image/Convert.cs b/Aaru/Commands/Image/Convert.cs index e035a2dea..b41d75d27 100644 --- a/Aaru/Commands/Image/Convert.cs +++ b/Aaru/Commands/Image/Convert.cs @@ -1261,29 +1261,18 @@ sealed class ConvertImageCommand : Command outputOptical.WriteMediaTag(Encoding.UTF8.GetBytes(mcn), MediaTagType.CD_MCN); // TODO: Progress - if((inputOptical.Info.MediaType == MediaType.CD || inputOptical.Info.MediaType == MediaType.CDDA || - inputOptical.Info.MediaType == MediaType.CDG || inputOptical.Info.MediaType == MediaType.CDEG || - inputOptical.Info.MediaType == MediaType.CDI || inputOptical.Info.MediaType == MediaType.CDROM || - inputOptical.Info.MediaType == MediaType.CDROMXA || inputOptical.Info.MediaType == MediaType.CDPLUS || - inputOptical.Info.MediaType == MediaType.CDMO || inputOptical.Info.MediaType == MediaType.CDR || - inputOptical.Info.MediaType == MediaType.CDRW || inputOptical.Info.MediaType == MediaType.CDMRW || - inputOptical.Info.MediaType == MediaType.VCD || inputOptical.Info.MediaType == MediaType.SVCD || - inputOptical.Info.MediaType == MediaType.PCD || inputOptical.Info.MediaType == MediaType.DTSCD || - inputOptical.Info.MediaType == MediaType.CDMIDI || inputOptical.Info.MediaType == MediaType.CDV || - inputOptical.Info.MediaType == MediaType.CDIREADY || inputOptical.Info.MediaType == MediaType.FMTOWNS || - inputOptical.Info.MediaType == MediaType.PS1CD || inputOptical.Info.MediaType == MediaType.PS2CD || - inputOptical.Info.MediaType == MediaType.MEGACD || inputOptical.Info.MediaType == MediaType.SATURNCD || - inputOptical.Info.MediaType == MediaType.GDROM || inputOptical.Info.MediaType == MediaType.GDR || - inputOptical.Info.MediaType == MediaType.MilCD || - inputOptical.Info.MediaType == MediaType.SuperCDROM2 || - inputOptical.Info.MediaType == MediaType.JaguarCD || inputOptical.Info.MediaType == MediaType.ThreeDO || - inputOptical.Info.MediaType == MediaType.PCFX || inputOptical.Info.MediaType == MediaType.NeoGeoCD || - inputOptical.Info.MediaType == MediaType.CDTV || inputOptical.Info.MediaType == MediaType.CD32 || - inputOptical.Info.MediaType == MediaType.Playdia || inputOptical.Info.MediaType == MediaType.Pippin || - inputOptical.Info.MediaType == MediaType.VideoNow || - inputOptical.Info.MediaType == MediaType.VideoNowColor || - inputOptical.Info.MediaType == MediaType.VideoNowXp || inputOptical.Info.MediaType == MediaType.CVD) && - generateSubchannels) + if(inputOptical.Info.MediaType is MediaType.CD or MediaType.CDDA or MediaType.CDG or MediaType.CDEG + or MediaType.CDI or MediaType.CDROM or MediaType.CDROMXA or MediaType.CDPLUS + or MediaType.CDMO or MediaType.CDR or MediaType.CDRW or MediaType.CDMRW + or MediaType.VCD or MediaType.SVCD or MediaType.PCD or MediaType.DTSCD + or MediaType.CDMIDI or MediaType.CDV or MediaType.CDIREADY + or MediaType.FMTOWNS or MediaType.PS1CD or MediaType.PS2CD + or MediaType.MEGACD or MediaType.SATURNCD or MediaType.GDROM or MediaType.GDR + or MediaType.MilCD or MediaType.SuperCDROM2 or MediaType.JaguarCD + or MediaType.ThreeDO or MediaType.PCFX or MediaType.NeoGeoCD + or MediaType.CDTV or MediaType.CD32 or MediaType.Playdia or MediaType.Pippin + or MediaType.VideoNow or MediaType.VideoNowColor or MediaType.VideoNowXp + or MediaType.CVD && generateSubchannels) Spectre.ProgressSingleSpinner(ctx => { ctx.AddTask("Generating subchannels...").IsIndeterminate();