// /*************************************************************************** // The Disc Image Chef // ---------------------------------------------------------------------------- // // Filename : PFI.cs // Author(s) : Natalia Portillo // // Component : Device structures decoders. // // --[ Description ] ---------------------------------------------------------- // // Records DVD Physical Format Information. // // --[ License ] -------------------------------------------------------------- // // This library is free software; you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; either version 2.1 of the // License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, see . // // ---------------------------------------------------------------------------- // Copyright © 2011-2019 Natalia Portillo // ****************************************************************************/ using System; using System.Diagnostics.CodeAnalysis; using System.Text; namespace DiscImageChef.Decoders.DVD { /// /// Information from the following standards: /// ANSI X3.304-1997 /// T10/1048-D revision 9.0 /// T10/1048-D revision 10a /// T10/1228-D revision 7.0c /// T10/1228-D revision 11a /// T10/1363-D revision 10g /// T10/1545-D revision 1d /// T10/1545-D revision 5 /// T10/1545-D revision 5a /// T10/1675-D revision 2c /// T10/1675-D revision 4 /// T10/1836-D revision 2g /// ECMA 267: 120 mm DVD - Read-Only Disk /// ECMA 268: 80 mm DVD - Read-Only Disk /// ECMA 272: 120 mm DVD Rewritable Disk (DVD-RAM) /// ECMA 274: Data Interchange on 120 mm Optical Disk using +RW Format - Capacity: 3,0 Gbytes and 6,0 Gbytes /// ECMA 279: 80 mm (1,23 Gbytes per side) and 120 mm (3,95 Gbytes per side) DVD-Recordable Disk (DVD-R) /// ECMA 330: 120 mm (4,7 Gbytes per side) and 80 mm (1,46 Gbytes per side) DVD Rewritable Disk (DVD-RAM) /// ECMA 337: Data Interchange on 120 mm and 80 mm Optical Disk using +RW Format - Capacity: 4,7 and 1,46 Gbytes per /// Side /// ECMA 338: 80 mm (1,46 Gbytes per side) and 120 mm (4,70 Gbytes per side) DVD Re-recordable Disk (DVD-RW) /// ECMA 349: Data Interchange on 120 mm and 80 mm Optical Disk using +R Format - Capacity: 4,7 and 1,46 Gbytes per /// Side /// ECMA 359: 80 mm (1,46 Gbytes per side) and 120 mm (4,70 Gbytes per side) DVD Recordable Disk (DVD-R) /// ECMA 364: Data Interchange on 120 mm and 80 mm Optical Disk using +R DL Format - Capacity 8,55 and 2,66 Gbytes per /// Side /// ECMA 365: Data Interchange on 60 mm Read-Only ODC - Capacity: 1,8 Gbytes (UMD™) /// ECMA 371: Data Interchange on 120 mm and 80 mm Optical Disk using +RW HS Format - Capacity 4,7 and 1,46 Gbytes per /// side /// ECMA 374: Data Interchange on 120 mm and 80 mm Optical Disk using +RW DL Format - Capacity 8,55 and 2,66 Gbytes per /// side /// ECMA 382: 120 mm (8,54 Gbytes per side) and 80 mm (2,66 Gbytes per side) DVD Recordable Disk for Dual Layer (DVD-R /// for DL) /// ECMA 384: 120 mm (8,54 Gbytes per side) and 80 mm (2,66 Gbytes per side) DVD Re-recordable Disk for Dual Layer /// (DVD-RW for DL) /// [SuppressMessage("ReSharper", "InconsistentNaming")] [SuppressMessage("ReSharper", "MemberCanBeInternal")] [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] [SuppressMessage("ReSharper", "NotAccessedField.Global")] public static class PFI { public struct PhysicalFormatInformation { /// /// Bytes 0 to 1 /// Data length /// public ushort DataLength; /// /// Byte 2 /// Reserved /// public byte Reserved1; /// /// Byte 3 /// Reserved /// public byte Reserved2; #region PFI common to all /// /// Byte 4, bits 7 to 4 /// Disk category field /// public DiskCategory DiskCategory; /// /// Byte 4, bits 3 to 0 /// Media version /// public byte PartVersion; /// /// Byte 5, bits 7 to 4 /// 120mm if 0, 80mm if 1. If UMD (60mm) 0 also. Reserved rest of values /// public DVDSize DiscSize; /// /// Byte 5, bits 3 to 0 /// Maximum data rate /// public MaximumRateField MaximumRate; /// /// Byte 6, bit 7 /// Reserved /// public bool Reserved3; /// /// Byte 6, bits 6 to 5 /// Number of layers /// public byte Layers; /// /// Byte 6, bit 4 /// Track path /// public bool TrackPath; /// /// Byte 6, bits 3 to 0 /// Layer type /// public LayerTypeFieldMask LayerType; /// /// Byte 7, bits 7 to 4 /// Linear density field /// public LinearDensityField LinearDensity; /// /// Byte 7, bits 3 to 0 /// Track density field /// public TrackDensityField TrackDensity; /// /// Bytes 8 to 11 /// PSN where Data Area starts /// public uint DataAreaStartPSN; /// /// Bytes 12 to 15 /// PSN where Data Area ends /// public uint DataAreaEndPSN; /// /// Bytes 16 to 19 /// PSN where Data Area ends in Layer 0 /// public uint Layer0EndPSN; /// /// Byte 20, bit 7 /// True if BCA exists. GC/Wii discs do not have this bit set, but there is a BCA, making it unreadable in normal DVD /// drives /// public bool BCA; /// /// Byte 20, bits 6 to 0 /// Reserved /// public byte Reserved4; #endregion PFI common to all #region UMD PFI /// /// Bytes 21 to 22 /// UMD only, media attribute, application-defined, part of media specific in rest of discs /// public ushort MediaAttribute; #endregion UMD PFI #region DVD-RAM PFI /// /// Byte 36 /// Disc type, respecting case recordability /// public DVDRAMDiscType DiscType; #endregion DVD-RAM PFI #region DVD-RAM PFI, Version 0001b /// /// Byte 52 /// Byte 504 in Version 0110b /// Linear velocity, in tenths of m/s /// public byte Velocity; /// /// Byte 53 /// Byte 505 in Version 0110b /// Read power on disk surface, tenths of mW /// public byte ReadPower; /// /// Byte 54 /// Byte 507 in Version 0110b /// Peak power on disk surface for recording land tracks /// public byte PeakPower; /// /// Byte 55 /// Bias power on disk surface for recording land tracks /// public byte BiasPower; /// /// Byte 56 /// First pulse starting time for recording on land tracks, ns /// public byte FirstPulseStart; /// /// Byte 57 /// Byte 515 in Version 0110b /// First pulse ending time for recording on land tracks /// public byte FirstPulseEnd; /// /// Byte 58 /// Byte 518 in Version 0110b /// Multiple-pulse duration time for recording on land tracks /// public byte MultiplePulseDuration; /// /// Byte 59 /// Byte 519 in Version 0110b /// Last pulse starting time for recording on land tracks /// public byte LastPulseStart; /// /// Byte 60 /// Las pulse ending time for recording on land tracks /// public byte LastPulseEnd; /// /// Byte 61 /// Bias power duration for recording on land tracks /// public byte BiasPowerDuration; /// /// Byte 62 /// Byte 511 on Version 0110b /// Peak power for recording on groove tracks /// public byte PeakPowerGroove; /// /// Byte 63 /// Bias power for recording on groove tracks /// public byte BiasPowerGroove; /// /// Byte 64 /// First pulse starting time on groove tracks /// public byte FirstPulseStartGroove; /// /// Byte 65 /// First pulse ending time on groove tracks /// public byte FirstPulseEndGroove; /// /// Byte 66 /// Multiple-pulse duration time on groove tracks /// public byte MultiplePulseDurationGroove; /// /// Byte 67 /// Last pulse starting time on groove tracks /// public byte LastPulseStartGroove; /// /// Byte 68 /// Last pulse ending time on groove tracks /// public byte LastPulseEndGroove; /// /// Byte 69 /// Bias power duration for recording on groove tracks /// public byte BiasPowerDurationGroove; #endregion DVD-RAM PFI, Version 0001b #region DVD-R PFI, DVD-RW PFI /// /// Bytes 36 to 39 /// Sector number of the first sector of the current Border Out /// public uint CurrentBorderOutSector; /// /// Bytes 40 to 43 /// Sector number of the first sector of the next Border In /// public uint NextBorderInSector; #endregion DVD-R PFI, DVD-RW PFI #region DVD+RW PFI /// /// Byte 36 /// Linear velocities /// 0 = CLV from 4,90 m/s to 6,25 m/s /// 1 = CAV from 3,02 m/s to 7,35 m/s /// public byte RecordingVelocity; /// /// Byte 37 /// Maximum read power in milliwatts at maximum velocity /// mW = 20 * (value - 1) /// public byte ReadPowerMaxVelocity; /// /// Byte 38 /// Indicative value of Ptarget in mW at maximum velocity /// public byte PIndMaxVelocity; /// /// Byte 39 /// Peak power multiplication factor at maximum velocity /// public byte PMaxVelocity; /// /// Byte 40 /// Bias1/write power ration at maximum velocity /// public byte E1MaxVelocity; /// /// Byte 41 /// Bias2/write power ration at maximum velocity /// public byte E2MaxVelocity; /// /// Byte 42 /// Target value for γ, γtarget at the maximum velocity /// public byte YTargetMaxVelocity; /// /// Byte 43 /// Maximum read power in milliwatts at reference velocity (4,90 m/s) /// mW = 20 * (value - 1) /// public byte ReadPowerRefVelocity; /// /// Byte 44 /// Indicative value of Ptarget in mW at reference velocity (4,90 m/s) /// public byte PIndRefVelocity; /// /// Byte 45 /// Peak power multiplication factor at reference velocity (4,90 m/s) /// public byte PRefVelocity; /// /// Byte 46 /// Bias1/write power ration at reference velocity (4,90 m/s) /// public byte E1RefVelocity; /// /// Byte 47 /// Bias2/write power ration at reference velocity (4,90 m/s) /// public byte E2RefVelocity; /// /// Byte 48 /// Target value for γ, γtarget at the reference velocity (4,90 m/s) /// public byte YTargetRefVelocity; /// /// Byte 49 /// Maximum read power in milliwatts at minimum velocity /// mW = 20 * (value - 1) /// public byte ReadPowerMinVelocity; /// /// Byte 50 /// Indicative value of Ptarget in mW at minimum velocity /// public byte PIndMinVelocity; /// /// Byte 51 /// Peak power multiplication factor at minimum velocity /// public byte PMinVelocity; /// /// Byte 52 /// Bias1/write power ration at minimum velocity /// public byte E1MinVelocity; /// /// Byte 53 /// Bias2/write power ration at minimum velocity /// public byte E2MinVelocity; /// /// Byte 54 /// Target value for γ, γtarget at the minimum velocity /// public byte YTargetMinVelocity; #endregion DVD+RW PFI #region DVD-RAM PFI, version 0110b /// /// Byte 506, bit 7 /// Mode of adaptative write pulse control /// public bool AdaptativeWritePulseControlFlag; /// /// Byte 508 /// Bias power 1 on disk surface for recording land tracks /// public byte BiasPower1; /// /// Byte 509 /// Bias power 2 on disk surface for recording land tracks /// public byte BiasPower2; /// /// Byte 510 /// Bias power 3 on disk surface for recording land tracks /// public byte BiasPower3; /// /// Byte 512 /// Bias power 1 on disk surface for recording groove tracks /// public byte BiasPower1Groove; /// /// Byte 513 /// Bias power 2 on disk surface for recording groove tracks /// public byte BiasPower2Groove; /// /// Byte 514 /// Bias power 3 on disk surface for recording groove tracks /// public byte BiasPower3Groove; /// /// Byte 516 /// First pulse duration /// public byte FirstPulseDuration; /// /// Byte 520 /// Bias power 2 duration on land tracks at Velocity 1 /// public byte BiasPower2Duration; /// /// Byte 521 /// First pulse start time, at Mark 3T and Leading Space 3T /// public byte FirstPulseStart3TSpace3T; /// /// Byte 522 /// First pulse start time, at Mark 4T and Leading Space 3T /// public byte FirstPulseStart4TSpace3T; /// /// Byte 523 /// First pulse start time, at Mark 5T and Leading Space 3T /// public byte FirstPulseStart5TSpace3T; /// /// Byte 524 /// First pulse start time, at Mark >5T and Leading Space 3T /// public byte FirstPulseStartSpace3T; /// /// Byte 525 /// First pulse start time, at Mark 3T and Leading Space 4T /// public byte FirstPulseStart3TSpace4T; /// /// Byte 526 /// First pulse start time, at Mark 4T and Leading Space 4T /// public byte FirstPulseStart4TSpace4T; /// /// Byte 527 /// First pulse start time, at Mark 5T and Leading Space 4T /// public byte FirstPulseStart5TSpace4T; /// /// Byte 528 /// First pulse start time, at Mark >5T and Leading Space 4T /// public byte FirstPulseStartSpace4T; /// /// Byte 529 /// First pulse start time, at Mark 3T and Leading Space 5T /// public byte FirstPulseStart3TSpace5T; /// /// Byte 530 /// First pulse start time, at Mark 4T and Leading Space 5T /// public byte FirstPulseStart4TSpace5T; /// /// Byte 531 /// First pulse start time, at Mark 5T and Leading Space 5T /// public byte FirstPulseStart5TSpace5T; /// /// Byte 532 /// First pulse start time, at Mark >5T and Leading Space 5T /// public byte FirstPulseStartSpace5T; /// /// Byte 533 /// First pulse start time, at Mark 3T and Leading Space >5T /// public byte FirstPulseStart3TSpace; /// /// Byte 534 /// First pulse start time, at Mark 4T and Leading Space >5T /// public byte FirstPulseStart4TSpace; /// /// Byte 535 /// First pulse start time, at Mark 5T and Leading Space >5T /// public byte FirstPulseStart5TSpace; /// /// Byte 536 /// First pulse start time, at Mark >5T and Leading Space >5T /// public byte FirstPulseStartSpace; /// /// Byte 537 /// First pulse start time, at Mark 3T and Trailing Space 3T /// public byte FirstPulse3TStartTSpace3T; /// /// Byte 538 /// First pulse start time, at Mark 4T and Trailing Space 3T /// public byte FirstPulse4TStartTSpace3T; /// /// Byte 539 /// First pulse start time, at Mark 5T and Trailing Space 3T /// public byte FirstPulse5TStartTSpace3T; /// /// Byte 540 /// First pulse start time, at Mark >5T and Trailing Space 3T /// public byte FirstPulseStartTSpace3T; /// /// Byte 541 /// First pulse start time, at Mark 3T and Trailing Space 4T /// public byte FirstPulse3TStartTSpace4T; /// /// Byte 542 /// First pulse start time, at Mark 4T and Trailing Space 4T /// public byte FirstPulse4TStartTSpace4T; /// /// Byte 543 /// First pulse start time, at Mark 5T and Trailing Space 4T /// public byte FirstPulse5TStartTSpace4T; /// /// Byte 544 /// First pulse start time, at Mark >5T and Trailing Space 4T /// public byte FirstPulseStartTSpace4T; /// /// Byte 545 /// First pulse start time, at Mark 3T and Trailing Space 5T /// public byte FirstPulse3TStartTSpace5T; /// /// Byte 546 /// First pulse start time, at Mark 4T and Trailing Space 5T /// public byte FirstPulse4TStartTSpace5T; /// /// Byte 547 /// First pulse start time, at Mark 5T and Trailing Space 5T /// public byte FirstPulse5TStartTSpace5T; /// /// Byte 548 /// First pulse start time, at Mark >5T and Trailing Space 5T /// public byte FirstPulseStartTSpace5T; /// /// Byte 549 /// First pulse start time, at Mark 3T and Trailing Space >5T /// public byte FirstPulse3TStartTSpace; /// /// Byte 550 /// First pulse start time, at Mark 4T and Trailing Space >5T /// public byte FirstPulse4TStartTSpace; /// /// Byte 551 /// First pulse start time, at Mark 5T and Trailing Space >5T /// public byte FirstPulse5TStartTSpace; /// /// Byte 552 /// First pulse start time, at Mark >5T and Trailing Space >5T /// public byte FirstPulseStartTSpace; /// /// Bytes 553 to 600 /// Disk manufacturer's name, space-padded /// public string DiskManufacturer; /// /// Bytes 601 to 616 /// Disk manufacturer's supplementary information /// public string DiskManufacturerSupplementary; /// /// Bytes 617 to 627 /// Write power control parameters /// public byte[] WritePowerControlParams; /// /// Byte 619 /// Ratio of peak power for land tracks to threshold peak power for land tracks /// public byte PowerRatioLandThreshold; /// /// Byte 620 /// Target asymmetry /// public byte TargetAsymmetry; /// /// Byte 621 /// Temporary peak power /// public byte TemporaryPeakPower; /// /// Byte 622 /// Temporary bias power 1 /// public byte TemporaryBiasPower1; /// /// Byte 623 /// Temporary bias power 2 /// public byte TemporaryBiasPower2; /// /// Byte 624 /// Temporary bias power 3 /// public byte TemporaryBiasPower3; /// /// Byte 625 /// Ratio of peak power for groove tracks to threshold peak power for groove tracks /// public byte PowerRatioGrooveThreshold; /// /// Byte 626 /// Ratio of peak power for land tracks to threshold 6T peak power for land tracks /// public byte PowerRatioLandThreshold6T; /// /// Byte 627 /// Ratio of peak power for groove tracks to threshold 6T peak power for groove tracks /// public byte PowerRatioGrooveThreshold6T; #endregion DVD-RAM PFI, version 0110b #region DVD+RW PFI, DVD+R PFI, DVD+R DL PFI and DVD+RW DL PFI /// /// Byte 20, bit 6 /// If set indicates data zone contains extended information for VCPS /// public bool VCPS; /// /// Byte 21 /// Indicates restricted usage disk /// public byte ApplicationCode; /// /// Byte 22 /// Bitmap of extended information block presence /// public byte ExtendedInformation; /// /// Bytes 23 to 30 /// Disk manufacturer ID, null-padded /// public string DiskManufacturerID; /// /// Bytes 31 to 33 /// Media type ID, null-padded /// public string MediaTypeID; /// /// Byte 34 /// Product revision number /// public byte ProductRevision; /// /// Byte 35 /// Indicates how many bytes, up to 63, are used in ADIP's PFI /// public byte PFIUsedInADIP; #endregion DVD+RW PFI, DVD+R PFI, DVD+R DL PFI and DVD+RW DL PFI #region DVD+RW PFI, version 0010b /// /// Byte 55 /// Ttop first pulse duration /// public byte TopFirstPulseDuration; /// /// Byte 56 /// Tmp multi pulse duration /// public byte MultiPulseDuration; /// /// Byte 57 /// dTtop first pulse lead time /// public byte FirstPulseLeadTime; /// /// Byte 58 /// dTera erase lead time at reference velocity /// public byte EraseLeadTimeRefVelocity; /// /// Byte 59 /// dTera erase lead time at upper velocity /// public byte EraseLeadTimeUppVelocity; #endregion DVD+RW PFI, version 0010b #region DVD+R PFI version 0001b and DVD+R DL PFI version 0001b /// /// Byte 36 /// Primary recording velocity for the basic write strategy /// public byte PrimaryVelocity; /// /// Byte 37 /// Upper recording velocity for the basic write strategy /// public byte UpperVelocity; /// /// Byte 38 /// Wavelength λIND /// public byte Wavelength; /// /// Byte 39 /// Normalized write power dependency on wavelength (dP/dλ)/(PIND/λIND) /// public byte NormalizedPowerDependency; /// /// Byte 40 /// Maximum read power at primary velocity /// public byte MaximumPowerAtPrimaryVelocity; /// /// Byte 41 /// Pind at primary velocity /// public byte PindAtPrimaryVelocity; /// /// Byte 42 /// βtarget at primary velocity /// public byte BtargetAtPrimaryVelocity; /// /// Byte 43 /// Maximum read power at upper velocity /// public byte MaximumPowerAtUpperVelocity; /// /// Byte 44 /// Pind at primary velocity /// public byte PindAtUpperVelocity; /// /// Byte 45 /// βtarget at upper velocity /// public byte BtargetAtUpperVelocity; /// /// Byte 46 /// Ttop (≥4T) first pulse duration for cm∗ ≥4T at Primary velocity /// public byte FirstPulseDuration4TPrimaryVelocity; /// /// Byte 47 /// Ttop (=3T) first pulse duration for cm∗ =3T at Primary velocity /// public byte FirstPulseDuration3TPrimaryVelocity; /// /// Byte 48 /// Tmp multi pulse duration at Primary velocity /// public byte MultiPulseDurationPrimaryVelocity; /// /// Byte 49 /// Tlp last pulse duration at Primary velocity /// public byte LastPulseDurationPrimaryVelocity; /// /// Byte 50 /// dTtop (≥4T) first pulse lead time for cm∗ ≥4T at Primary velocity /// public byte FirstPulseLeadTime4TPrimaryVelocity; /// /// Byte 51 /// dTtop (=3T) first pulse lead time for cm∗ =3T at Primary velocity /// public byte FirstPulseLeadTime3TPrimaryVelocity; /// /// Byte 52 /// dTle first pulse leading edge shift for ps∗ =3T at Primary velocity /// public byte FirstPulseLeadingEdgePrimaryVelocity; /// /// Byte 53 /// Ttop (≥4T) first pulse duration for cm∗ ≥4T at Upper velocity /// public byte FirstPulseDuration4TUpperVelocity; /// /// Byte 54 /// Ttop (=3T) first pulse duration for cm∗ =3T at Upper velocity /// public byte FirstPulseDuration3TUpperVelocity; /// /// Byte 55 /// Tmp multi pulse duration at Upper velocity /// public byte MultiPulseDurationUpperVelocity; /// /// Byte 56 /// Tlp last pulse duration at Upper velocity /// public byte LastPulseDurationUpperVelocity; /// /// Byte 57 /// dTtop (≥4T) first pulse lead time for cm∗ ≥4T at Upper velocity /// public byte FirstPulseLeadTime4TUpperVelocity; /// /// Byte 58 /// dTtop (=3T) first pulse lead time for cm∗ =3T at Upper velocity /// public byte FirstPulseLeadTime3TUpperVelocity; /// /// Byte 59 /// dTle first pulse leading edge shift for ps∗ =3T at Upper velocity /// public byte FirstPulseLeadingEdgeUpperVelocity; #endregion DVD+R PFI version 0001b and DVD+R DL PFI version 0001b #region DVD+R DL PFI version 0001b /// /// Byte 34, bits 7 to 6 /// public DVDLayerStructure LayerStructure; #endregion DVD+R DL PFI version 0001b #region DVD+RW DL PFI /// /// Byte 36 /// Primary recording velocity for the basic write strategy /// public byte BasicPrimaryVelocity; /// /// Byte 37 /// Maximum read power at Primary velocity /// public byte MaxReadPowerPrimaryVelocity; /// /// Byte 38 /// PIND at Primary velocity /// public byte PindPrimaryVelocity; /// /// Byte 39 /// ρ at Primary velocity /// public byte PPrimaryVelocity; /// /// Byte 40 /// ε1 at Primary velocity /// public byte E1PrimaryVelocity; /// /// Byte 41 /// ε2 at Primary velocity /// public byte E2PrimaryVelocity; /// /// Byte 42 /// γtarget at Primary velocity /// public byte YtargetPrimaryVelocity; /// /// Byte 43 /// β optimum at Primary velocity /// public byte BOptimumPrimaryVelocity; /// /// Byte 46 /// Ttop first pulse duration /// public byte TFirstPulseDuration; /// /// Byte 47 /// Tmp multi pulse duration /// public byte TMultiPulseDuration; /// /// Byte 48 /// dTtop first pulse lead/lag time for any runlength ≥ 4T /// public byte FirstPulseLeadTimeAnyRun; /// /// Byte 49 /// dTtop,3 first pulse lead/lag time for runlengths = 3T /// public byte FirstPulseLeadTimeRun3T; /// /// Byte 50 /// dTlp last pulse lead/lag time for any runlength ≥ 5T /// public byte LastPulseLeadTimeAnyRun; /// /// Byte 51 /// dTlp,3 last pulse lead/lag time for runlengths = 3T /// public byte LastPulseLeadTime3T; /// /// Byte 52 /// dTlp,4 last pulse lead/lag time for runlengths = 4T /// public byte LastPulseLeadTime4T; /// /// Byte 53 /// dTera erase lead/lag time when preceding mark length ≥ 5T /// public byte ErasePulseLeadTimeAny; /// /// Byte 54 /// dTera,3 erase lead/lag time when preceding mark length = 3T /// public byte ErasePulseLeadTime3T; /// /// Byte 55 /// dTera,4 erase lead/lag time when preceding mark length = 4T /// public byte ErasePulseLeadTime4T; #endregion DVD+RW DL PFI #region DVD-R DL PFI and DVD-RW DL PFI /// /// Byte 21 /// Maximum recording speed /// public DVDRecordingSpeed MaxRecordingSpeed; /// /// Byte 22 /// Minimum recording speed /// public DVDRecordingSpeed MinRecordingSpeed; /// /// Byte 23 /// Another recording speed /// public DVDRecordingSpeed RecordingSpeed1; /// /// Byte 24 /// Another recording speed /// public DVDRecordingSpeed RecordingSpeed2; /// /// Byte 25 /// Another recording speed /// public DVDRecordingSpeed RecordingSpeed3; /// /// Byte 26 /// Another recording speed /// public DVDRecordingSpeed RecordingSpeed4; /// /// Byte 27 /// Another recording speed /// public DVDRecordingSpeed RecordingSpeed5; /// /// Byte 28 /// Another recording speed /// public DVDRecordingSpeed RecordingSpeed6; /// /// Byte 29 /// Another recording speed /// public DVDRecordingSpeed RecordingSpeed7; /// /// Byte 30 /// Class /// public byte Class; /// /// Byte 31 /// Extended version. 0x30 = ECMA-382, 0x20 = ECMA-384 /// public byte ExtendedVersion; /// /// Byte 36 /// Start sector number of current RMD in Extra Border Zone /// public uint CurrentRMDExtraBorderPSN; /// /// Byte 40 /// Start sector number of Physical Format Information blocks in Extra Border Zone /// public uint PFIExtraBorderPSN; /// /// Byte 44, bit 0 /// If NOT set, Control Data Zone is pre-recorded /// public bool PreRecordedControlDataInv; /// /// Byte 44 bit 1 /// Lead-in Zone is pre-recorded /// public bool PreRecordedLeadIn; /// /// Byte 44 bit 3 /// Lead-out Zone is pre-recorded /// public bool PreRecordedLeadOut; /// /// Byte 45 bits 0 to 3 /// AR characteristic of LPP on Layer 1 /// public byte ARCharLayer1; /// /// Byte 45 bits 4 to 7 /// Tracking polarity on Layer 1 /// public byte TrackPolarityLayer1; #endregion DVD-R DL PFI and DVD-RW DL PFI } public static PhysicalFormatInformation? Decode(byte[] response) { if(response == null) return null; if(response.Length == 2048) { byte[] tmp2 = new byte[2052]; Array.Copy(response, 0, tmp2, 4, 2048); response = tmp2; } if(response.Length < 2052) return null; PhysicalFormatInformation pfi = new PhysicalFormatInformation(); byte[] tmp; pfi.DataLength = (ushort)((response[0] << 8) + response[1]); pfi.Reserved1 = response[2]; pfi.Reserved2 = response[3]; // Common pfi.DiskCategory = (DiskCategory)((response[4] & 0xF0) >> 4); pfi.PartVersion = (byte)(response[4] & 0x0F); pfi.DiscSize = (DVDSize)((response[5] & 0xF0) >> 4); pfi.MaximumRate = (MaximumRateField)(response[5] & 0x0F); pfi.Reserved3 |= (response[6] & 0x80) == 0x80; pfi.Layers = (byte)((response[6] & 0x60) >> 5); pfi.TrackPath |= (response[6] & 0x08) == 0x08; pfi.LayerType = (LayerTypeFieldMask)(response[6] & 0x07); pfi.LinearDensity = (LinearDensityField)((response[7] & 0xF0) >> 4); pfi.TrackDensity = (TrackDensityField)(response[7] & 0x0F); pfi.DataAreaStartPSN = (uint)((response[8] << 24) + (response[9] << 16) + (response[10] << 8) + response[11]); pfi.DataAreaEndPSN = (uint)((response[12] << 24) + (response[13] << 16) + (response[14] << 8) + response[15]); pfi.Layer0EndPSN = (uint)((response[16] << 24) + (response[17] << 16) + (response[18] << 8) + response[19]); pfi.BCA |= (response[20] & 0x80) == 0x80; switch(pfi.DiskCategory) { // UMD case DiskCategory.UMD: pfi.MediaAttribute = (ushort)((response[21] << 8) + response[22]); break; // DVD-RAM case DiskCategory.DVDRAM: pfi.DiscType = (DVDRAMDiscType)response[36]; if(pfi.PartVersion == 1) { pfi.Velocity = response[52]; pfi.ReadPower = response[53]; pfi.PeakPower = response[54]; pfi.BiasPower = response[55]; pfi.FirstPulseStart = response[56]; pfi.FirstPulseEnd = response[57]; pfi.MultiPulseDuration = response[58]; pfi.LastPulseStart = response[59]; pfi.LastPulseEnd = response[60]; pfi.BiasPowerDuration = response[61]; pfi.PeakPowerGroove = response[62]; pfi.BiasPowerGroove = response[63]; pfi.FirstPulseStartGroove = response[64]; pfi.FirstPulseEndGroove = response[65]; pfi.MultiplePulseDurationGroove = response[66]; pfi.LastPulseStartGroove = response[67]; pfi.LastPulseEndGroove = response[68]; pfi.BiasPowerDurationGroove = response[69]; } else if(pfi.PartVersion == 6) { pfi.Velocity = response[504]; pfi.ReadPower = response[505]; pfi.AdaptativeWritePulseControlFlag |= (response[506] & 0x80) == 0x80; pfi.PeakPower = response[507]; pfi.BiasPower1 = response[508]; pfi.BiasPower2 = response[509]; pfi.BiasPower3 = response[510]; pfi.PeakPowerGroove = response[511]; pfi.BiasPower1Groove = response[512]; pfi.BiasPower2Groove = response[513]; pfi.BiasPower3Groove = response[514]; pfi.FirstPulseEnd = response[515]; pfi.FirstPulseDuration = response[516]; pfi.MultiPulseDuration = response[518]; pfi.LastPulseStart = response[519]; pfi.BiasPower2Duration = response[520]; pfi.FirstPulseStart3TSpace3T = response[521]; pfi.FirstPulseStart4TSpace3T = response[522]; pfi.FirstPulseStart5TSpace3T = response[523]; pfi.FirstPulseStartSpace3T = response[524]; pfi.FirstPulseStart3TSpace4T = response[525]; pfi.FirstPulseStart4TSpace4T = response[526]; pfi.FirstPulseStart5TSpace4T = response[527]; pfi.FirstPulseStartSpace4T = response[528]; pfi.FirstPulseStart3TSpace5T = response[529]; pfi.FirstPulseStart4TSpace5T = response[530]; pfi.FirstPulseStart5TSpace5T = response[531]; pfi.FirstPulseStartSpace5T = response[532]; pfi.FirstPulseStart3TSpace = response[533]; pfi.FirstPulseStart4TSpace = response[534]; pfi.FirstPulseStart5TSpace = response[535]; pfi.FirstPulseStartSpace = response[536]; pfi.FirstPulse3TStartTSpace3T = response[537]; pfi.FirstPulse4TStartTSpace3T = response[538]; pfi.FirstPulse5TStartTSpace3T = response[539]; pfi.FirstPulseStartTSpace3T = response[540]; pfi.FirstPulse3TStartTSpace4T = response[541]; pfi.FirstPulse4TStartTSpace4T = response[542]; pfi.FirstPulse5TStartTSpace4T = response[543]; pfi.FirstPulseStartTSpace4T = response[544]; pfi.FirstPulse3TStartTSpace5T = response[545]; pfi.FirstPulse4TStartTSpace5T = response[546]; pfi.FirstPulse5TStartTSpace5T = response[547]; pfi.FirstPulseStartTSpace5T = response[548]; pfi.FirstPulse3TStartTSpace = response[549]; pfi.FirstPulse4TStartTSpace = response[550]; pfi.FirstPulse5TStartTSpace = response[551]; pfi.FirstPulseStartTSpace = response[552]; tmp = new byte[48]; Array.Copy(response, 553, tmp, 0, 48); pfi.DiskManufacturer = StringHandlers.SpacePaddedToString(tmp); tmp = new byte[16]; Array.Copy(response, 601, tmp, 0, 16); pfi.DiskManufacturerSupplementary = StringHandlers.SpacePaddedToString(tmp); pfi.WritePowerControlParams = new byte[2]; pfi.WritePowerControlParams[0] = response[617]; pfi.WritePowerControlParams[1] = response[618]; pfi.PowerRatioLandThreshold = response[619]; pfi.TargetAsymmetry = response[620]; pfi.TemporaryPeakPower = response[621]; pfi.TemporaryBiasPower1 = response[622]; pfi.TemporaryBiasPower2 = response[623]; pfi.TemporaryBiasPower3 = response[624]; pfi.PowerRatioGrooveThreshold = response[625]; pfi.PowerRatioLandThreshold6T = response[626]; pfi.PowerRatioGrooveThreshold6T = response[627]; } break; // DVD-R and DVD-RW case DiskCategory.DVDR when pfi.PartVersion < 6: case DiskCategory.DVDRW when pfi.PartVersion < 3: pfi.CurrentBorderOutSector = (uint)((response[36] << 24) + (response[37] << 16) + (response[38] << 8) + response[39]); pfi.NextBorderInSector = (uint)((response[40] << 24) + (response[41] << 16) + (response[42] << 8) + response[43]); break; // DVD+RW case DiskCategory.DVDPRW: pfi.RecordingVelocity = response[36]; pfi.ReadPowerMaxVelocity = response[37]; pfi.PIndMaxVelocity = response[38]; pfi.PMaxVelocity = response[39]; pfi.E1MaxVelocity = response[40]; pfi.E2MaxVelocity = response[41]; pfi.YTargetMaxVelocity = response[42]; pfi.ReadPowerRefVelocity = response[43]; pfi.PIndRefVelocity = response[44]; pfi.PRefVelocity = response[45]; pfi.E1RefVelocity = response[46]; pfi.E2RefVelocity = response[47]; pfi.YTargetRefVelocity = response[48]; pfi.ReadPowerMinVelocity = response[49]; pfi.PIndMinVelocity = response[50]; pfi.PMinVelocity = response[51]; pfi.E1MinVelocity = response[52]; pfi.E2MinVelocity = response[53]; pfi.YTargetMinVelocity = response[54]; break; } // DVD+R, DVD+RW, DVD+R DL and DVD+RW DL if(pfi.DiskCategory == DiskCategory.DVDPR || pfi.DiskCategory == DiskCategory.DVDPRW || pfi.DiskCategory == DiskCategory.DVDPRDL || pfi.DiskCategory == DiskCategory.DVDPRWDL) { pfi.VCPS |= (response[20] & 0x40) == 0x40; pfi.ApplicationCode = response[21]; pfi.ExtendedInformation = response[22]; tmp = new byte[8]; Array.Copy(response, 23, tmp, 0, 8); pfi.DiskManufacturerID = StringHandlers.CToString(tmp); tmp = new byte[3]; Array.Copy(response, 31, tmp, 0, 3); pfi.MediaTypeID = StringHandlers.CToString(tmp); pfi.ProductRevision = pfi.DiskCategory == DiskCategory.DVDPRDL ? (byte)(response[34] & 0x3F) : response[34]; pfi.PFIUsedInADIP = response[35]; } switch(pfi.DiskCategory) { // DVD+RW case DiskCategory.DVDPRW when pfi.PartVersion == 2: pfi.TopFirstPulseDuration = response[55]; pfi.MultiPulseDuration = response[56]; pfi.FirstPulseLeadTime = response[57]; pfi.EraseLeadTimeRefVelocity = response[58]; pfi.EraseLeadTimeUppVelocity = response[59]; break; // DVD+R and DVD+R DL case DiskCategory.DVDPR: case DiskCategory.DVDPRDL: pfi.PrimaryVelocity = response[36]; pfi.UpperVelocity = response[37]; pfi.Wavelength = response[38]; pfi.NormalizedPowerDependency = response[39]; pfi.MaximumPowerAtPrimaryVelocity = response[40]; pfi.PindAtPrimaryVelocity = response[41]; pfi.BtargetAtPrimaryVelocity = response[42]; pfi.MaximumPowerAtUpperVelocity = response[43]; pfi.PindAtUpperVelocity = response[44]; pfi.BtargetAtUpperVelocity = response[45]; pfi.FirstPulseDuration4TPrimaryVelocity = response[46]; pfi.FirstPulseDuration3TPrimaryVelocity = response[47]; pfi.MultiPulseDurationPrimaryVelocity = response[48]; pfi.LastPulseDurationPrimaryVelocity = response[49]; pfi.FirstPulseLeadTime4TPrimaryVelocity = response[50]; pfi.FirstPulseLeadTime3TPrimaryVelocity = response[51]; pfi.FirstPulseLeadingEdgePrimaryVelocity = response[52]; pfi.FirstPulseDuration4TUpperVelocity = response[53]; pfi.FirstPulseDuration3TUpperVelocity = response[54]; pfi.MultiPulseDurationUpperVelocity = response[55]; pfi.LastPulseDurationUpperVelocity = response[56]; pfi.FirstPulseLeadTime4TUpperVelocity = response[57]; pfi.FirstPulseLeadTime3TUpperVelocity = response[58]; pfi.FirstPulseLeadingEdgeUpperVelocity = response[59]; break; } switch(pfi.DiskCategory) { // DVD+R DL case DiskCategory.DVDPRDL: pfi.LayerStructure = (DVDLayerStructure)((response[34] & 0xC0) >> 6); break; // DVD+RW DL case DiskCategory.DVDPRWDL: pfi.BasicPrimaryVelocity = response[36]; pfi.MaxReadPowerPrimaryVelocity = response[37]; pfi.PindPrimaryVelocity = response[38]; pfi.PPrimaryVelocity = response[39]; pfi.E1PrimaryVelocity = response[40]; pfi.E2PrimaryVelocity = response[41]; pfi.YtargetPrimaryVelocity = response[42]; pfi.BOptimumPrimaryVelocity = response[43]; pfi.TFirstPulseDuration = response[46]; pfi.TMultiPulseDuration = response[47]; pfi.FirstPulseLeadTimeAnyRun = response[48]; pfi.FirstPulseLeadTimeRun3T = response[49]; pfi.LastPulseLeadTimeAnyRun = response[50]; pfi.LastPulseLeadTime3T = response[51]; pfi.LastPulseLeadTime4T = response[52]; pfi.ErasePulseLeadTimeAny = response[53]; pfi.ErasePulseLeadTime3T = response[54]; pfi.ErasePulseLeadTime4T = response[55]; break; // DVD-R DL and DVD-RW DL case DiskCategory.DVDR when pfi.PartVersion == 6: case DiskCategory.DVDRW when pfi.PartVersion == 3: pfi.MaxRecordingSpeed = (DVDRecordingSpeed)response[21]; pfi.MinRecordingSpeed = (DVDRecordingSpeed)response[22]; pfi.RecordingSpeed1 = (DVDRecordingSpeed)response[23]; pfi.RecordingSpeed2 = (DVDRecordingSpeed)response[24]; pfi.RecordingSpeed3 = (DVDRecordingSpeed)response[25]; pfi.RecordingSpeed4 = (DVDRecordingSpeed)response[26]; pfi.RecordingSpeed5 = (DVDRecordingSpeed)response[27]; pfi.RecordingSpeed6 = (DVDRecordingSpeed)response[28]; pfi.RecordingSpeed7 = (DVDRecordingSpeed)response[29]; pfi.Class = response[30]; pfi.ExtendedVersion = response[31]; pfi.CurrentBorderOutSector = (uint)((response[36] << 24) + (response[37] << 16) + (response[38] << 8) + response[39]); pfi.NextBorderInSector = (uint)((response[40] << 24) + (response[41] << 16) + (response[42] << 8) + response[43]); pfi.PreRecordedControlDataInv |= (response[44] & 0x01) == 0x01; pfi.PreRecordedLeadIn |= (response[44] & 0x02) == 0x02; pfi.PreRecordedLeadOut |= (response[44] & 0x08) == 0x08; pfi.ARCharLayer1 = (byte)(response[45] & 0x0F); pfi.TrackPolarityLayer1 = (byte)((response[45] & 0xF0) >> 4); break; } return pfi; } public static string Prettify(PhysicalFormatInformation? pfi) { if(pfi == null) return null; PhysicalFormatInformation decoded = pfi.Value; StringBuilder sb = new StringBuilder(); string sizeString; switch(decoded.DiscSize) { case DVDSize.Eighty: sizeString = "80mm"; break; case DVDSize.OneTwenty: sizeString = "120mm"; break; default: sizeString = $"unknown size identifier {decoded.DiscSize}"; break; } string categorySentence = "Disc is a {0} {1} version {2}"; switch(decoded.DiskCategory) { case DiskCategory.DVDROM: sb.AppendFormat(categorySentence, sizeString, "DVD-ROM", decoded.PartVersion).AppendLine(); switch(decoded.DiscSize) { case DVDSize.OneTwenty when decoded.PartVersion == 1: sb.AppendLine("Disc claims conformation to ECMA-267"); break; case DVDSize.Eighty when decoded.PartVersion == 1: sb.AppendLine("Disc claims conformation to ECMA-268"); break; } break; case DiskCategory.DVDRAM: sb.AppendFormat(categorySentence, sizeString, "DVD-RAM", decoded.PartVersion).AppendLine(); switch(decoded.PartVersion) { case 1: sb.AppendLine("Disc claims conformation to ECMA-272"); break; case 6: sb.AppendLine("Disc claims conformation to ECMA-330"); break; } break; case DiskCategory.DVDR: if(decoded.PartVersion >= 6) sb.AppendFormat(categorySentence, sizeString, "DVD-R DL", decoded.PartVersion).AppendLine(); else sb.AppendFormat(categorySentence, sizeString, "DVD-R", decoded.PartVersion).AppendLine(); switch(decoded.PartVersion) { case 1: sb.AppendLine("Disc claims conformation to ECMA-279"); break; case 5: sb.AppendLine("Disc claims conformation to ECMA-359"); break; case 6: sb.AppendLine("Disc claims conformation to ECMA-382"); break; } break; case DiskCategory.DVDRW: if(decoded.PartVersion >= 3) sb.AppendFormat(categorySentence, sizeString, "DVD-RW DL", decoded.PartVersion).AppendLine(); else sb.AppendFormat(categorySentence, sizeString, "DVD-RW", decoded.PartVersion).AppendLine(); switch(decoded.PartVersion) { case 2: sb.AppendLine("Disc claims conformation to ECMA-338"); break; case 3: sb.AppendLine("Disc claims conformation to ECMA-384"); break; } break; case DiskCategory.UMD: if(decoded.DiscSize == DVDSize.OneTwenty) sb.AppendFormat(categorySentence, "60mm", "UMD", decoded.PartVersion).AppendLine(); else sb.AppendFormat(categorySentence, "invalid size", "UMD", decoded.PartVersion).AppendLine(); switch(decoded.PartVersion) { case 0: sb.AppendLine("Disc claims conformation to ECMA-365"); break; } break; case DiskCategory.DVDPRW: sb.AppendFormat(categorySentence, sizeString, "DVD+RW", decoded.PartVersion).AppendLine(); switch(decoded.PartVersion) { case 1: sb.AppendLine("Disc claims conformation to ECMA-274"); break; case 2: sb.AppendLine("Disc claims conformation to ECMA-337"); break; case 3: sb.AppendLine("Disc claims conformation to ECMA-371"); break; } break; case DiskCategory.DVDPR: sb.AppendFormat(categorySentence, sizeString, "DVD+R", decoded.PartVersion).AppendLine(); switch(decoded.PartVersion) { case 1: sb.AppendLine("Disc claims conformation to ECMA-349"); break; } break; case DiskCategory.DVDPRWDL: sb.AppendFormat(categorySentence, sizeString, "DVD+RW DL", decoded.PartVersion).AppendLine(); switch(decoded.PartVersion) { case 1: sb.AppendLine("Disc claims conformation to ECMA-374"); break; } break; case DiskCategory.DVDPRDL: sb.AppendFormat(categorySentence, sizeString, "DVD+R DL", decoded.PartVersion).AppendLine(); switch(decoded.PartVersion) { case 1: sb.AppendLine("Disc claims conformation to ECMA-364"); break; } break; case DiskCategory.Nintendo: if(decoded.PartVersion == 15) if(decoded.DiscSize == DVDSize.Eighty) sb.AppendLine("Disc is a Nintendo Gamecube Optical Disc (GOD)"); else if(decoded.DiscSize == DVDSize.OneTwenty) sb.AppendLine("Disc is a Nintendo Wii Optical Disc (WOD)"); else goto default; else goto default; break; case DiskCategory.HDDVDROM: sb.AppendFormat(categorySentence, sizeString, "HD DVD-ROM", decoded.PartVersion).AppendLine(); break; case DiskCategory.HDDVDRAM: sb.AppendFormat(categorySentence, sizeString, "HD DVD-RAM", decoded.PartVersion).AppendLine(); break; case DiskCategory.HDDVDR: sb.AppendFormat(categorySentence, sizeString, "HD DVD-R", decoded.PartVersion).AppendLine(); break; case DiskCategory.HDDVDRW: sb.AppendFormat(categorySentence, sizeString, "HD DVD-RW", decoded.PartVersion).AppendLine(); break; default: sb.AppendFormat(categorySentence, sizeString, "unknown disc type", decoded.PartVersion) .AppendLine(); break; } switch(decoded.MaximumRate) { case MaximumRateField.TwoMbps: sb.AppendLine("Disc maximum transfer rate is 2,52 Mbit/sec."); break; case MaximumRateField.FiveMbps: sb.AppendLine("Disc maximum transfer rate is 5,04 Mbit/sec."); break; case MaximumRateField.TenMbps: sb.AppendLine("Disc maximum transfer rate is 10,08 Mbit/sec."); break; case MaximumRateField.TwentyMbps: sb.AppendLine("Disc maximum transfer rate is 20,16 Mbit/sec."); break; case MaximumRateField.ThirtyMbps: sb.AppendLine("Disc maximum transfer rate is 30,24 Mbit/sec."); break; case MaximumRateField.Unspecified: sb.AppendLine("Disc maximum transfer rate is unspecified."); break; default: sb.AppendFormat("Disc maximum transfer rate is specified by unknown key {0}", decoded.MaximumRate) .AppendLine(); break; } sb.AppendFormat("Disc has {0} layers", decoded.Layers + 1).AppendLine(); if(decoded.TrackPath && decoded.Layers == 1) sb.AppendLine("Layers are in parallel track path"); else if(!decoded.TrackPath && decoded.Layers == 1) sb.AppendLine("Layers are in opposite track path"); switch(decoded.LinearDensity) { case LinearDensityField.TwoSix: sb.AppendLine("Pitch size is 0,267 μm/bit"); break; case LinearDensityField.TwoNine: sb.AppendLine("Pitch size is 0,147 μm/bit"); break; case LinearDensityField.FourZero: sb.AppendLine("Pitch size is between 0,409 μm/bit and 0,435 μm/bit"); break; case LinearDensityField.TwoEight: sb.AppendLine("Pitch size is between 0,140 μm/bit and 0,148 μm/bit"); break; case LinearDensityField.OneFive: sb.AppendLine("Pitch size is 0,153 μm/bit"); break; case LinearDensityField.OneThree: sb.AppendLine("Pitch size is between 0,130 μm/bit and 0,140 μm/bit"); break; case LinearDensityField.ThreeFive: sb.AppendLine("Pitch size is 0,353 μm/bit"); break; default: sb.AppendFormat("Unknown pitch size key {0}", decoded.LinearDensity).AppendLine(); break; } switch(decoded.TrackDensity) { case TrackDensityField.Seven: sb.AppendLine("Track size is 0,74 μm"); break; case TrackDensityField.Eight: sb.AppendLine("Track size is 0,80 μm"); break; case TrackDensityField.Six: sb.AppendLine("Track size is 0,615 μm"); break; case TrackDensityField.Four: sb.AppendLine("Track size is 0,40 μm"); break; case TrackDensityField.Three: sb.AppendLine("Track size is 0,34 μm"); break; default: sb.AppendFormat("Unknown track size key {0}", decoded.LinearDensity).AppendLine(); break; } if(decoded.DataAreaStartPSN > 0) if(decoded.DataAreaEndPSN > 0) { sb.AppendFormat("Data area starts at PSN {0:X}h", decoded.DataAreaStartPSN).AppendLine(); sb.AppendFormat("Data area ends at PSN {0:X}h", decoded.DataAreaEndPSN).AppendLine(); if(decoded.Layers == 1 && !decoded.TrackPath) sb.AppendFormat("Layer 0 ends at PSN {0:X}h", decoded.Layer0EndPSN).AppendLine(); } else sb.AppendLine("Disc is empty"); else sb.AppendLine("Disc is empty"); if(decoded.BCA) sb.AppendLine("Disc has a burst cutting area"); switch(decoded.DiskCategory) { case DiskCategory.UMD: sb.AppendFormat("Media attribute is {0}", decoded.MediaAttribute).AppendLine(); break; case DiskCategory.DVDRAM: switch(decoded.DiscType) { case DVDRAMDiscType.Cased: sb.AppendLine("Disc shall be recorded with a case"); break; case DVDRAMDiscType.Uncased: sb.AppendLine("Disc can be recorded with or without a case"); break; default: sb.AppendFormat("Unknown DVD-RAM case type key {0}", decoded.DiscType).AppendLine(); break; } if(decoded.PartVersion == 6) { sb.AppendFormat("Disc manufacturer is {0}", decoded.DiskManufacturer).AppendLine(); sb.AppendFormat("Disc manufacturer supplementary information is {0}", decoded.DiskManufacturerSupplementary).AppendLine(); } break; case DiskCategory.DVDR when decoded.PartVersion < 6: case DiskCategory.DVDRW when decoded.PartVersion < 3: sb.AppendFormat("Current Border-Out first sector is PSN {0:X}h", decoded.CurrentBorderOutSector) .AppendLine(); sb.AppendFormat("Next Border-In first sector is PSN {0:X}h", decoded.NextBorderInSector) .AppendLine(); break; case DiskCategory.DVDPR: case DiskCategory.DVDPRW: case DiskCategory.DVDPRDL: case DiskCategory.DVDPRWDL: if(decoded.VCPS) sb.AppendLine("Disc contains extended information for VCPS"); sb.AppendFormat("Disc application code is {0}", decoded.ApplicationCode).AppendLine(); sb.AppendFormat("Disc manufacturer is {0}", decoded.DiskManufacturerID).AppendLine(); sb.AppendFormat("Disc media type is {0}", decoded.MediaTypeID).AppendLine(); sb.AppendFormat("Disc product revision is {0}", decoded.ProductRevision).AppendLine(); break; } if((decoded.DiskCategory != DiskCategory.DVDR || decoded.PartVersion < 6) && (decoded.DiskCategory != DiskCategory.DVDRW || decoded.PartVersion < 3)) return sb.ToString(); sb.AppendFormat("Current RMD in extra Border zone starts at PSN {0:X}h", decoded.CurrentRMDExtraBorderPSN) .AppendLine(); sb.AppendFormat("PFI in extra Border zone starts at PSN {0:X}h", decoded.PFIExtraBorderPSN).AppendLine(); if(!decoded.PreRecordedControlDataInv) sb.AppendLine("Control Data Zone is pre-recorded"); if(decoded.PreRecordedLeadIn) sb.AppendLine("Lead-In is pre-recorded"); if(decoded.PreRecordedLeadOut) sb.AppendLine("Lead-Out is pre-recorded"); return sb.ToString(); } public static string Prettify(byte[] response) { return Prettify(Decode(response)); } } }