2017-05-19 20:28:49 +01:00
// /***************************************************************************
2015-10-19 02:40:30 +01:00
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : FullTOC.cs
2016-07-28 18:13:49 +01:00
// Author(s) : Natalia Portillo <claunia@claunia.com>
2015-10-19 02:40:30 +01:00
//
2016-07-28 18:13:49 +01:00
// Component : Device structures decoders.
2015-10-19 02:40:30 +01:00
//
// --[ Description ] ----------------------------------------------------------
//
2016-07-28 18:13:49 +01:00
// Decodes CD full Table of Contents.
2015-10-19 02:40:30 +01:00
//
// --[ License ] --------------------------------------------------------------
//
2016-07-28 18:13:49 +01:00
// 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
2015-10-19 02:40:30 +01:00
// License, or (at your option) any later version.
//
2016-07-28 18:13:49 +01:00
// 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.
2015-10-19 02:40:30 +01:00
//
2016-07-28 18:13:49 +01:00
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
2015-10-19 02:40:30 +01:00
//
// ----------------------------------------------------------------------------
2017-12-19 03:50:57 +00:00
// Copyright © 2011-2018 Natalia Portillo
2015-10-19 02:40:30 +01:00
// ****************************************************************************/
2016-07-28 18:13:49 +01:00
2015-10-19 02:40:30 +01:00
using System ;
using DiscImageChef.Console ;
using System.Text ;
namespace DiscImageChef.Decoders.CD
{
/// <summary>
/// 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
2015-12-03 09:31:06 +00:00
/// ISO/IEC 61104: Compact disc video system - 12 cm CD-V
/// ISO/IEC 60908: Audio recording - Compact disc digital audio system
2015-10-19 02:40:30 +01:00
/// </summary>
public static class FullTOC
{
2015-12-04 01:57:56 +00:00
const string StereoNoPre = "Stereo audio track with no pre-emphasis" ;
const string StereoPreEm = "Stereo audio track with 50/15 μs pre-emphasis" ;
const string QuadNoPreEm = "Quadraphonic audio track with no pre-emphasis" ;
const string QuadPreEmph = "Quadraphonic audio track with 50/15 μs pre-emphasis" ;
const string DataUnintrp = "Data track, recorded uninterrupted" ;
const string DataIncrtly = "Data track, recorded incrementally" ;
2015-10-19 02:40:30 +01:00
public struct CDFullTOC
{
/// <summary>
/// Total size of returned session information minus this field
/// </summary>
2016-07-28 22:25:26 +01:00
public ushort DataLength ;
2015-10-19 02:40:30 +01:00
/// <summary>
/// First complete session number in hex
/// </summary>
public byte FirstCompleteSession ;
/// <summary>
/// Last complete session number in hex
/// </summary>
public byte LastCompleteSession ;
/// <summary>
/// Track descriptors
/// </summary>
2015-10-19 02:46:04 +01:00
public TrackDataDescriptor [ ] TrackDescriptors ;
2015-10-19 02:40:30 +01:00
}
2015-10-19 02:46:04 +01:00
public struct TrackDataDescriptor
2015-10-19 02:40:30 +01:00
{
/// <summary>
/// Byte 0
/// Session number in hex
/// </summary>
public byte SessionNumber ;
/// <summary>
/// Byte 1, bits 7 to 4
/// Type of information in Q subchannel of block where this TOC entry was found
/// </summary>
public byte ADR ;
/// <summary>
/// Byte 1, bits 3 to 0
/// Track attributes
/// </summary>
public byte CONTROL ;
/// <summary>
/// Byte 2
/// </summary>
public byte TNO ;
/// <summary>
/// Byte 3
/// </summary>
public byte POINT ;
/// <summary>
/// Byte 4
/// </summary>
public byte Min ;
/// <summary>
/// Byte 5
/// </summary>
public byte Sec ;
/// <summary>
/// Byte 6
/// </summary>
public byte Frame ;
/// <summary>
/// Byte 7, CD only
/// </summary>
public byte Zero ;
/// <summary>
/// Byte 7, bits 7 to 4, DDCD only
/// </summary>
public byte HOUR ;
/// <summary>
/// Byte 7, bits 3 to 0, DDCD only
/// </summary>
public byte PHOUR ;
/// <summary>
/// Byte 8
/// </summary>
public byte PMIN ;
/// <summary>
/// Byte 9
/// </summary>
public byte PSEC ;
/// <summary>
/// Byte 10
/// </summary>
public byte PFRAME ;
}
2015-10-19 02:46:04 +01:00
public static CDFullTOC ? Decode ( byte [ ] CDFullTOCResponse )
2015-10-19 02:40:30 +01:00
{
2016-04-19 02:11:47 +01:00
if ( CDFullTOCResponse = = null )
2015-10-19 02:40:30 +01:00
return null ;
CDFullTOC decoded = new CDFullTOC ( ) ;
BigEndianBitConverter . IsLittleEndian = BitConverter . IsLittleEndian ;
decoded . DataLength = BigEndianBitConverter . ToUInt16 ( CDFullTOCResponse , 0 ) ;
decoded . FirstCompleteSession = CDFullTOCResponse [ 2 ] ;
decoded . LastCompleteSession = CDFullTOCResponse [ 3 ] ;
2015-10-19 02:46:04 +01:00
decoded . TrackDescriptors = new TrackDataDescriptor [ ( decoded . DataLength - 2 ) / 11 ] ;
2015-10-19 02:40:30 +01:00
2016-04-19 02:11:47 +01:00
if ( decoded . DataLength + 2 ! = CDFullTOCResponse . Length )
2015-10-19 02:40:30 +01:00
{
DicConsole . DebugWriteLine ( "CD full TOC decoder" , "Expected CDFullTOC size ({0} bytes) is not received size ({1} bytes), not decoding" , decoded . DataLength + 2 , CDFullTOCResponse . Length ) ;
return null ;
}
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < ( ( decoded . DataLength - 2 ) / 11 ) ; i + + )
2015-10-19 02:40:30 +01:00
{
decoded . TrackDescriptors [ i ] . SessionNumber = CDFullTOCResponse [ 0 + i * 11 + 4 ] ;
decoded . TrackDescriptors [ i ] . ADR = ( byte ) ( ( CDFullTOCResponse [ 1 + i * 11 + 4 ] & 0xF0 ) > > 4 ) ;
decoded . TrackDescriptors [ i ] . CONTROL = ( byte ) ( CDFullTOCResponse [ 1 + i * 11 + 4 ] & 0x0F ) ;
decoded . TrackDescriptors [ i ] . TNO = CDFullTOCResponse [ 2 + i * 11 + 4 ] ;
decoded . TrackDescriptors [ i ] . POINT = CDFullTOCResponse [ 3 + i * 11 + 4 ] ;
decoded . TrackDescriptors [ i ] . Min = CDFullTOCResponse [ 4 + i * 11 + 4 ] ;
decoded . TrackDescriptors [ i ] . Sec = CDFullTOCResponse [ 5 + i * 11 + 4 ] ;
decoded . TrackDescriptors [ i ] . Frame = CDFullTOCResponse [ 6 + i * 11 + 4 ] ;
decoded . TrackDescriptors [ i ] . Zero = CDFullTOCResponse [ 7 + i * 11 + 4 ] ;
decoded . TrackDescriptors [ i ] . HOUR = ( byte ) ( ( CDFullTOCResponse [ 7 + i * 11 + 4 ] & 0xF0 ) > > 4 ) ;
decoded . TrackDescriptors [ i ] . PHOUR = ( byte ) ( CDFullTOCResponse [ 7 + i * 11 + 4 ] & 0x0F ) ;
decoded . TrackDescriptors [ i ] . PMIN = CDFullTOCResponse [ 8 + i * 11 + 4 ] ;
decoded . TrackDescriptors [ i ] . PSEC = CDFullTOCResponse [ 9 + i * 11 + 4 ] ;
decoded . TrackDescriptors [ i ] . PFRAME = CDFullTOCResponse [ 10 + i * 11 + 4 ] ;
}
return decoded ;
}
2015-10-19 02:46:04 +01:00
public static string Prettify ( CDFullTOC ? CDFullTOCResponse )
2015-10-19 02:40:30 +01:00
{
2016-04-19 02:11:47 +01:00
if ( CDFullTOCResponse = = null )
2015-10-19 02:40:30 +01:00
return null ;
CDFullTOC response = CDFullTOCResponse . Value ;
StringBuilder sb = new StringBuilder ( ) ;
2015-12-03 09:31:06 +00:00
int lastSession = 0 ;
2015-10-19 02:40:30 +01:00
sb . AppendFormat ( "First complete session number: {0}" , response . FirstCompleteSession ) . AppendLine ( ) ;
sb . AppendFormat ( "Last complete session number: {0}" , response . LastCompleteSession ) . AppendLine ( ) ;
2016-04-19 02:11:47 +01:00
foreach ( TrackDataDescriptor descriptor in response . TrackDescriptors )
2015-10-19 02:40:30 +01:00
{
2016-04-19 02:11:47 +01:00
if ( ( descriptor . CONTROL & 0x08 ) = = 0x08 | |
2015-12-04 07:26:03 +00:00
( descriptor . ADR ! = 1 & & descriptor . ADR ! = 5 & & descriptor . ADR ! = 4 & & descriptor . ADR ! = 6 ) | |
2015-10-19 02:40:30 +01:00
descriptor . TNO ! = 0 )
{
sb . AppendLine ( "Unknown TOC entry format, printing values as-is" ) ;
sb . AppendFormat ( "SessionNumber = {0}" , descriptor . SessionNumber ) . AppendLine ( ) ;
sb . AppendFormat ( "ADR = {0}" , descriptor . ADR ) . AppendLine ( ) ;
sb . AppendFormat ( "CONTROL = {0}" , descriptor . CONTROL ) . AppendLine ( ) ;
sb . AppendFormat ( "TNO = {0}" , descriptor . TNO ) . AppendLine ( ) ;
sb . AppendFormat ( "POINT = {0}" , descriptor . POINT ) . AppendLine ( ) ;
sb . AppendFormat ( "Min = {0}" , descriptor . Min ) . AppendLine ( ) ;
sb . AppendFormat ( "Sec = {0}" , descriptor . Sec ) . AppendLine ( ) ;
sb . AppendFormat ( "Frame = {0}" , descriptor . Frame ) . AppendLine ( ) ;
sb . AppendFormat ( "HOUR = {0}" , descriptor . HOUR ) . AppendLine ( ) ;
sb . AppendFormat ( "PHOUR = {0}" , descriptor . PHOUR ) . AppendLine ( ) ;
sb . AppendFormat ( "PMIN = {0}" , descriptor . PMIN ) . AppendLine ( ) ;
sb . AppendFormat ( "PSEC = {0}" , descriptor . PSEC ) . AppendLine ( ) ;
sb . AppendFormat ( "PFRAME = {0}" , descriptor . PFRAME ) . AppendLine ( ) ;
}
else
{
2015-12-03 09:31:06 +00:00
if ( descriptor . SessionNumber > lastSession )
{
sb . AppendFormat ( "Session {0}" , descriptor . SessionNumber ) . AppendLine ( ) ;
lastSession = descriptor . SessionNumber ;
}
2016-04-19 02:11:47 +01:00
switch ( descriptor . ADR )
2015-10-19 02:40:30 +01:00
{
case 1 :
2015-12-03 09:31:06 +00:00
case 4 :
2015-10-19 02:40:30 +01:00
{
2016-04-19 02:11:47 +01:00
switch ( descriptor . POINT )
2015-10-19 02:40:30 +01:00
{
case 0xA0 :
{
2016-04-19 02:11:47 +01:00
if ( descriptor . ADR = = 4 )
2015-12-03 09:31:06 +00:00
{
sb . AppendFormat ( "First video track number: {0}" , descriptor . PMIN ) . AppendLine ( ) ;
2016-04-19 02:11:47 +01:00
switch ( descriptor . PSEC )
2015-12-03 09:31:06 +00:00
{
case 0x10 :
sb . AppendLine ( "CD-V single in NTSC format with digital stereo sound" ) ;
break ;
case 0x11 :
sb . AppendLine ( "CD-V single in NTSC format with digital bilingual sound" ) ;
break ;
case 0x12 :
sb . AppendLine ( "CD-V disc in NTSC format with digital stereo sound" ) ;
break ;
case 0x13 :
sb . AppendLine ( "CD-V disc in NTSC format with digital bilingual sound" ) ;
break ;
case 0x20 :
sb . AppendLine ( "CD-V single in PAL format with digital stereo sound" ) ;
break ;
case 0x21 :
sb . AppendLine ( "CD-V single in PAL format with digital bilingual sound" ) ;
break ;
case 0x22 :
sb . AppendLine ( "CD-V disc in PAL format with digital stereo sound" ) ;
break ;
case 0x23 :
sb . AppendLine ( "CD-V disc in PAL format with digital bilingual sound" ) ;
break ;
}
}
else
{
2015-12-04 01:57:56 +00:00
sb . AppendFormat ( "First track number: {0} (" , descriptor . PMIN ) ;
2016-04-19 02:11:47 +01:00
switch ( ( TOC_CONTROL ) ( descriptor . CONTROL & 0x0D ) )
2015-12-04 01:57:56 +00:00
{
case TOC_CONTROL . TwoChanNoPreEmph :
sb . Append ( StereoNoPre ) ;
break ;
case TOC_CONTROL . TwoChanPreEmph :
sb . Append ( StereoPreEm ) ;
break ;
case TOC_CONTROL . FourChanNoPreEmph :
sb . Append ( QuadNoPreEm ) ;
break ;
case TOC_CONTROL . FourChanPreEmph :
sb . Append ( QuadPreEmph ) ;
break ;
case TOC_CONTROL . DataTrack :
sb . Append ( DataUnintrp ) ;
break ;
case TOC_CONTROL . DataTrackIncremental :
sb . Append ( DataIncrtly ) ;
break ;
}
sb . AppendLine ( ")" ) ;
2015-12-03 09:31:06 +00:00
sb . AppendFormat ( "Disc type: {0}" , descriptor . PSEC ) . AppendLine ( ) ;
//sb.AppendFormat("Absolute time: {3:D2}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine();
}
2015-10-19 02:40:30 +01:00
break ;
}
case 0xA1 :
{
2016-04-19 02:11:47 +01:00
if ( descriptor . ADR = = 4 )
2015-12-03 09:31:06 +00:00
sb . AppendFormat ( "Last video track number: {0}" , descriptor . PMIN ) . AppendLine ( ) ;
else
2015-12-04 01:57:56 +00:00
{
sb . AppendFormat ( "Last track number: {0} (" , descriptor . PMIN ) ;
2016-04-19 02:11:47 +01:00
switch ( ( TOC_CONTROL ) ( descriptor . CONTROL & 0x0D ) )
2015-12-04 01:57:56 +00:00
{
case TOC_CONTROL . TwoChanNoPreEmph :
sb . Append ( StereoNoPre ) ;
break ;
case TOC_CONTROL . TwoChanPreEmph :
sb . Append ( StereoPreEm ) ;
break ;
case TOC_CONTROL . FourChanNoPreEmph :
sb . Append ( QuadNoPreEm ) ;
break ;
case TOC_CONTROL . FourChanPreEmph :
sb . Append ( QuadPreEmph ) ;
break ;
case TOC_CONTROL . DataTrack :
sb . Append ( DataUnintrp ) ;
break ;
case TOC_CONTROL . DataTrackIncremental :
sb . Append ( DataIncrtly ) ;
break ;
}
sb . AppendLine ( ")" ) ;
}
2015-12-03 09:31:06 +00:00
//sb.AppendFormat("Absolute time: {3:D2}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine();
2015-10-19 02:40:30 +01:00
break ;
}
case 0xA2 :
{
2015-12-03 09:31:06 +00:00
if ( descriptor . PHOUR > 0 )
sb . AppendFormat ( "Lead-out start position: {3:D2}:{0:D2}:{1:D2}:{2:D2}" , descriptor . PMIN , descriptor . PSEC , descriptor . PFRAME , descriptor . PHOUR ) . AppendLine ( ) ;
else
sb . AppendFormat ( "Lead-out start position: {0:D2}:{1:D2}:{2:D2}" , descriptor . PMIN , descriptor . PSEC , descriptor . PFRAME ) . AppendLine ( ) ;
//sb.AppendFormat("Absolute time: {3:D2}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine();
2015-12-04 01:57:56 +00:00
2016-04-19 02:11:47 +01:00
switch ( ( TOC_CONTROL ) ( descriptor . CONTROL & 0x0D ) )
2015-12-04 01:57:56 +00:00
{
case TOC_CONTROL . TwoChanNoPreEmph :
case TOC_CONTROL . TwoChanPreEmph :
case TOC_CONTROL . FourChanNoPreEmph :
case TOC_CONTROL . FourChanPreEmph :
sb . AppendLine ( "Lead-out is audio type" ) ;
break ;
case TOC_CONTROL . DataTrack :
case TOC_CONTROL . DataTrackIncremental :
sb . AppendLine ( "Lead-out is data type" ) ;
break ;
}
2015-10-19 02:40:30 +01:00
break ;
}
case 0xF0 :
{
sb . AppendFormat ( "Book type: 0x{0:X2}" , descriptor . PMIN ) ;
sb . AppendFormat ( "Material type: 0x{0:X2}" , descriptor . PSEC ) ;
sb . AppendFormat ( "Moment of inertia: 0x{0:X2}" , descriptor . PFRAME ) ;
2015-12-03 09:31:06 +00:00
if ( descriptor . PHOUR > 0 )
sb . AppendFormat ( "Absolute time: {3:D2}:{0:D2}:{1:D2}:{2:D2}" , descriptor . Min , descriptor . Sec , descriptor . Frame , descriptor . HOUR ) . AppendLine ( ) ;
else
sb . AppendFormat ( "Absolute time: {0:D2}:{1:D2}:{2:D2}" , descriptor . Min , descriptor . Sec , descriptor . Frame ) . AppendLine ( ) ;
2015-10-19 02:40:30 +01:00
break ;
}
default :
{
2016-04-19 02:11:47 +01:00
if ( descriptor . POINT > = 0x01 & & descriptor . POINT < = 0x63 )
2015-10-19 02:40:30 +01:00
{
2016-04-19 02:11:47 +01:00
if ( descriptor . ADR = = 4 )
2015-12-04 01:57:56 +00:00
sb . AppendFormat ( "Video track {3} starts at: {0:D2}:{1:D2}:{2:D2}" , descriptor . PMIN , descriptor . PSEC , descriptor . PFRAME , descriptor . POINT ) . AppendLine ( ) ;
2015-12-03 09:31:06 +00:00
else
{
2015-12-04 01:57:56 +00:00
string type = "Audio" ;
2016-04-19 02:11:47 +01:00
if ( ( TOC_CONTROL ) ( descriptor . CONTROL & 0x0D ) = = TOC_CONTROL . DataTrack | |
2015-12-04 01:57:56 +00:00
( TOC_CONTROL ) ( descriptor . CONTROL & 0x0D ) = = TOC_CONTROL . DataTrackIncremental )
type = "Data" ;
2015-12-03 09:31:06 +00:00
if ( descriptor . PHOUR > 0 )
2015-12-04 01:57:56 +00:00
sb . AppendFormat ( "{5} track {3} starts at: {4:D2}:{0:D2}:{1:D2}:{2:D2} (" , descriptor . PMIN , descriptor . PSEC , descriptor . PFRAME , descriptor . POINT , descriptor . PHOUR , type ) ;
2015-12-03 09:31:06 +00:00
else
2015-12-04 01:57:56 +00:00
sb . AppendFormat ( "{4} track {3} starts at: {0:D2}:{1:D2}:{2:D2} (" , descriptor . PMIN , descriptor . PSEC , descriptor . PFRAME , descriptor . POINT , type ) ;
2016-04-19 02:11:47 +01:00
switch ( ( TOC_CONTROL ) ( descriptor . CONTROL & 0x0D ) )
2015-12-04 01:57:56 +00:00
{
case TOC_CONTROL . TwoChanNoPreEmph :
sb . Append ( StereoNoPre ) ;
break ;
case TOC_CONTROL . TwoChanPreEmph :
sb . Append ( StereoPreEm ) ;
break ;
case TOC_CONTROL . FourChanNoPreEmph :
sb . Append ( QuadNoPreEm ) ;
break ;
case TOC_CONTROL . FourChanPreEmph :
sb . Append ( QuadPreEmph ) ;
break ;
case TOC_CONTROL . DataTrack :
sb . Append ( DataUnintrp ) ;
break ;
case TOC_CONTROL . DataTrackIncremental :
sb . Append ( DataIncrtly ) ;
break ;
}
sb . AppendLine ( ")" ) ;
2015-12-03 09:31:06 +00:00
}
//sb.AppendFormat("Absolute time: {3:D2}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine();
2015-10-19 02:40:30 +01:00
}
else
{
sb . AppendFormat ( "ADR = {0}" , descriptor . ADR ) . AppendLine ( ) ;
sb . AppendFormat ( "CONTROL = {0}" , descriptor . CONTROL ) . AppendLine ( ) ;
sb . AppendFormat ( "TNO = {0}" , descriptor . TNO ) . AppendLine ( ) ;
sb . AppendFormat ( "POINT = {0}" , descriptor . POINT ) . AppendLine ( ) ;
sb . AppendFormat ( "Min = {0}" , descriptor . Min ) . AppendLine ( ) ;
sb . AppendFormat ( "Sec = {0}" , descriptor . Sec ) . AppendLine ( ) ;
sb . AppendFormat ( "Frame = {0}" , descriptor . Frame ) . AppendLine ( ) ;
sb . AppendFormat ( "HOUR = {0}" , descriptor . HOUR ) . AppendLine ( ) ;
sb . AppendFormat ( "PHOUR = {0}" , descriptor . PHOUR ) . AppendLine ( ) ;
sb . AppendFormat ( "PMIN = {0}" , descriptor . PMIN ) . AppendLine ( ) ;
sb . AppendFormat ( "PSEC = {0}" , descriptor . PSEC ) . AppendLine ( ) ;
sb . AppendFormat ( "PFRAME = {0}" , descriptor . PFRAME ) . AppendLine ( ) ;
}
break ;
}
}
break ;
}
case 5 :
{
2016-04-19 02:11:47 +01:00
switch ( descriptor . POINT )
2015-10-19 02:40:30 +01:00
{
case 0xB0 :
{
2016-04-19 02:11:47 +01:00
if ( descriptor . PHOUR > 0 )
2015-12-03 09:31:06 +00:00
{
sb . AppendFormat ( "Start of next possible program in the recordable area of the disc: {3:D2}:{0:D2}:{1:D2}:{2:D2}" , descriptor . Min , descriptor . Sec , descriptor . Frame , descriptor . HOUR ) . AppendLine ( ) ;
sb . AppendFormat ( "Maximum start of outermost Lead-out in the recordable area of the disc: {3:D2}:{0:D2}:{1:D2}:{2:D2}" , descriptor . PMIN , descriptor . PSEC , descriptor . PFRAME , descriptor . PHOUR ) . AppendLine ( ) ;
}
else
{
sb . AppendFormat ( "Start of next possible program in the recordable area of the disc: {0:D2}:{1:D2}:{2:D2}" , descriptor . Min , descriptor . Sec , descriptor . Frame ) . AppendLine ( ) ;
sb . AppendFormat ( "Maximum start of outermost Lead-out in the recordable area of the disc: {0:D2}:{1:D2}:{2:D2}" , descriptor . PMIN , descriptor . PSEC , descriptor . PFRAME ) . AppendLine ( ) ;
}
2015-10-19 02:40:30 +01:00
break ;
}
case 0xB1 :
{
2015-12-03 09:31:06 +00:00
sb . AppendFormat ( "Number of skip interval pointers: {0}" , descriptor . PMIN ) . AppendLine ( ) ;
sb . AppendFormat ( "Number of skip track pointers: {0}" , descriptor . PSEC ) . AppendLine ( ) ;
2015-10-19 02:40:30 +01:00
break ;
}
case 0xB2 :
case 0xB3 :
case 0xB4 :
{
sb . AppendFormat ( "Skip track {0}" , descriptor . Min ) . AppendLine ( ) ;
sb . AppendFormat ( "Skip track {0}" , descriptor . Sec ) . AppendLine ( ) ;
sb . AppendFormat ( "Skip track {0}" , descriptor . Frame ) . AppendLine ( ) ;
sb . AppendFormat ( "Skip track {0}" , descriptor . Zero ) . AppendLine ( ) ;
sb . AppendFormat ( "Skip track {0}" , descriptor . PMIN ) . AppendLine ( ) ;
sb . AppendFormat ( "Skip track {0}" , descriptor . PSEC ) . AppendLine ( ) ;
sb . AppendFormat ( "Skip track {0}" , descriptor . PFRAME ) . AppendLine ( ) ;
break ;
}
case 0xC0 :
{
sb . AppendFormat ( "Optimum recording power: 0x{0:X2}" , descriptor . Min ) . AppendLine ( ) ;
2016-04-19 02:11:47 +01:00
if ( descriptor . PHOUR > 0 )
2015-12-03 09:31:06 +00:00
sb . AppendFormat ( "Start time of the first Lead-in area in the disc: {3:D2}:{0:D2}:{1:D2}:{2:D2}" , descriptor . PMIN , descriptor . PSEC , descriptor . PFRAME , descriptor . PHOUR ) . AppendLine ( ) ;
else
sb . AppendFormat ( "Start time of the first Lead-in area in the disc: {0:D2}:{1:D2}:{2:D2}" , descriptor . PMIN , descriptor . PSEC , descriptor . PFRAME ) . AppendLine ( ) ;
2015-10-19 02:40:30 +01:00
break ;
}
case 0xC1 :
{
sb . AppendFormat ( "Copy of information of A1 from ATIP found" ) ;
sb . AppendFormat ( "Min = {0}" , descriptor . Min ) . AppendLine ( ) ;
sb . AppendFormat ( "Sec = {0}" , descriptor . Sec ) . AppendLine ( ) ;
sb . AppendFormat ( "Frame = {0}" , descriptor . Frame ) . AppendLine ( ) ;
sb . AppendFormat ( "Zero = {0}" , descriptor . Zero ) . AppendLine ( ) ;
sb . AppendFormat ( "PMIN = {0}" , descriptor . PMIN ) . AppendLine ( ) ;
sb . AppendFormat ( "PSEC = {0}" , descriptor . PSEC ) . AppendLine ( ) ;
sb . AppendFormat ( "PFRAME = {0}" , descriptor . PFRAME ) . AppendLine ( ) ;
break ;
}
case 0xCF :
{
2016-04-19 02:11:47 +01:00
if ( descriptor . PHOUR > 0 )
2015-12-03 09:31:06 +00:00
{
sb . AppendFormat ( "Start position of outer part lead-in area: {3:D2}:{0:D2}:{1:D2}:{2:D2}" , descriptor . PMIN , descriptor . PSEC , descriptor . PFRAME , descriptor . PHOUR ) . AppendLine ( ) ;
sb . AppendFormat ( "Stop position of inner part lead-out area: {3:D2}:{0:D2}:{1:D2}:{2:D2}" , descriptor . Min , descriptor . Sec , descriptor . Frame , descriptor . HOUR ) . AppendLine ( ) ;
}
else
{
sb . AppendFormat ( "Start position of outer part lead-in area: {0:D2}:{1:D2}:{2:D2}" , descriptor . PMIN , descriptor . PSEC , descriptor . PFRAME ) . AppendLine ( ) ;
sb . AppendFormat ( "Stop position of inner part lead-out area: {0:D2}:{1:D2}:{2:D2}" , descriptor . Min , descriptor . Sec , descriptor . Frame ) . AppendLine ( ) ;
}
2015-10-19 02:40:30 +01:00
break ;
}
default :
{
2016-04-19 02:11:47 +01:00
if ( descriptor . POINT > = 0x01 & & descriptor . POINT < = 0x40 )
2015-10-19 02:40:30 +01:00
{
2015-12-03 09:31:06 +00:00
sb . AppendFormat ( "Start time for interval that should be skipped: {0:D2}:{1:D2}:{2:D2}" , descriptor . PMIN , descriptor . PSEC , descriptor . PFRAME ) . AppendLine ( ) ;
sb . AppendFormat ( "Ending time for interval that should be skipped: {0:D2}:{1:D2}:{2:D2}" , descriptor . Min , descriptor . Sec , descriptor . Frame ) . AppendLine ( ) ;
2015-10-19 02:40:30 +01:00
}
else
{
sb . AppendFormat ( "ADR = {0}" , descriptor . ADR ) . AppendLine ( ) ;
sb . AppendFormat ( "CONTROL = {0}" , descriptor . CONTROL ) . AppendLine ( ) ;
sb . AppendFormat ( "TNO = {0}" , descriptor . TNO ) . AppendLine ( ) ;
sb . AppendFormat ( "POINT = {0}" , descriptor . POINT ) . AppendLine ( ) ;
sb . AppendFormat ( "Min = {0}" , descriptor . Min ) . AppendLine ( ) ;
sb . AppendFormat ( "Sec = {0}" , descriptor . Sec ) . AppendLine ( ) ;
sb . AppendFormat ( "Frame = {0}" , descriptor . Frame ) . AppendLine ( ) ;
sb . AppendFormat ( "HOUR = {0}" , descriptor . HOUR ) . AppendLine ( ) ;
sb . AppendFormat ( "PHOUR = {0}" , descriptor . PHOUR ) . AppendLine ( ) ;
sb . AppendFormat ( "PMIN = {0}" , descriptor . PMIN ) . AppendLine ( ) ;
sb . AppendFormat ( "PSEC = {0}" , descriptor . PSEC ) . AppendLine ( ) ;
sb . AppendFormat ( "PFRAME = {0}" , descriptor . PFRAME ) . AppendLine ( ) ;
}
break ;
}
}
break ;
}
2015-12-04 07:26:03 +00:00
case 6 :
{
uint id = ( uint ) ( ( descriptor . Min < < 16 ) + ( descriptor . Sec < < 8 ) + descriptor . Frame ) ;
sb . AppendFormat ( "Disc ID: {0:X6}" , id & 0x00FFFFFF ) . AppendLine ( ) ;
break ;
}
2015-10-19 02:40:30 +01:00
}
}
}
return sb . ToString ( ) ;
}
2015-10-19 02:46:04 +01:00
public static string Prettify ( byte [ ] CDFullTOCResponse )
2015-10-19 02:40:30 +01:00
{
2015-10-19 02:46:04 +01:00
CDFullTOC ? decoded = Decode ( CDFullTOCResponse ) ;
return Prettify ( decoded ) ;
2015-10-19 02:40:30 +01:00
}
}
}