// /*************************************************************************** // Aaru Data Preservation Suite // ---------------------------------------------------------------------------- // // 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-2022 Natalia Portillo // ****************************************************************************/ namespace Aaru.Decoders.DVD; using System; using System.Diagnostics.CodeAnalysis; using System.Text; using Aaru.CommonTypes; using Aaru.Helpers; // 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 static PhysicalFormatInformation? Decode(byte[] response, MediaType mediaType) { if(response == null) return null; if(response.Length == 2048) { var tmp2 = new byte[2052]; Array.Copy(response, 0, tmp2, 4, 2048); response = tmp2; } if(response.Length < 2052) return null; var 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; pfi.RecordedBookType = pfi.DiskCategory; if(mediaType != MediaType.DVDROM) switch(mediaType) { case MediaType.DVDPR: pfi.DiskCategory = DiskCategory.DVDPR; break; case MediaType.DVDPRDL: pfi.DiskCategory = DiskCategory.DVDPRDL; break; case MediaType.DVDPRW: pfi.DiskCategory = DiskCategory.DVDPRW; break; case MediaType.DVDPRWDL: pfi.DiskCategory = DiskCategory.DVDPRWDL; break; case MediaType.DVDRDL: pfi.DiskCategory = DiskCategory.DVDR; if(pfi.PartVersion < 6) pfi.PartVersion = 6; break; case MediaType.DVDR: pfi.DiskCategory = DiskCategory.DVDR; if(pfi.PartVersion > 5) pfi.PartVersion = 5; break; case MediaType.DVDRAM: pfi.DiskCategory = DiskCategory.DVDRAM; break; case MediaType.DVDRWDL: pfi.DiskCategory = DiskCategory.DVDRW; if(pfi.PartVersion < 15) pfi.PartVersion = 15; break; case MediaType.DVDRW: pfi.DiskCategory = DiskCategory.DVDRW; if(pfi.PartVersion > 14) pfi.PartVersion = 14; break; case MediaType.HDDVDR: pfi.DiskCategory = DiskCategory.HDDVDR; break; case MediaType.HDDVDRAM: pfi.DiskCategory = DiskCategory.HDDVDRAM; break; case MediaType.HDDVDROM: pfi.DiskCategory = DiskCategory.HDDVDROM; break; case MediaType.HDDVDRW: pfi.DiskCategory = DiskCategory.HDDVDRW; break; case MediaType.GOD: pfi.DiscSize = DVDSize.Eighty; pfi.DiskCategory = DiskCategory.Nintendo; break; case MediaType.WOD: pfi.DiscSize = DVDSize.OneTwenty; pfi.DiskCategory = DiskCategory.Nintendo; break; case MediaType.UMD: pfi.DiskCategory = DiskCategory.UMD; break; } 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 < 15: 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 is DiskCategory.DVDPR or DiskCategory.DVDPRW or DiskCategory.DVDPRDL or 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 >= 15: 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; var 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; } var 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 >= 15) 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; } if(decoded.RecordedBookType != decoded.DiskCategory) { var bookTypeSentence = "Disc book type is {0}"; switch(decoded.RecordedBookType) { case DiskCategory.DVDROM: sb.AppendFormat(bookTypeSentence, "DVD-ROM").AppendLine(); break; case DiskCategory.DVDRAM: sb.AppendFormat(bookTypeSentence, "DVD-RAM").AppendLine(); break; case DiskCategory.DVDR: if(decoded.PartVersion >= 6) sb.AppendFormat(bookTypeSentence, "DVD-R DL").AppendLine(); else sb.AppendFormat(bookTypeSentence, "DVD-R").AppendLine(); break; case DiskCategory.DVDRW: if(decoded.PartVersion >= 15) sb.AppendFormat(bookTypeSentence, "DVD-RW DL").AppendLine(); else sb.AppendFormat(bookTypeSentence, "DVD-RW").AppendLine(); break; case DiskCategory.UMD: sb.AppendFormat(bookTypeSentence, "UMD").AppendLine(); break; case DiskCategory.DVDPRW: sb.AppendFormat(bookTypeSentence, "DVD+RW").AppendLine(); break; case DiskCategory.DVDPR: sb.AppendFormat(bookTypeSentence, "DVD+R").AppendLine(); break; case DiskCategory.DVDPRWDL: sb.AppendFormat(bookTypeSentence, "DVD+RW DL").AppendLine(); break; case DiskCategory.DVDPRDL: sb.AppendFormat(bookTypeSentence, "DVD+R DL").AppendLine(); break; case DiskCategory.HDDVDROM: sb.AppendFormat(bookTypeSentence, "HD DVD-ROM").AppendLine(); break; case DiskCategory.HDDVDRAM: sb.AppendFormat(bookTypeSentence, "HD DVD-RAM").AppendLine(); break; case DiskCategory.HDDVDR: sb.AppendFormat(bookTypeSentence, "HD DVD-R").AppendLine(); break; case DiskCategory.HDDVDRW: sb.AppendFormat(bookTypeSentence, "HD DVD-RW").AppendLine(); break; default: sb.AppendFormat(bookTypeSentence, "unknown").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}", ManufacturerFromDVDRAM(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 < 15: 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}", ManufacturerFromDVDPlusID(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 < 15)) 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, MediaType mediaType) => Prettify(Decode(response, mediaType)); public static string ManufacturerFromDVDRAM(string manufacturerId) { switch(manufacturerId) { default: return ManufacturerFromDVDPlusID(manufacturerId); } } public static string ManufacturerFromDVDPlusID(string manufacturerId) { var manufacturer = ""; switch(manufacturerId) { case "CMC MAG": manufacturer = "CMC Magnetics Corporation"; break; case "INFOME": manufacturer = "InfoMedia Inc."; break; case "RITEK": manufacturer = "Ritek Co."; break; case "RICOHJPN": manufacturer = "Ricoh Company, Ltd."; break; case "ISSM": manufacturer = "Info Source Digital Media (Zhongshan) Co., Ltd."; break; case "LD": manufacturer = "Lead Data Inc."; break; case "MAXELL": manufacturer = "Hitachi Maxell, Ltd."; break; case "MCC": manufacturer = "Mitsubishi Kagaku Media Co., LTD."; break; case "PRODISC": manufacturer = "Prodisc Technology Inc."; break; case "Philips": case "PHILIPS": manufacturer = "Philips Components"; break; case "YUDEN000": manufacturer = "Taiyo Yuden Company Ltd."; break; case "AML": manufacturer = "Avic Umedisc HK Ltd."; break; case "DAXON": manufacturer = "Daxon Technology Inc."; break; case "FTI": manufacturer = "Falcon Technologies International L.L.C."; break; case "GSC503": manufacturer = "Gigastore Corporation"; break; case "MBIPG101": manufacturer = "Moser Baer India Ltd."; break; case "OPTODISC": manufacturer = "OptoDisc Ltd."; break; case "SONY": manufacturer = "Sony Corporation"; break; case "TDK": manufacturer = "TDK Corporation"; break; case "SENTINEL": manufacturer = "Sentinel B.V."; break; case "BeAll000": manufacturer = "BeALL Developers, Inc."; break; case "MPOMEDIA": manufacturer = "MPO Disque Compact"; break; case "IMC JPN": manufacturer = "Intermedia Co., Ltd."; break; case "INFODISC": manufacturer = "InfoDisc Technology Co., Ltd."; break; case "WFKA11": manufacturer = "Wealth Fair Investment Inc."; break; case "MAM": manufacturer = "Manufacturing Advanced Media Europe"; break; case "VDSPMSAB": manufacturer = "Interaxia Digital Storage Materials AG"; break; case "KIC00000": manufacturer = "Advanced Media Corporation"; break; case "MJC": manufacturer = "Megan Media Holdings Berhad"; break; case "MUST": manufacturer = "Must Technology Co., Ltd."; break; case "IS02": manufacturer = "Infosmart Technology Ltd."; break; case "DDDessau": manufacturer = "Digital Disc Dessau GmbH"; break; case "SKYMEDIA": manufacturer = "Sky Media Manufacturing S.A."; break; case "MICRON": manufacturer = "Eastgate Technology Ltd."; break; case "VIVA": manufacturer = "Viva Optical Disc Manufacturing Ltd."; break; case "EMDPZ3": manufacturer = "E-TOP Mediatek Inc."; break; case "LGEP16": manufacturer = "LG Electronics Inc."; break; case "POS": manufacturer = "POSTECH Corporation"; break; case "Dvsn+160": manufacturer = "Digital Storage Technology Co., Ltd."; break; case "ODMS": manufacturer = "VDL Optical Disc Manufacturing Systems"; break; } return manufacturer != "" ? $"{manufacturer} (\"{manufacturerId}\")" : $"\"{manufacturerId}\""; } 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 DiskCategory RecordedBookType; } }