2016-07-28 18:13:49 +01:00
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : Nero.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Disc image plugins.
//
// --[ Description ] ----------------------------------------------------------
//
// Manages Nero Burning ROM disc images.
//
// --[ 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 <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2016 Natalia Portillo
// ****************************************************************************/
2014-07-09 19:52:00 +01:00
using System ;
using System.IO ;
using System.Collections.Generic ;
2015-10-18 22:04:03 +01:00
using DiscImageChef.Console ;
2015-11-23 21:44:58 +00:00
using DiscImageChef.CommonTypes ;
2014-07-09 19:52:00 +01:00
namespace DiscImageChef.ImagePlugins
{
class Nero : ImagePlugin
{
#region Internal structures
struct NeroV1Footer
{
/// <summary>
/// "NERO"
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkID ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Offset of first chunk in file
/// </summary>
2016-07-28 22:25:26 +01:00
public uint FirstChunkOffset ;
2014-07-09 19:52:00 +01:00
}
struct NeroV2Footer
{
/// <summary>
/// "NER5"
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkID ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Offset of first chunk in file
/// </summary>
2016-07-28 22:25:26 +01:00
public ulong FirstChunkOffset ;
2014-07-09 19:52:00 +01:00
}
struct NeroV2CueEntry
{
/// <summary>
/// Track mode. 0x01 for audio, 0x21 for copy-protected audio, 0x41 for data
/// </summary>
public byte Mode ;
/// <summary>
/// Track number in BCD
/// </summary>
public byte TrackNumber ;
/// <summary>
/// Index number in BCD
/// </summary>
public byte IndexNumber ;
/// <summary>
/// Always zero
/// </summary>
public byte Dummy ;
/// <summary>
/// LBA sector start for this entry
/// </summary>
2016-07-28 22:25:26 +01:00
public int LBAStart ;
2014-07-09 19:52:00 +01:00
}
struct NeroV2Cuesheet
{
/// <summary>
/// "CUEX"
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkID ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Chunk size
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkSize ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Cuesheet entries
/// </summary>
public List < NeroV2CueEntry > Entries ;
}
struct NeroV1CueEntry
{
/// <summary>
/// Track mode. 0x01 for audio, 0x21 for copy-protected audio, 0x41 for data
/// </summary>
public byte Mode ;
/// <summary>
/// Track number in BCD
/// </summary>
public byte TrackNumber ;
/// <summary>
/// Index number in BCD
/// </summary>
public byte IndexNumber ;
/// <summary>
/// Always zero
/// </summary>
2016-07-28 22:25:26 +01:00
public ushort Dummy ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// MSF start sector's minute for this entry
/// </summary>
public byte Minute ;
/// <summary>
/// MSF start sector's second for this entry
/// </summary>
public byte Second ;
/// <summary>
/// MSF start sector's frame for this entry
/// </summary>
public byte Frame ;
}
struct NeroV1Cuesheet
{
/// <summary>
/// "CUES"
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkID ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Chunk size
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkSize ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Cuesheet entries
/// </summary>
public List < NeroV1CueEntry > Entries ;
}
struct NeroV1DAOEntry
{
/// <summary>
/// ISRC (12 bytes)
/// </summary>
public byte [ ] ISRC ;
/// <summary>
/// Size of sector inside image (in bytes)
/// </summary>
2016-07-28 22:25:26 +01:00
public ushort SectorSize ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Sector mode in image
/// </summary>
2016-07-28 22:25:26 +01:00
public ushort Mode ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Unknown
/// </summary>
2016-07-28 22:25:26 +01:00
public ushort Unknown ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Index 0 start
/// </summary>
2016-07-28 22:25:26 +01:00
public uint Index0 ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Index 1 start
/// </summary>
2016-07-28 22:25:26 +01:00
public uint Index1 ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// End of track + 1
/// </summary>
2016-07-28 22:25:26 +01:00
public uint EndOfTrack ;
2014-07-09 19:52:00 +01:00
}
struct NeroV1DAO
{
/// <summary>
/// "DAOI"
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkID ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Chunk size (big endian)
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkSizeBe ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Chunk size (little endian)
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkSizeLe ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// UPC (14 bytes, null-padded)
/// </summary>
public byte [ ] UPC ;
/// <summary>
/// TOC type
/// </summary>
2016-07-28 22:25:26 +01:00
public ushort TocType ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// First track
/// </summary>
public byte FirstTrack ;
/// <summary>
/// Last track
/// </summary>
public byte LastTrack ;
/// <summary>
/// Tracks
/// </summary>
public List < NeroV1DAOEntry > Tracks ;
}
struct NeroV2DAOEntry
{
/// <summary>
/// ISRC (12 bytes)
/// </summary>
public byte [ ] ISRC ;
/// <summary>
/// Size of sector inside image (in bytes)
/// </summary>
2016-07-28 22:25:26 +01:00
public ushort SectorSize ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Sector mode in image
/// </summary>
2016-07-28 22:25:26 +01:00
public ushort Mode ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Seems to be always 0.
/// </summary>
2016-07-28 22:25:26 +01:00
public ushort Unknown ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Index 0 start
/// </summary>
2016-07-28 22:25:26 +01:00
public ulong Index0 ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Index 1 start
/// </summary>
2016-07-28 22:25:26 +01:00
public ulong Index1 ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// End of track + 1
/// </summary>
2016-07-28 22:25:26 +01:00
public ulong EndOfTrack ;
2014-07-09 19:52:00 +01:00
}
struct NeroV2DAO
{
/// <summary>
/// "DAOX"
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkID ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Chunk size (big endian)
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkSizeBe ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Chunk size (little endian)
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkSizeLe ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// UPC (14 bytes, null-padded)
/// </summary>
public byte [ ] UPC ;
/// <summary>
/// TOC type
/// </summary>
2016-07-28 22:25:26 +01:00
public ushort TocType ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// First track
/// </summary>
public byte FirstTrack ;
/// <summary>
/// Last track
/// </summary>
public byte LastTrack ;
/// <summary>
/// Tracks
/// </summary>
public List < NeroV2DAOEntry > Tracks ;
}
struct NeroCDTextPack
{
/// <summary>
/// Pack type
/// </summary>
public byte PackType ;
/// <summary>
/// Track number
/// </summary>
public byte TrackNumber ;
/// <summary>
/// Pack number in block
/// </summary>
public byte PackNumber ;
/// <summary>
/// Block number
/// </summary>
public byte BlockNumber ;
/// <summary>
/// 12 bytes of data
/// </summary>
public byte [ ] Text ;
/// <summary>
/// CRC
/// </summary>
2016-07-28 22:25:26 +01:00
public ushort CRC ;
2014-07-09 19:52:00 +01:00
}
struct NeroCDText
{
/// <summary>
/// "CDTX"
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkID ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Chunk size
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkSize ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// CD-TEXT packs
/// </summary>
public List < NeroCDTextPack > Packs ;
}
struct NeroV1TAOEntry
{
/// <summary>
/// Offset of track on image
/// </summary>
2016-07-28 22:25:26 +01:00
public uint Offset ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Length of track in bytes
/// </summary>
2016-07-28 22:25:26 +01:00
public uint Length ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Track mode
/// </summary>
2016-07-28 22:25:26 +01:00
public uint Mode ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// LBA track start (plus 150 lead in sectors)
/// </summary>
2016-07-28 22:25:26 +01:00
public uint StartLBA ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Unknown
/// </summary>
2016-07-28 22:25:26 +01:00
public uint Unknown ;
2014-07-09 19:52:00 +01:00
}
struct NeroV1TAO
{
/// <summary>
/// "ETNF"
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkID ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Chunk size
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkSize ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// CD-TEXT packs
/// </summary>
public List < NeroV1TAOEntry > Tracks ;
}
struct NeroV2TAOEntry
{
/// <summary>
/// Offset of track on image
/// </summary>
2016-07-28 22:25:26 +01:00
public ulong Offset ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Length of track in bytes
/// </summary>
2016-07-28 22:25:26 +01:00
public ulong Length ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Track mode
/// </summary>
2016-07-28 22:25:26 +01:00
public uint Mode ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// LBA track start (plus 150 lead in sectors)
/// </summary>
2016-07-28 22:25:26 +01:00
public uint StartLBA ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Unknown
/// </summary>
2016-07-28 22:25:26 +01:00
public uint Unknown ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Track length in sectors
/// </summary>
2016-07-28 22:25:26 +01:00
public uint Sectors ;
2014-07-09 19:52:00 +01:00
}
struct NeroV2TAO
{
/// <summary>
/// "ETN2"
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkID ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Chunk size
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkSize ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// CD-TEXT packs
/// </summary>
public List < NeroV2TAOEntry > Tracks ;
}
struct NeroSession
{
/// <summary>
/// "SINF"
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkID ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Chunk size
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkSize ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Tracks in session
/// </summary>
2016-07-28 22:25:26 +01:00
public uint Tracks ;
2014-07-09 19:52:00 +01:00
}
struct NeroMediaType
{
/// <summary>
/// "MTYP"
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkID ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Chunk size
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkSize ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Media type
/// </summary>
2016-07-28 22:25:26 +01:00
public uint Type ;
2014-07-09 19:52:00 +01:00
}
struct NeroDiscInformation
{
/// <summary>
/// "DINF"
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkID ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Chunk size
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkSize ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Unknown
/// </summary>
2016-07-28 22:25:26 +01:00
public uint Unknown ;
2014-07-09 19:52:00 +01:00
}
struct NeroTOCChunk
{
/// <summary>
/// "TOCT"
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkID ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Chunk size
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkSize ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Unknown
/// </summary>
2016-07-28 22:25:26 +01:00
public ushort Unknown ;
2014-07-09 19:52:00 +01:00
}
struct NeroRELOChunk
{
/// <summary>
/// "RELO"
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkID ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Chunk size
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkSize ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Unknown
/// </summary>
2016-07-28 22:25:26 +01:00
public uint Unknown ;
2014-07-09 19:52:00 +01:00
}
struct NeroEndOfChunkChain
{
/// <summary>
/// "END!"
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkID ;
2014-07-09 19:52:00 +01:00
/// <summary>
/// Chunk size
/// </summary>
2016-07-28 22:25:26 +01:00
public uint ChunkSize ;
2014-07-09 19:52:00 +01:00
}
// Internal use only
struct NeroTrack
{
public byte [ ] ISRC ;
2016-07-28 22:25:26 +01:00
public ushort SectorSize ;
public ulong Offset ;
public ulong Length ;
public ulong EndOfTrack ;
public uint Mode ;
public ulong StartLBA ;
public ulong Sectors ;
public ulong Index0 ;
public ulong Index1 ;
public uint Sequence ;
2014-07-09 19:52:00 +01:00
}
#endregion
#region Internal consts
// "NERO"
2016-07-28 22:25:26 +01:00
public const uint NeroV1FooterID = 0x4E45524F ;
2014-07-09 19:52:00 +01:00
// "NER5"
2016-07-28 22:25:26 +01:00
public const uint NeroV2FooterID = 0x4E455235 ;
2014-07-09 19:52:00 +01:00
// "CUES"
2016-07-28 22:25:26 +01:00
public const uint NeroV1CUEID = 0x43554553 ;
2014-07-09 19:52:00 +01:00
// "CUEX"
2016-07-28 22:25:26 +01:00
public const uint NeroV2CUEID = 0x43554558 ;
2014-07-09 19:52:00 +01:00
// "ETNF"
2016-07-28 22:25:26 +01:00
public const uint NeroV1TAOID = 0x45544E46 ;
2014-07-09 19:52:00 +01:00
// "ETN2"
2016-07-28 22:25:26 +01:00
public const uint NeroV2TAOID = 0x45544E32 ;
2014-07-09 19:52:00 +01:00
// "DAOI"
2016-07-28 22:25:26 +01:00
public const uint NeroV1DAOID = 0x44414F49 ;
2014-07-09 19:52:00 +01:00
// "DAOX"
2016-07-28 22:25:26 +01:00
public const uint NeroV2DAOID = 0x44414F58 ;
2014-07-09 19:52:00 +01:00
// "CDTX"
2016-07-28 22:25:26 +01:00
public const uint NeroCDTextID = 0x43445458 ;
2014-07-09 19:52:00 +01:00
// "SINF"
2016-07-28 22:25:26 +01:00
public const uint NeroSessionID = 0x53494E46 ;
2014-07-09 19:52:00 +01:00
// "MTYP"
2016-07-28 22:25:26 +01:00
public const uint NeroDiskTypeID = 0x4D545950 ;
2014-07-09 19:52:00 +01:00
// "DINF"
2016-07-28 22:25:26 +01:00
public const uint NeroDiscInfoID = 0x44494E46 ;
2014-07-09 19:52:00 +01:00
// "TOCT"
2016-07-28 22:25:26 +01:00
public const uint NeroTOCID = 0x544F4354 ;
2014-07-09 19:52:00 +01:00
// "RELO"
2016-07-28 22:25:26 +01:00
public const uint NeroReloID = 0x52454C4F ;
2014-07-09 19:52:00 +01:00
// "END!"
2016-07-28 22:25:26 +01:00
public const uint NeroEndID = 0x454E4421 ;
2014-07-09 19:52:00 +01:00
public enum DAOMode : ushort
{
Data = 0x0000 ,
DataM2F1 = 0x0002 ,
DataM2F2 = 0x0003 ,
DataRaw = 0x0005 ,
DataM2Raw = 0x0006 ,
Audio = 0x0007 ,
DataRawSub = 0x000F ,
AudioSub = 0x0010 ,
DataM2RawSub = 0x0011
}
2016-07-28 22:25:26 +01:00
[Flags]
2014-07-09 19:52:00 +01:00
public enum NeroMediaTypes : uint
{
/// <summary>
/// No media
/// </summary>
NERO_MTYP_NONE = 0x00000 ,
/// <summary>
/// CD-R/RW
/// </summary>
NERO_MTYP_CD = 0x00001 ,
/// <summary>
/// DDCD-R/RW
/// </summary>
NERO_MTYP_DDCD = 0x00002 ,
/// <summary>
/// DVD-R/RW
/// </summary>
NERO_MTYP_DVD_M = 0x00004 ,
/// <summary>
/// DVD+RW
/// </summary>
NERO_MTYP_DVD_P = 0x00008 ,
/// <summary>
/// DVD-RAM
/// </summary>
NERO_MTYP_DVD_RAM = 0x00010 ,
/// <summary>
/// Multi-level disc
/// </summary>
NERO_MTYP_ML = 0x00020 ,
/// <summary>
/// Mount Rainier
/// </summary>
NERO_MTYP_MRW = 0x00040 ,
/// <summary>
/// Exclude CD-R
/// </summary>
NERO_MTYP_NO_CDR = 0x00080 ,
/// <summary>
/// Exclude CD-RW
/// </summary>
NERO_MTYP_NO_CDRW = 0x00100 ,
/// <summary>
/// CD-RW
/// </summary>
NERO_MTYP_CDRW = NERO_MTYP_CD | NERO_MTYP_NO_CDR ,
/// <summary>
/// CD-R
/// </summary>
NERO_MTYP_CDR = NERO_MTYP_CD | NERO_MTYP_NO_CDRW ,
/// <summary>
/// DVD-ROM
/// </summary>
NERO_MTYP_DVD_ROM = 0x00200 ,
/// <summary>
/// CD-ROM
/// </summary>
NERO_MTYP_CDROM = 0x00400 ,
/// <summary>
/// Exclude DVD-RW
/// </summary>
NERO_MTYP_NO_DVD_M_RW = 0x00800 ,
/// <summary>
/// Exclude DVD-R
/// </summary>
NERO_MTYP_NO_DVD_M_R = 0x01000 ,
/// <summary>
/// Exclude DVD+RW
/// </summary>
NERO_MTYP_NO_DVD_P_RW = 0x02000 ,
/// <summary>
/// Exclude DVD+R
/// </summary>
NERO_MTYP_NO_DVD_P_R = 0x04000 ,
/// <summary>
/// DVD-R
/// </summary>
NERO_MTYP_DVD_M_R = NERO_MTYP_DVD_M | NERO_MTYP_NO_DVD_M_RW ,
/// <summary>
/// DVD-RW
/// </summary>
NERO_MTYP_DVD_M_RW = NERO_MTYP_DVD_M | NERO_MTYP_NO_DVD_M_R ,
/// <summary>
/// DVD+R
/// </summary>
NERO_MTYP_DVD_P_R = NERO_MTYP_DVD_P | NERO_MTYP_NO_DVD_P_RW ,
/// <summary>
/// DVD+RW
/// </summary>
NERO_MTYP_DVD_P_RW = NERO_MTYP_DVD_P | NERO_MTYP_NO_DVD_P_R ,
/// <summary>
/// Packet-writing (fixed)
/// </summary>
NERO_MTYP_FPACKET = 0x08000 ,
/// <summary>
/// Packet-writing (variable)
/// </summary>
NERO_MTYP_VPACKET = 0x10000 ,
/// <summary>
/// Packet-writing (any)
/// </summary>
NERO_MTYP_PACKETW = NERO_MTYP_MRW | NERO_MTYP_FPACKET | NERO_MTYP_VPACKET ,
/// <summary>
/// HD-Burn
/// </summary>
NERO_MTYP_HDB = 0x20000 ,
/// <summary>
/// DVD+R DL
/// </summary>
NERO_MTYP_DVD_P_R9 = 0x40000 ,
/// <summary>
/// DVD-R DL
/// </summary>
NERO_MTYP_DVD_M_R9 = 0x80000 ,
/// <summary>
/// Any DVD double-layer
/// </summary>
NERO_MTYP_DVD_ANY_R9 = NERO_MTYP_DVD_P_R9 | NERO_MTYP_DVD_M_R9 ,
/// <summary>
/// Any DVD
/// </summary>
NERO_MTYP_DVD_ANY = NERO_MTYP_DVD_M | NERO_MTYP_DVD_P | NERO_MTYP_DVD_RAM | NERO_MTYP_DVD_ANY_R9 ,
/// <summary>
/// BD-ROM
/// </summary>
NERO_MTYP_BD_ROM = 0x100000 ,
/// <summary>
/// BD-R
/// </summary>
NERO_MTYP_BD_R = 0x200000 ,
/// <summary>
/// BD-RE
/// </summary>
NERO_MTYP_BD_RE = 0x400000 ,
/// <summary>
/// BD-R/RE
/// </summary>
NERO_MTYP_BD = NERO_MTYP_BD_R | NERO_MTYP_BD_RE ,
/// <summary>
/// Any BD
/// </summary>
NERO_MTYP_BD_ANY = NERO_MTYP_BD | NERO_MTYP_BD_ROM ,
/// <summary>
/// HD DVD-ROM
/// </summary>
NERO_MTYP_HD_DVD_ROM = 0x0800000 ,
/// <summary>
/// HD DVD-R
/// </summary>
NERO_MTYP_HD_DVD_R = 0x1000000 ,
/// <summary>
/// HD DVD-RW
/// </summary>
NERO_MTYP_HD_DVD_RW = 0x2000000 ,
/// <summary>
/// HD DVD-R/RW
/// </summary>
NERO_MTYP_HD_DVD = NERO_MTYP_HD_DVD_R | NERO_MTYP_HD_DVD_RW ,
/// <summary>
/// Any HD DVD
/// </summary>
NERO_MTYP_HD_DVD_ANY = NERO_MTYP_HD_DVD | NERO_MTYP_HD_DVD_ROM ,
2016-08-08 18:44:08 +01:00
/// <summary>
/// Any DVD, old
/// </summary>
NERO_MTYP_DVD_ANY_OLD = NERO_MTYP_DVD_M | NERO_MTYP_DVD_P | NERO_MTYP_DVD_RAM ,
2014-07-09 19:52:00 +01:00
}
#endregion
#region Internal variables
string _imagePath ;
FileStream imageStream ;
FileInfo imageInfo ;
bool imageNewFormat ;
2016-07-28 22:25:26 +01:00
Dictionary < ushort , uint > neroSessions ;
2014-07-09 19:52:00 +01:00
NeroV1Cuesheet neroCuesheetV1 ;
NeroV2Cuesheet neroCuesheetV2 ;
NeroV1DAO neroDAOV1 ;
NeroV2DAO neroDAOV2 ;
NeroCDText neroCDTXT ;
NeroV1TAO neroTAOV1 ;
NeroV2TAO neroTAOV2 ;
NeroMediaType neroMediaTyp ;
NeroDiscInformation neroDiscInfo ;
NeroTOCChunk neroTOC ;
NeroRELOChunk neroRELO ;
List < Track > imageTracks ;
Dictionary < uint , byte [ ] > TrackISRCs ;
byte [ ] UPC ;
Dictionary < uint , NeroTrack > neroTracks ;
2016-07-28 22:25:26 +01:00
Dictionary < uint , ulong > offsetmap ;
2014-07-09 19:52:00 +01:00
List < Session > imageSessions ;
2016-07-28 22:25:26 +01:00
List < Partition > ImagePartitions ;
2014-07-09 19:52:00 +01:00
#endregion
#region Methods
2015-10-05 19:45:07 +01:00
public Nero ( )
2014-07-09 19:52:00 +01:00
{
Name = "Nero Burning ROM image" ;
PluginUUID = new Guid ( "D160F9FF-5941-43FC-B037-AD81DD141F05" ) ;
_imagePath = "" ;
imageNewFormat = false ;
2014-08-28 19:29:18 +01:00
ImageInfo = new ImageInfo ( ) ;
ImageInfo . readableSectorTags = new List < SectorTagType > ( ) ;
2016-01-16 03:54:55 +00:00
ImageInfo . readableMediaTags = new List < MediaTagType > ( ) ;
2016-07-28 22:25:26 +01:00
neroSessions = new Dictionary < ushort , uint > ( ) ;
2014-07-09 19:52:00 +01:00
neroTracks = new Dictionary < uint , NeroTrack > ( ) ;
offsetmap = new Dictionary < uint , ulong > ( ) ;
imageSessions = new List < Session > ( ) ;
2016-07-28 22:25:26 +01:00
ImagePartitions = new List < Partition > ( ) ;
2014-07-09 19:52:00 +01:00
}
// Due to .cue format, this method must parse whole file, ignoring errors (those will be thrown by OpenImage()).
public override bool IdentifyImage ( string imagePath )
{
imageInfo = new FileInfo ( imagePath ) ;
imageStream = new FileStream ( imagePath , FileMode . Open , FileAccess . Read ) ;
BigEndianBitConverter . IsLittleEndian = BitConverter . IsLittleEndian ;
byte [ ] buffer ;
NeroV1Footer footerV1 = new NeroV1Footer ( ) ;
NeroV2Footer footerV2 = new NeroV2Footer ( ) ;
imageStream . Seek ( - 8 , SeekOrigin . End ) ;
buffer = new byte [ 8 ] ;
imageStream . Read ( buffer , 0 , 8 ) ;
footerV1 . ChunkID = BigEndianBitConverter . ToUInt32 ( buffer , 0 ) ;
footerV1 . FirstChunkOffset = BigEndianBitConverter . ToUInt32 ( buffer , 4 ) ;
imageStream . Seek ( - 12 , SeekOrigin . End ) ;
buffer = new byte [ 12 ] ;
imageStream . Read ( buffer , 0 , 12 ) ;
footerV2 . ChunkID = BigEndianBitConverter . ToUInt32 ( buffer , 0 ) ;
footerV2 . FirstChunkOffset = BigEndianBitConverter . ToUInt64 ( buffer , 4 ) ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "imageInfo.Length = {0}" , imageInfo . Length ) ;
2016-08-17 01:32:20 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "footerV1.ChunkID = 0x{0:X8}" , footerV1 . ChunkID ) ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "footerV1.FirstChunkOffset = {0}" , footerV1 . FirstChunkOffset ) ;
2016-08-17 01:32:20 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "footerV2.ChunkID = 0x{0:X8}" , footerV2 . ChunkID ) ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "footerV2.FirstChunkOffset = {0}" , footerV2 . FirstChunkOffset ) ;
2014-07-09 19:52:00 +01:00
2016-04-19 02:11:47 +01:00
if ( footerV2 . ChunkID = = NeroV2FooterID & & footerV2 . FirstChunkOffset < ( ulong ) imageInfo . Length )
2014-07-09 19:52:00 +01:00
{
imageStream . Close ( ) ;
return true ;
}
2016-04-19 02:11:47 +01:00
if ( footerV1 . ChunkID = = NeroV1FooterID & & footerV1 . FirstChunkOffset < ( ulong ) imageInfo . Length )
2014-07-09 19:52:00 +01:00
{
imageStream . Close ( ) ;
return true ;
}
imageStream . Close ( ) ;
return false ;
}
public override bool OpenImage ( string imagePath )
{
try
{
imageInfo = new FileInfo ( imagePath ) ;
imageStream = new FileStream ( imagePath , FileMode . Open , FileAccess . Read ) ;
BigEndianBitConverter . IsLittleEndian = BitConverter . IsLittleEndian ;
byte [ ] buffer ;
NeroV1Footer footerV1 = new NeroV1Footer ( ) ;
NeroV2Footer footerV2 = new NeroV2Footer ( ) ;
imageStream . Seek ( - 8 , SeekOrigin . End ) ;
buffer = new byte [ 8 ] ;
imageStream . Read ( buffer , 0 , 8 ) ;
footerV1 . ChunkID = BigEndianBitConverter . ToUInt32 ( buffer , 0 ) ;
footerV1 . FirstChunkOffset = BigEndianBitConverter . ToUInt32 ( buffer , 4 ) ;
imageStream . Seek ( - 12 , SeekOrigin . End ) ;
buffer = new byte [ 12 ] ;
imageStream . Read ( buffer , 0 , 12 ) ;
footerV2 . ChunkID = BigEndianBitConverter . ToUInt32 ( buffer , 0 ) ;
footerV2 . FirstChunkOffset = BigEndianBitConverter . ToUInt64 ( buffer , 4 ) ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "imageInfo.Length = {0}" , imageInfo . Length ) ;
2016-08-17 01:32:20 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "footerV1.ChunkID = 0x{0:X8} (\"{1}\")" , footerV1 . ChunkID , System . Text . Encoding . ASCII . GetString ( BigEndianBitConverter . GetBytes ( footerV1 . ChunkID ) ) ) ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "footerV1.FirstChunkOffset = {0}" , footerV1 . FirstChunkOffset ) ;
2016-08-17 01:32:20 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "footerV2.ChunkID = 0x{0:X8} (\"{1}\")" , footerV2 . ChunkID , System . Text . Encoding . ASCII . GetString ( BigEndianBitConverter . GetBytes ( footerV2 . ChunkID ) ) ) ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "footerV2.FirstChunkOffset = {0}" , footerV2 . FirstChunkOffset ) ;
2014-07-09 19:52:00 +01:00
2016-04-19 02:11:47 +01:00
if ( footerV1 . ChunkID = = NeroV1FooterID & & footerV1 . FirstChunkOffset < ( ulong ) imageInfo . Length )
2014-07-09 19:52:00 +01:00
imageNewFormat = false ;
2016-04-19 02:11:47 +01:00
else if ( footerV2 . ChunkID = = NeroV2FooterID & & footerV2 . FirstChunkOffset < ( ulong ) imageInfo . Length )
2014-07-09 19:52:00 +01:00
imageNewFormat = true ;
else
{
imageStream . Close ( ) ;
return true ;
}
2016-04-19 02:11:47 +01:00
if ( imageNewFormat )
2014-07-09 19:52:00 +01:00
imageStream . Seek ( ( long ) footerV2 . FirstChunkOffset , SeekOrigin . Begin ) ;
else
imageStream . Seek ( footerV1 . FirstChunkOffset , SeekOrigin . Begin ) ;
bool parsing = true ;
ushort currentsession = 1 ;
uint currenttrack = 1 ;
imageTracks = new List < Track > ( ) ;
TrackISRCs = new Dictionary < uint , byte [ ] > ( ) ;
2016-01-16 03:54:55 +00:00
ImageInfo . mediaType = MediaType . CD ;
2014-08-28 19:29:18 +01:00
ImageInfo . sectors = 0 ;
ImageInfo . sectorSize = 0 ;
2014-07-09 19:52:00 +01:00
2016-04-19 02:11:47 +01:00
while ( parsing )
2014-07-09 19:52:00 +01:00
{
byte [ ] ChunkHeaderBuffer = new byte [ 8 ] ;
2016-07-28 22:25:26 +01:00
uint ChunkID ;
uint ChunkLength ;
2014-07-09 19:52:00 +01:00
imageStream . Read ( ChunkHeaderBuffer , 0 , 8 ) ;
ChunkID = BigEndianBitConverter . ToUInt32 ( ChunkHeaderBuffer , 0 ) ;
ChunkLength = BigEndianBitConverter . ToUInt32 ( ChunkHeaderBuffer , 4 ) ;
2016-08-17 01:32:20 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "ChunkID = 0x{0:X8} (\"{1}\")" , ChunkID , System . Text . Encoding . ASCII . GetString ( BigEndianBitConverter . GetBytes ( ChunkID ) ) ) ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "ChunkLength = {0}" , ChunkLength ) ;
2014-07-09 19:52:00 +01:00
2016-04-19 02:11:47 +01:00
switch ( ChunkID )
2014-07-09 19:52:00 +01:00
{
case NeroV1CUEID :
{
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "Found \"CUES\" chunk, parsing {0} bytes" , ChunkLength ) ;
2014-07-09 19:52:00 +01:00
neroCuesheetV1 = new NeroV1Cuesheet ( ) ;
neroCuesheetV1 . ChunkID = ChunkID ;
neroCuesheetV1 . ChunkSize = ChunkLength ;
neroCuesheetV1 . Entries = new List < NeroV1CueEntry > ( ) ;
byte [ ] tmpbuffer = new byte [ 8 ] ;
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < neroCuesheetV1 . ChunkSize ; i + = 8 )
2014-07-09 19:52:00 +01:00
{
NeroV1CueEntry _entry = new NeroV1CueEntry ( ) ;
imageStream . Read ( tmpbuffer , 0 , 8 ) ;
_entry . Mode = tmpbuffer [ 0 ] ;
_entry . TrackNumber = tmpbuffer [ 1 ] ;
_entry . IndexNumber = tmpbuffer [ 2 ] ;
_entry . Dummy = BigEndianBitConverter . ToUInt16 ( tmpbuffer , 3 ) ;
_entry . Minute = tmpbuffer [ 5 ] ;
_entry . Second = tmpbuffer [ 6 ] ;
_entry . Frame = tmpbuffer [ 7 ] ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "Cuesheet entry {0}" , ( i / 8 ) + 1 ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Mode = {1:X2}" , ( i / 8 ) + 1 , _entry . Mode ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].TrackNumber = {1:X2}" , ( i / 8 ) + 1 , _entry . TrackNumber ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].IndexNumber = {1:X2}" , ( i / 8 ) + 1 , _entry . IndexNumber ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Dummy = {1:X4}" , ( i / 8 ) + 1 , _entry . Dummy ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Minute = {1:X2}" , ( i / 8 ) + 1 , _entry . Minute ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Second = {1:X2}" , ( i / 8 ) + 1 , _entry . Second ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Frame = {1:X2}" , ( i / 8 ) + 1 , _entry . Frame ) ;
2014-07-09 19:52:00 +01:00
neroCuesheetV1 . Entries . Add ( _entry ) ;
}
break ;
}
case NeroV2CUEID :
{
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "Found \"CUEX\" chunk, parsing {0} bytes" , ChunkLength ) ;
2014-07-09 19:52:00 +01:00
neroCuesheetV2 = new NeroV2Cuesheet ( ) ;
neroCuesheetV2 . ChunkID = ChunkID ;
neroCuesheetV2 . ChunkSize = ChunkLength ;
neroCuesheetV2 . Entries = new List < NeroV2CueEntry > ( ) ;
byte [ ] tmpbuffer = new byte [ 8 ] ;
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < neroCuesheetV2 . ChunkSize ; i + = 8 )
2014-07-09 19:52:00 +01:00
{
NeroV2CueEntry _entry = new NeroV2CueEntry ( ) ;
imageStream . Read ( tmpbuffer , 0 , 8 ) ;
_entry . Mode = tmpbuffer [ 0 ] ;
_entry . TrackNumber = tmpbuffer [ 1 ] ;
_entry . IndexNumber = tmpbuffer [ 2 ] ;
_entry . Dummy = tmpbuffer [ 3 ] ;
_entry . LBAStart = BigEndianBitConverter . ToInt32 ( tmpbuffer , 4 ) ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "Cuesheet entry {0}" , ( i / 8 ) + 1 ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Mode = 0x{1:X2}" , ( i / 8 ) + 1 , _entry . Mode ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].TrackNumber = {1:X2}" , ( i / 8 ) + 1 , _entry . TrackNumber ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].IndexNumber = {1:X2}" , ( i / 8 ) + 1 , _entry . IndexNumber ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Dummy = {1:X2}" , ( i / 8 ) + 1 , _entry . Dummy ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].LBAStart = {1}" , ( i / 8 ) + 1 , _entry . LBAStart ) ;
2014-07-09 19:52:00 +01:00
neroCuesheetV2 . Entries . Add ( _entry ) ;
}
break ;
}
case NeroV1DAOID :
{
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "Found \"DAOI\" chunk, parsing {0} bytes" , ChunkLength ) ;
2014-07-09 19:52:00 +01:00
neroDAOV1 = new NeroV1DAO ( ) ;
neroDAOV1 . ChunkID = ChunkID ;
neroDAOV1 . ChunkSizeBe = ChunkLength ;
byte [ ] tmpbuffer = new byte [ 22 ] ;
imageStream . Read ( tmpbuffer , 0 , 22 ) ;
neroDAOV1 . ChunkSizeLe = BigEndianBitConverter . ToUInt32 ( tmpbuffer , 0 ) ;
neroDAOV1 . UPC = new byte [ 14 ] ;
Array . Copy ( tmpbuffer , 4 , neroDAOV1 . UPC , 0 , 14 ) ;
neroDAOV1 . TocType = BigEndianBitConverter . ToUInt16 ( tmpbuffer , 18 ) ;
neroDAOV1 . FirstTrack = tmpbuffer [ 20 ] ;
neroDAOV1 . LastTrack = tmpbuffer [ 21 ] ;
neroDAOV1 . Tracks = new List < NeroV1DAOEntry > ( ) ;
2016-04-19 02:11:47 +01:00
if ( ! ImageInfo . readableMediaTags . Contains ( MediaTagType . CD_MCN ) )
2016-01-16 03:54:55 +00:00
ImageInfo . readableMediaTags . Add ( MediaTagType . CD_MCN ) ;
2014-07-09 19:52:00 +01:00
2016-04-19 02:11:47 +01:00
if ( ! ImageInfo . readableSectorTags . Contains ( SectorTagType . CDTrackISRC ) )
2014-08-28 19:29:18 +01:00
ImageInfo . readableSectorTags . Add ( SectorTagType . CDTrackISRC ) ;
2014-07-09 19:52:00 +01:00
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "neroDAOV1.ChunkSizeLe = {0} bytes" , neroDAOV1 . ChunkSizeLe ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "neroDAOV1.UPC = \"{0}\"" , StringHandlers . CToString ( neroDAOV1 . UPC ) ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "neroDAOV1.TocType = 0x{0:X4}" , neroDAOV1 . TocType ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "neroDAOV1.FirstTrack = {0}" , neroDAOV1 . FirstTrack ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "neroDAOV1.LastTrack = {0}" , neroDAOV1 . LastTrack ) ;
2014-07-09 19:52:00 +01:00
UPC = neroDAOV1 . UPC ;
tmpbuffer = new byte [ 30 ] ;
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < ( neroDAOV1 . ChunkSizeBe - 22 ) ; i + = 30 )
2014-07-09 19:52:00 +01:00
{
NeroV1DAOEntry _entry = new NeroV1DAOEntry ( ) ;
imageStream . Read ( tmpbuffer , 0 , 30 ) ;
_entry . ISRC = new byte [ 12 ] ;
Array . Copy ( tmpbuffer , 4 , _entry . ISRC , 0 , 12 ) ;
_entry . SectorSize = BigEndianBitConverter . ToUInt16 ( tmpbuffer , 12 ) ;
_entry . Mode = BitConverter . ToUInt16 ( tmpbuffer , 14 ) ;
_entry . Unknown = BigEndianBitConverter . ToUInt16 ( tmpbuffer , 16 ) ;
_entry . Index0 = BigEndianBitConverter . ToUInt32 ( tmpbuffer , 18 ) ;
_entry . Index1 = BigEndianBitConverter . ToUInt32 ( tmpbuffer , 22 ) ;
_entry . EndOfTrack = BigEndianBitConverter . ToUInt32 ( tmpbuffer , 26 ) ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "Disc-At-Once entry {0}" , ( i / 32 ) + 1 ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].ISRC = \"{1}\"" , ( i / 32 ) + 1 , StringHandlers . CToString ( _entry . ISRC ) ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].SectorSize = {1}" , ( i / 32 ) + 1 , _entry . SectorSize ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Mode = {1} (0x{2:X4})" , ( i / 32 ) + 1 , ( DAOMode ) _entry . Mode , _entry . Mode ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Unknown = 0x{1:X4}" , ( i / 32 ) + 1 , _entry . Unknown ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Index0 = {1}" , ( i / 32 ) + 1 , _entry . Index0 ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Index1 = {1}" , ( i / 32 ) + 1 , _entry . Index1 ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].EndOfTrack = {1}" , ( i / 32 ) + 1 , _entry . EndOfTrack ) ;
2014-07-09 19:52:00 +01:00
neroDAOV1 . Tracks . Add ( _entry ) ;
2016-04-19 02:11:47 +01:00
if ( _entry . SectorSize > ImageInfo . sectorSize )
2014-08-28 19:29:18 +01:00
ImageInfo . sectorSize = _entry . SectorSize ;
2014-07-09 19:52:00 +01:00
TrackISRCs . Add ( currenttrack , _entry . ISRC ) ;
2016-08-08 18:44:08 +01:00
if ( currenttrack = = 1 )
_entry . Index0 = _entry . Index1 ;
2014-07-09 19:52:00 +01:00
NeroTrack _neroTrack = new NeroTrack ( ) ;
_neroTrack . EndOfTrack = _entry . EndOfTrack ;
_neroTrack . ISRC = _entry . ISRC ;
_neroTrack . Length = _entry . EndOfTrack - _entry . Index0 ;
_neroTrack . Mode = _entry . Mode ;
_neroTrack . Offset = _entry . Index0 ;
_neroTrack . Sectors = _neroTrack . Length / _entry . SectorSize ;
_neroTrack . SectorSize = _entry . SectorSize ;
2014-08-28 19:29:18 +01:00
_neroTrack . StartLBA = ImageInfo . sectors ;
2014-07-09 19:52:00 +01:00
_neroTrack . Index0 = _entry . Index0 ;
_neroTrack . Index1 = _entry . Index1 ;
_neroTrack . Sequence = currenttrack ;
neroTracks . Add ( currenttrack , _neroTrack ) ;
2014-08-28 19:29:18 +01:00
ImageInfo . sectors + = _neroTrack . Sectors ;
2014-07-09 19:52:00 +01:00
currenttrack + + ;
}
break ;
}
case NeroV2DAOID :
{
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "Found \"DAOX\" chunk, parsing {0} bytes" , ChunkLength ) ;
2014-07-09 19:52:00 +01:00
neroDAOV2 = new NeroV2DAO ( ) ;
neroDAOV2 . ChunkID = ChunkID ;
neroDAOV2 . ChunkSizeBe = ChunkLength ;
byte [ ] tmpbuffer = new byte [ 22 ] ;
imageStream . Read ( tmpbuffer , 0 , 22 ) ;
neroDAOV2 . ChunkSizeLe = BigEndianBitConverter . ToUInt32 ( tmpbuffer , 0 ) ;
neroDAOV2 . UPC = new byte [ 14 ] ;
Array . Copy ( tmpbuffer , 4 , neroDAOV2 . UPC , 0 , 14 ) ;
neroDAOV2 . TocType = BigEndianBitConverter . ToUInt16 ( tmpbuffer , 18 ) ;
neroDAOV1 . FirstTrack = tmpbuffer [ 20 ] ;
neroDAOV2 . LastTrack = tmpbuffer [ 21 ] ;
neroDAOV2 . Tracks = new List < NeroV2DAOEntry > ( ) ;
2016-04-19 02:11:47 +01:00
if ( ! ImageInfo . readableMediaTags . Contains ( MediaTagType . CD_MCN ) )
2016-01-16 03:54:55 +00:00
ImageInfo . readableMediaTags . Add ( MediaTagType . CD_MCN ) ;
2014-07-09 19:52:00 +01:00
2016-04-19 02:11:47 +01:00
if ( ! ImageInfo . readableSectorTags . Contains ( SectorTagType . CDTrackISRC ) )
2014-08-28 19:29:18 +01:00
ImageInfo . readableSectorTags . Add ( SectorTagType . CDTrackISRC ) ;
2014-07-09 19:52:00 +01:00
UPC = neroDAOV2 . UPC ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "neroDAOV2.ChunkSizeLe = {0} bytes" , neroDAOV2 . ChunkSizeLe ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "neroDAOV2.UPC = \"{0}\"" , StringHandlers . CToString ( neroDAOV2 . UPC ) ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "neroDAOV2.TocType = 0x{0:X4}" , neroDAOV2 . TocType ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "neroDAOV2.FirstTrack = {0}" , neroDAOV2 . FirstTrack ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "neroDAOV2.LastTrack = {0}" , neroDAOV2 . LastTrack ) ;
2014-07-09 19:52:00 +01:00
tmpbuffer = new byte [ 42 ] ;
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < ( neroDAOV2 . ChunkSizeBe - 22 ) ; i + = 42 )
2014-07-09 19:52:00 +01:00
{
NeroV2DAOEntry _entry = new NeroV2DAOEntry ( ) ;
imageStream . Read ( tmpbuffer , 0 , 42 ) ;
_entry . ISRC = new byte [ 12 ] ;
Array . Copy ( tmpbuffer , 4 , _entry . ISRC , 0 , 12 ) ;
_entry . SectorSize = BigEndianBitConverter . ToUInt16 ( tmpbuffer , 12 ) ;
_entry . Mode = BitConverter . ToUInt16 ( tmpbuffer , 14 ) ;
_entry . Unknown = BigEndianBitConverter . ToUInt16 ( tmpbuffer , 16 ) ;
_entry . Index0 = BigEndianBitConverter . ToUInt64 ( tmpbuffer , 18 ) ;
_entry . Index1 = BigEndianBitConverter . ToUInt64 ( tmpbuffer , 26 ) ;
_entry . EndOfTrack = BigEndianBitConverter . ToUInt64 ( tmpbuffer , 34 ) ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "Disc-At-Once entry {0}" , ( i / 32 ) + 1 ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].ISRC = \"{1}\"" , ( i / 32 ) + 1 , StringHandlers . CToString ( _entry . ISRC ) ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].SectorSize = {1}" , ( i / 32 ) + 1 , _entry . SectorSize ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Mode = {1} (0x{2:X4})" , ( i / 32 ) + 1 , ( DAOMode ) _entry . Mode , _entry . Mode ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Unknown = {1:X2}" , ( i / 32 ) + 1 , _entry . Unknown ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Index0 = {1}" , ( i / 32 ) + 1 , _entry . Index0 ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Index1 = {1}" , ( i / 32 ) + 1 , _entry . Index1 ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].EndOfTrack = {1}" , ( i / 32 ) + 1 , _entry . EndOfTrack ) ;
2014-07-09 19:52:00 +01:00
neroDAOV2 . Tracks . Add ( _entry ) ;
2016-04-19 02:11:47 +01:00
if ( _entry . SectorSize > ImageInfo . sectorSize )
2014-08-28 19:29:18 +01:00
ImageInfo . sectorSize = _entry . SectorSize ;
2014-07-09 19:52:00 +01:00
TrackISRCs . Add ( currenttrack , _entry . ISRC ) ;
2016-08-08 18:44:08 +01:00
if ( currenttrack = = 1 )
_entry . Index0 = _entry . Index1 ;
2014-07-09 19:52:00 +01:00
NeroTrack _neroTrack = new NeroTrack ( ) ;
_neroTrack . EndOfTrack = _entry . EndOfTrack ;
_neroTrack . ISRC = _entry . ISRC ;
_neroTrack . Length = _entry . EndOfTrack - _entry . Index0 ;
_neroTrack . Mode = _entry . Mode ;
_neroTrack . Offset = _entry . Index0 ;
_neroTrack . Sectors = _neroTrack . Length / _entry . SectorSize ;
_neroTrack . SectorSize = _entry . SectorSize ;
2014-08-28 19:29:18 +01:00
_neroTrack . StartLBA = ImageInfo . sectors ;
2014-07-09 19:52:00 +01:00
_neroTrack . Index0 = _entry . Index0 ;
_neroTrack . Index1 = _entry . Index1 ;
_neroTrack . Sequence = currenttrack ;
neroTracks . Add ( currenttrack , _neroTrack ) ;
2014-08-28 19:29:18 +01:00
ImageInfo . sectors + = _neroTrack . Sectors ;
2014-07-09 19:52:00 +01:00
currenttrack + + ;
}
break ;
}
case NeroCDTextID :
{
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "Found \"CDTX\" chunk, parsing {0} bytes" , ChunkLength ) ;
2014-07-09 19:52:00 +01:00
neroCDTXT = new NeroCDText ( ) ;
neroCDTXT . ChunkID = ChunkID ;
neroCDTXT . ChunkSize = ChunkLength ;
neroCDTXT . Packs = new List < NeroCDTextPack > ( ) ;
byte [ ] tmpbuffer = new byte [ 18 ] ;
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < ( neroCDTXT . ChunkSize ) ; i + = 18 )
2014-07-09 19:52:00 +01:00
{
NeroCDTextPack _entry = new NeroCDTextPack ( ) ;
imageStream . Read ( tmpbuffer , 0 , 18 ) ;
_entry . PackType = tmpbuffer [ 0 ] ;
_entry . TrackNumber = tmpbuffer [ 1 ] ;
_entry . PackNumber = tmpbuffer [ 2 ] ;
_entry . BlockNumber = tmpbuffer [ 3 ] ;
_entry . Text = new byte [ 12 ] ;
Array . Copy ( tmpbuffer , 4 , _entry . Text , 0 , 12 ) ;
_entry . CRC = BigEndianBitConverter . ToUInt16 ( tmpbuffer , 16 ) ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "CD-TEXT entry {0}" , ( i / 18 ) + 1 ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].PackType = 0x{1:X2}" , ( i / 18 ) + 1 , _entry . PackType ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].TrackNumber = 0x{1:X2}" , ( i / 18 ) + 1 , _entry . TrackNumber ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].PackNumber = 0x{1:X2}" , ( i / 18 ) + 1 , _entry . PackNumber ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].BlockNumber = 0x{1:X2}" , ( i / 18 ) + 1 , _entry . BlockNumber ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Text = \"{1}\"" , ( i / 18 ) + 1 , StringHandlers . CToString ( _entry . Text ) ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].CRC = 0x{1:X4}" , ( i / 18 ) + 1 , _entry . CRC ) ;
2014-07-09 19:52:00 +01:00
neroCDTXT . Packs . Add ( _entry ) ;
}
break ;
}
case NeroV1TAOID :
{
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "Found \"ETNF\" chunk, parsing {0} bytes" , ChunkLength ) ;
2014-07-09 19:52:00 +01:00
neroTAOV1 = new NeroV1TAO ( ) ;
neroTAOV1 . ChunkID = ChunkID ;
neroTAOV1 . ChunkSize = ChunkLength ;
neroTAOV1 . Tracks = new List < NeroV1TAOEntry > ( ) ;
byte [ ] tmpbuffer = new byte [ 20 ] ;
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < ( neroTAOV1 . ChunkSize ) ; i + = 20 )
2014-07-09 19:52:00 +01:00
{
NeroV1TAOEntry _entry = new NeroV1TAOEntry ( ) ;
imageStream . Read ( tmpbuffer , 0 , 20 ) ;
_entry . Offset = BigEndianBitConverter . ToUInt32 ( tmpbuffer , 0 ) ;
_entry . Length = BigEndianBitConverter . ToUInt32 ( tmpbuffer , 4 ) ;
_entry . Mode = BigEndianBitConverter . ToUInt32 ( tmpbuffer , 8 ) ;
_entry . StartLBA = BigEndianBitConverter . ToUInt32 ( tmpbuffer , 12 ) ;
_entry . Unknown = BigEndianBitConverter . ToUInt32 ( tmpbuffer , 16 ) ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "Track-at-Once entry {0}" , ( i / 20 ) + 1 ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Offset = {1}" , ( i / 20 ) + 1 , _entry . Offset ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Length = {1} bytes" , ( i / 20 ) + 1 , _entry . Length ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Mode = {1} (0x{2:X4})" , ( i / 20 ) + 1 , ( DAOMode ) _entry . Mode , _entry . Mode ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].StartLBA = {1}" , ( i / 20 ) + 1 , _entry . StartLBA ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Unknown = 0x{1:X4}" , ( i / 20 ) + 1 , _entry . Unknown ) ;
2014-07-09 19:52:00 +01:00
neroTAOV1 . Tracks . Add ( _entry ) ;
2016-04-19 02:11:47 +01:00
if ( NeroTrackModeToBytesPerSector ( ( DAOMode ) _entry . Mode ) > ImageInfo . sectorSize )
2014-08-28 19:29:18 +01:00
ImageInfo . sectorSize = NeroTrackModeToBytesPerSector ( ( DAOMode ) _entry . Mode ) ;
2014-07-09 19:52:00 +01:00
NeroTrack _neroTrack = new NeroTrack ( ) ;
_neroTrack . EndOfTrack = _entry . Offset + _entry . Length ;
_neroTrack . ISRC = new byte [ 12 ] ;
_neroTrack . Length = _entry . Length ;
_neroTrack . Mode = _entry . Mode ;
_neroTrack . Offset = _entry . Offset ;
_neroTrack . Sectors = _neroTrack . Length / NeroTrackModeToBytesPerSector ( ( DAOMode ) _entry . Mode ) ;
_neroTrack . SectorSize = NeroTrackModeToBytesPerSector ( ( DAOMode ) _entry . Mode ) ;
2014-08-28 19:29:18 +01:00
_neroTrack . StartLBA = ImageInfo . sectors ;
2014-07-09 19:52:00 +01:00
_neroTrack . Index0 = _entry . Offset ;
_neroTrack . Index1 = _entry . Offset ;
_neroTrack . Sequence = currenttrack ;
neroTracks . Add ( currenttrack , _neroTrack ) ;
2014-08-28 19:29:18 +01:00
ImageInfo . sectors + = _neroTrack . Sectors ;
2014-07-09 19:52:00 +01:00
currenttrack + + ;
}
break ;
}
case NeroV2TAOID :
{
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "Found \"ETN2\" chunk, parsing {0} bytes" , ChunkLength ) ;
2014-07-09 19:52:00 +01:00
neroTAOV2 = new NeroV2TAO ( ) ;
neroTAOV2 . ChunkID = ChunkID ;
neroTAOV2 . ChunkSize = ChunkLength ;
neroTAOV2 . Tracks = new List < NeroV2TAOEntry > ( ) ;
byte [ ] tmpbuffer = new byte [ 32 ] ;
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < ( neroTAOV2 . ChunkSize ) ; i + = 32 )
2014-07-09 19:52:00 +01:00
{
NeroV2TAOEntry _entry = new NeroV2TAOEntry ( ) ;
imageStream . Read ( tmpbuffer , 0 , 32 ) ;
_entry . Offset = BigEndianBitConverter . ToUInt64 ( tmpbuffer , 0 ) ;
_entry . Length = BigEndianBitConverter . ToUInt64 ( tmpbuffer , 8 ) ;
_entry . Mode = BigEndianBitConverter . ToUInt32 ( tmpbuffer , 16 ) ;
_entry . StartLBA = BigEndianBitConverter . ToUInt32 ( tmpbuffer , 20 ) ;
_entry . Unknown = BigEndianBitConverter . ToUInt32 ( tmpbuffer , 24 ) ;
_entry . Sectors = BigEndianBitConverter . ToUInt32 ( tmpbuffer , 28 ) ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "Track-at-Once entry {0}" , ( i / 32 ) + 1 ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Offset = {1}" , ( i / 32 ) + 1 , _entry . Offset ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Length = {1} bytes" , ( i / 32 ) + 1 , _entry . Length ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Mode = {1} (0x{2:X4})" , ( i / 32 ) + 1 , ( DAOMode ) _entry . Mode , _entry . Mode ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].StartLBA = {1}" , ( i / 32 ) + 1 , _entry . StartLBA ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Unknown = 0x{1:X4}" , ( i / 32 ) + 1 , _entry . Unknown ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Sectors = {1}" , ( i / 32 ) + 1 , _entry . Sectors ) ;
2014-07-09 19:52:00 +01:00
neroTAOV2 . Tracks . Add ( _entry ) ;
2016-04-19 02:11:47 +01:00
if ( NeroTrackModeToBytesPerSector ( ( DAOMode ) _entry . Mode ) > ImageInfo . sectorSize )
2014-08-28 19:29:18 +01:00
ImageInfo . sectorSize = NeroTrackModeToBytesPerSector ( ( DAOMode ) _entry . Mode ) ;
2014-07-09 19:52:00 +01:00
NeroTrack _neroTrack = new NeroTrack ( ) ;
_neroTrack . EndOfTrack = _entry . Offset + _entry . Length ;
_neroTrack . ISRC = new byte [ 12 ] ;
_neroTrack . Length = _entry . Length ;
_neroTrack . Mode = _entry . Mode ;
_neroTrack . Offset = _entry . Offset ;
_neroTrack . Sectors = _neroTrack . Length / NeroTrackModeToBytesPerSector ( ( DAOMode ) _entry . Mode ) ;
_neroTrack . SectorSize = NeroTrackModeToBytesPerSector ( ( DAOMode ) _entry . Mode ) ;
2014-08-28 19:29:18 +01:00
_neroTrack . StartLBA = ImageInfo . sectors ;
2014-07-09 19:52:00 +01:00
_neroTrack . Index0 = _entry . Offset ;
_neroTrack . Index1 = _entry . Offset ;
_neroTrack . Sequence = currenttrack ;
neroTracks . Add ( currenttrack , _neroTrack ) ;
2014-08-28 19:29:18 +01:00
ImageInfo . sectors + = _neroTrack . Sectors ;
2014-07-09 19:52:00 +01:00
currenttrack + + ;
}
break ;
}
case NeroSessionID :
{
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "Found \"SINF\" chunk, parsing {0} bytes" , ChunkLength ) ;
2014-07-09 19:52:00 +01:00
2016-07-28 22:25:26 +01:00
uint sessionTracks ;
2014-07-09 19:52:00 +01:00
byte [ ] tmpbuffer = new byte [ 4 ] ;
imageStream . Read ( tmpbuffer , 0 , 4 ) ;
sessionTracks = BigEndianBitConverter . ToUInt32 ( tmpbuffer , 0 ) ;
neroSessions . Add ( currentsession , sessionTracks ) ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "\tSession {0} has {1} tracks" , currentsession , sessionTracks ) ;
2014-07-09 19:52:00 +01:00
currentsession + + ;
break ;
}
case NeroDiskTypeID :
{
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "Found \"MTYP\" chunk, parsing {0} bytes" , ChunkLength ) ;
2014-07-09 19:52:00 +01:00
neroMediaTyp = new NeroMediaType ( ) ;
neroMediaTyp . ChunkID = ChunkID ;
neroMediaTyp . ChunkSize = ChunkLength ;
byte [ ] tmpbuffer = new byte [ 4 ] ;
imageStream . Read ( tmpbuffer , 0 , 4 ) ;
neroMediaTyp . Type = BigEndianBitConverter . ToUInt32 ( tmpbuffer , 0 ) ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "\tMedia type is {0} ({1})" , ( NeroMediaTypes ) neroMediaTyp . Type , neroMediaTyp . Type ) ;
2014-07-09 19:52:00 +01:00
2016-01-16 03:54:55 +00:00
ImageInfo . mediaType = NeroMediaTypeToMediaType ( ( NeroMediaTypes ) neroMediaTyp . Type ) ;
2014-07-09 19:52:00 +01:00
break ;
}
case NeroDiscInfoID :
{
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "Found \"DINF\" chunk, parsing {0} bytes" , ChunkLength ) ;
2014-07-09 19:52:00 +01:00
neroDiscInfo = new NeroDiscInformation ( ) ;
neroDiscInfo . ChunkID = ChunkID ;
neroDiscInfo . ChunkSize = ChunkLength ;
byte [ ] tmpbuffer = new byte [ 4 ] ;
imageStream . Read ( tmpbuffer , 0 , 4 ) ;
neroDiscInfo . Unknown = BigEndianBitConverter . ToUInt32 ( tmpbuffer , 0 ) ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "\tneroDiscInfo.Unknown = 0x{0:X4} ({0})" , neroDiscInfo . Unknown ) ;
2014-07-09 19:52:00 +01:00
break ;
}
case NeroReloID :
{
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "Found \"RELO\" chunk, parsing {0} bytes" , ChunkLength ) ;
2014-07-09 19:52:00 +01:00
neroRELO = new NeroRELOChunk ( ) ;
neroRELO . ChunkID = ChunkID ;
neroRELO . ChunkSize = ChunkLength ;
byte [ ] tmpbuffer = new byte [ 4 ] ;
imageStream . Read ( tmpbuffer , 0 , 4 ) ;
neroRELO . Unknown = BigEndianBitConverter . ToUInt32 ( tmpbuffer , 0 ) ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "\tneroRELO.Unknown = 0x{0:X4} ({0})" , neroRELO . Unknown ) ;
2014-07-09 19:52:00 +01:00
break ;
}
case NeroTOCID :
{
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "Found \"TOCT\" chunk, parsing {0} bytes" , ChunkLength ) ;
2014-07-09 19:52:00 +01:00
neroTOC = new NeroTOCChunk ( ) ;
neroTOC . ChunkID = ChunkID ;
neroTOC . ChunkSize = ChunkLength ;
byte [ ] tmpbuffer = new byte [ 2 ] ;
imageStream . Read ( tmpbuffer , 0 , 2 ) ;
neroTOC . Unknown = BigEndianBitConverter . ToUInt16 ( tmpbuffer , 0 ) ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "\tneroTOC.Unknown = 0x{0:X4} ({0})" , neroTOC . Unknown ) ;
2014-07-09 19:52:00 +01:00
break ;
}
case NeroEndID :
{
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "Found \"END!\" chunk, finishing parse" ) ;
2014-07-09 19:52:00 +01:00
parsing = false ;
break ;
}
default :
{
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "Unknown chunk ID \"{0}\", skipping..." , System . Text . Encoding . ASCII . GetString ( BigEndianBitConverter . GetBytes ( ChunkID ) ) ) ;
2014-07-09 19:52:00 +01:00
imageStream . Seek ( ChunkLength , SeekOrigin . Current ) ;
break ;
}
}
}
2014-08-28 19:29:18 +01:00
ImageInfo . imageHasPartitions = true ;
ImageInfo . imageHasSessions = true ;
ImageInfo . imageCreator = null ;
ImageInfo . imageCreationTime = imageInfo . CreationTimeUtc ;
ImageInfo . imageLastModificationTime = imageInfo . LastWriteTimeUtc ;
ImageInfo . imageName = Path . GetFileNameWithoutExtension ( imagePath ) ;
ImageInfo . imageComments = null ;
2016-01-16 03:54:55 +00:00
ImageInfo . mediaManufacturer = null ;
ImageInfo . mediaModel = null ;
ImageInfo . mediaSerialNumber = null ;
ImageInfo . mediaBarcode = null ;
ImageInfo . mediaPartNumber = null ;
2014-08-28 19:29:18 +01:00
ImageInfo . driveManufacturer = null ;
ImageInfo . driveModel = null ;
ImageInfo . driveSerialNumber = null ;
2016-01-16 03:54:55 +00:00
ImageInfo . mediaSequence = 0 ;
ImageInfo . lastMediaSequence = 0 ;
2016-04-19 02:11:47 +01:00
if ( imageNewFormat )
2014-07-09 19:52:00 +01:00
{
2014-08-28 19:29:18 +01:00
ImageInfo . imageSize = footerV2 . FirstChunkOffset ;
ImageInfo . imageVersion = "Nero Burning ROM >= 5.5" ;
ImageInfo . imageApplication = "Nero Burning ROM" ;
ImageInfo . imageApplicationVersion = ">= 5.5" ;
2014-07-09 19:52:00 +01:00
}
else
{
2014-08-28 19:29:18 +01:00
ImageInfo . imageSize = footerV1 . FirstChunkOffset ;
ImageInfo . imageVersion = "Nero Burning ROM <= 5.0" ;
ImageInfo . imageApplication = "Nero Burning ROM" ;
ImageInfo . imageApplicationVersion = "<= 5.0" ;
2014-07-09 19:52:00 +01:00
}
2016-04-19 02:11:47 +01:00
if ( neroSessions . Count = = 0 )
2014-07-09 19:52:00 +01:00
neroSessions . Add ( 1 , currenttrack ) ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "Building offset, track and session maps" ) ;
2014-07-09 19:52:00 +01:00
currentsession = 1 ;
uint currentsessionmaxtrack ;
neroSessions . TryGetValue ( 1 , out currentsessionmaxtrack ) ;
uint currentsessioncurrenttrack = 1 ;
Session currentsessionstruct = new Session ( ) ;
ulong PartitionSequence = 0 ;
2016-08-08 18:44:08 +01:00
ulong partitionStartByte = 0 ;
2016-04-19 02:11:47 +01:00
for ( uint i = 1 ; i < = neroTracks . Count ; i + + )
2014-07-09 19:52:00 +01:00
{
NeroTrack _neroTrack ;
2016-04-19 02:11:47 +01:00
if ( neroTracks . TryGetValue ( i , out _neroTrack ) )
2014-07-09 19:52:00 +01:00
{
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "\tcurrentsession = {0}" , currentsession ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\tcurrentsessionmaxtrack = {0}" , currentsessionmaxtrack ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\tcurrentsessioncurrenttrack = {0}" , currentsessioncurrenttrack ) ;
2014-07-09 19:52:00 +01:00
Track _track = new Track ( ) ;
2016-08-08 18:44:08 +01:00
if ( _neroTrack . Sequence = = 1 )
_neroTrack . Index0 = _neroTrack . Index1 ;
2014-07-09 19:52:00 +01:00
_track . Indexes = new Dictionary < int , ulong > ( ) ;
2016-04-19 02:11:47 +01:00
if ( _neroTrack . Index0 < _neroTrack . Index1 )
2014-07-09 19:52:00 +01:00
_track . Indexes . Add ( 0 , _neroTrack . Index0 / _neroTrack . SectorSize ) ;
_track . Indexes . Add ( 1 , _neroTrack . Index1 / _neroTrack . SectorSize ) ;
_track . TrackDescription = StringHandlers . CToString ( _neroTrack . ISRC ) ;
2016-08-08 18:44:08 +01:00
_track . TrackEndSector = ( _neroTrack . Length / _neroTrack . SectorSize ) + _neroTrack . StartLBA - 1 ;
2014-07-09 19:52:00 +01:00
_track . TrackPregap = ( _neroTrack . Index1 - _neroTrack . Index0 ) / _neroTrack . SectorSize ;
_track . TrackSequence = _neroTrack . Sequence ;
_track . TrackSession = currentsession ;
_track . TrackStartSector = _neroTrack . StartLBA ;
_track . TrackType = NeroTrackModeToTrackType ( ( DAOMode ) _neroTrack . Mode ) ;
2016-08-08 18:44:08 +01:00
_track . TrackFile = imagePath ;
2015-12-06 05:09:31 +00:00
_track . TrackFileOffset = _neroTrack . Offset ;
_track . TrackFileType = "BINARY" ;
_track . TrackSubchannelType = TrackSubchannelType . None ;
switch ( ( DAOMode ) _neroTrack . Mode )
{
case DAOMode . Audio :
_track . TrackBytesPerSector = 2352 ;
_track . TrackRawBytesPerSector = 2352 ;
break ;
case DAOMode . AudioSub :
_track . TrackBytesPerSector = 2352 ;
_track . TrackRawBytesPerSector = 2448 ;
_track . TrackSubchannelType = TrackSubchannelType . RawInterleaved ;
break ;
case DAOMode . Data :
case DAOMode . DataM2F1 :
_track . TrackBytesPerSector = 2048 ;
_track . TrackRawBytesPerSector = 2048 ;
break ;
case DAOMode . DataM2F2 :
_track . TrackBytesPerSector = 2336 ;
_track . TrackRawBytesPerSector = 2336 ;
break ;
case DAOMode . DataM2Raw :
_track . TrackBytesPerSector = 2352 ;
_track . TrackRawBytesPerSector = 2352 ;
break ;
case DAOMode . DataM2RawSub :
_track . TrackBytesPerSector = 2352 ;
_track . TrackRawBytesPerSector = 2448 ;
_track . TrackSubchannelType = TrackSubchannelType . RawInterleaved ;
break ;
case DAOMode . DataRaw :
_track . TrackBytesPerSector = 2048 ;
_track . TrackRawBytesPerSector = 2352 ;
break ;
case DAOMode . DataRawSub :
_track . TrackBytesPerSector = 2048 ;
_track . TrackRawBytesPerSector = 2448 ;
_track . TrackSubchannelType = TrackSubchannelType . RawInterleaved ;
break ;
}
if ( _track . TrackSubchannelType = = TrackSubchannelType . RawInterleaved )
{
_track . TrackSubchannelFile = _imagePath ;
_track . TrackSubchannelOffset = _neroTrack . Offset ;
}
2014-07-09 19:52:00 +01:00
2016-08-08 18:44:08 +01:00
imageTracks . Add ( _track ) ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "\t\t _track.TrackDescription = {0}" , _track . TrackDescription ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t\t _track.TrackEndSector = {0}" , _track . TrackEndSector ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t\t _track.TrackPregap = {0}" , _track . TrackPregap ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t\t _track.TrackSequence = {0}" , _track . TrackSequence ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t\t _track.TrackSession = {0}" , _track . TrackSession ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t\t _track.TrackStartSector = {0}" , _track . TrackStartSector ) ;
DicConsole . DebugWriteLine ( "Nero plugin" , "\t\t _track.TrackType = {0}" , _track . TrackType ) ;
2014-07-09 19:52:00 +01:00
2016-04-19 02:11:47 +01:00
if ( currentsessioncurrenttrack = = 1 )
2014-07-09 19:52:00 +01:00
{
currentsessionstruct = new Session ( ) ;
currentsessionstruct . SessionSequence = currentsession ;
currentsessionstruct . StartSector = _track . TrackStartSector ;
currentsessionstruct . StartTrack = _track . TrackSequence ;
}
currentsessioncurrenttrack + + ;
2016-04-19 02:11:47 +01:00
if ( currentsessioncurrenttrack > currentsessionmaxtrack )
2014-07-09 19:52:00 +01:00
{
currentsession + + ;
neroSessions . TryGetValue ( currentsession , out currentsessionmaxtrack ) ;
currentsessioncurrenttrack = 1 ;
currentsessionstruct . EndTrack = _track . TrackSequence ;
currentsessionstruct . EndSector = _track . TrackEndSector ;
imageSessions . Add ( currentsessionstruct ) ;
}
2016-08-08 18:44:08 +01:00
if ( i = = neroTracks . Count )
{
neroSessions . TryGetValue ( currentsession , out currentsessionmaxtrack ) ;
currentsessioncurrenttrack = 1 ;
currentsessionstruct . EndTrack = _track . TrackSequence ;
currentsessionstruct . EndSector = _track . TrackEndSector ;
imageSessions . Add ( currentsessionstruct ) ;
}
2014-07-09 19:52:00 +01:00
offsetmap . Add ( _track . TrackSequence , _track . TrackStartSector ) ;
2015-10-18 22:04:03 +01:00
DicConsole . DebugWriteLine ( "Nero plugin" , "\t\t Offset[{0}]: {1}" , _track . TrackSequence , _track . TrackStartSector ) ;
2016-04-19 02:11:47 +01:00
2016-07-28 22:25:26 +01:00
Partition partition ;
2014-07-09 19:52:00 +01:00
2016-08-08 18:44:08 +01:00
/ * if ( _neroTrack . Index0 < _neroTrack . Index1 )
2014-07-09 19:52:00 +01:00
{
2016-07-28 22:25:26 +01:00
partition = new Partition ( ) ;
partition . PartitionDescription = string . Format ( "Track {0} Index 0" , _track . TrackSequence ) ;
2014-07-09 19:52:00 +01:00
partition . PartitionLength = ( _neroTrack . Index1 - _neroTrack . Index0 ) ;
partition . PartitionName = StringHandlers . CToString ( _neroTrack . ISRC ) ;
partition . PartitionSectors = partition . PartitionLength / _neroTrack . SectorSize ;
partition . PartitionSequence = PartitionSequence ;
partition . PartitionStart = _neroTrack . Index0 ;
partition . PartitionStartSector = _neroTrack . StartLBA ;
partition . PartitionType = NeroTrackModeToTrackType ( ( DAOMode ) _neroTrack . Mode ) . ToString ( ) ;
ImagePartitions . Add ( partition ) ;
PartitionSequence + + ;
2016-08-08 18:44:08 +01:00
} * /
2014-07-09 19:52:00 +01:00
2016-07-28 22:25:26 +01:00
partition = new Partition ( ) ;
partition . PartitionDescription = string . Format ( "Track {0} Index 1" , _track . TrackSequence ) ;
2014-07-09 19:52:00 +01:00
partition . PartitionLength = ( _neroTrack . EndOfTrack - _neroTrack . Index1 ) ;
partition . PartitionName = StringHandlers . CToString ( _neroTrack . ISRC ) ;
partition . PartitionSectors = partition . PartitionLength / _neroTrack . SectorSize ;
partition . PartitionSequence = PartitionSequence ;
2016-08-08 18:44:08 +01:00
partition . PartitionStart = partitionStartByte ;
2014-07-09 19:52:00 +01:00
partition . PartitionStartSector = _neroTrack . StartLBA + ( ( _neroTrack . Index1 - _neroTrack . Index0 ) / _neroTrack . SectorSize ) ;
partition . PartitionType = NeroTrackModeToTrackType ( ( DAOMode ) _neroTrack . Mode ) . ToString ( ) ;
ImagePartitions . Add ( partition ) ;
PartitionSequence + + ;
2016-08-08 18:44:08 +01:00
partitionStartByte + = partition . PartitionLength ;
2014-07-09 19:52:00 +01:00
}
}
_imagePath = imagePath ;
imageStream . Close ( ) ;
2015-12-05 17:21:47 +00:00
2016-08-08 18:44:08 +01:00
if ( ImageInfo . mediaType = = MediaType . Unknown | | ImageInfo . mediaType = = MediaType . CD )
{
bool data = false ;
bool mode2 = false ;
bool firstaudio = false ;
bool firstdata = false ;
bool audio = false ;
for ( uint i = 0 ; i < neroTracks . Count ; i + + )
{
// First track is audio
firstaudio | = i = = 0 & & ( ( DAOMode ) neroTracks [ i ] . Mode = = DAOMode . Audio | | ( DAOMode ) neroTracks [ i ] . Mode = = DAOMode . AudioSub ) ;
// First track is data
firstdata | = i = = 0 & & ( ( DAOMode ) neroTracks [ i ] . Mode ! = DAOMode . Audio & & ( DAOMode ) neroTracks [ i ] . Mode ! = DAOMode . AudioSub ) ;
// Any non first track is data
data | = i ! = 0 & & ( ( DAOMode ) neroTracks [ i ] . Mode ! = DAOMode . Audio & & ( DAOMode ) neroTracks [ i ] . Mode ! = DAOMode . AudioSub ) ;
// Any non first track is audio
audio | = i ! = 0 & & ( ( DAOMode ) neroTracks [ i ] . Mode = = DAOMode . Audio | | ( DAOMode ) neroTracks [ i ] . Mode = = DAOMode . AudioSub ) ;
switch ( ( DAOMode ) neroTracks [ i ] . Mode )
{
case DAOMode . DataM2F1 :
case DAOMode . DataM2F2 :
case DAOMode . DataM2Raw :
case DAOMode . DataM2RawSub :
mode2 = true ;
break ;
}
}
if ( ! data & & ! firstdata )
ImageInfo . mediaType = MediaType . CDDA ;
else if ( firstaudio & & data & & imageSessions . Count > 1 & & mode2 )
ImageInfo . mediaType = MediaType . CDPLUS ;
else if ( ( firstdata & & audio ) | | mode2 )
ImageInfo . mediaType = MediaType . CDROMXA ;
else if ( ! audio )
ImageInfo . mediaType = MediaType . CDROM ;
else
ImageInfo . mediaType = MediaType . CD ;
}
2015-12-05 17:21:47 +00:00
ImageInfo . xmlMediaType = XmlMediaType . OpticalDisc ;
2014-07-09 19:52:00 +01:00
return true ;
}
catch
{
return false ;
}
}
public override bool ImageHasPartitions ( )
{
// Even if they only have 1 track, there is a partition (track 1)
return true ;
}
2016-07-28 22:25:26 +01:00
public override ulong GetImageSize ( )
2014-07-09 19:52:00 +01:00
{
2014-08-28 19:29:18 +01:00
return ImageInfo . imageSize ;
2014-07-09 19:52:00 +01:00
}
2016-07-28 22:25:26 +01:00
public override ulong GetSectors ( )
2014-07-09 19:52:00 +01:00
{
2014-08-28 19:29:18 +01:00
return ImageInfo . sectors ;
2014-07-09 19:52:00 +01:00
}
2016-07-28 22:25:26 +01:00
public override uint GetSectorSize ( )
2014-07-09 19:52:00 +01:00
{
2014-08-28 19:29:18 +01:00
return ImageInfo . sectorSize ;
2014-07-09 19:52:00 +01:00
}
2016-01-16 03:54:55 +00:00
public override byte [ ] ReadDiskTag ( MediaTagType tag )
2014-07-09 19:52:00 +01:00
{
2016-04-19 02:11:47 +01:00
switch ( tag )
2014-07-09 19:52:00 +01:00
{
2016-01-16 03:54:55 +00:00
case MediaTagType . CD_MCN :
2014-07-09 19:52:00 +01:00
return UPC ;
2016-01-16 03:54:55 +00:00
case MediaTagType . CD_TEXT :
2014-07-09 19:52:00 +01:00
throw new NotImplementedException ( "Not yet implemented" ) ;
default :
throw new FeaturedNotSupportedByDiscImageException ( "Requested disk tag not supported by image" ) ;
}
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSector ( ulong sectorAddress )
2014-07-09 19:52:00 +01:00
{
return ReadSectors ( sectorAddress , 1 ) ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectorTag ( ulong sectorAddress , SectorTagType tag )
2014-07-09 19:52:00 +01:00
{
return ReadSectorsTag ( sectorAddress , 1 , tag ) ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSector ( ulong sectorAddress , uint track )
2014-07-09 19:52:00 +01:00
{
return ReadSectors ( sectorAddress , 1 , track ) ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectorTag ( ulong sectorAddress , uint track , SectorTagType tag )
2014-07-09 19:52:00 +01:00
{
return ReadSectorsTag ( sectorAddress , 1 , track , tag ) ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectors ( ulong sectorAddress , uint length )
2014-07-09 19:52:00 +01:00
{
2016-04-19 02:11:47 +01:00
foreach ( KeyValuePair < uint , ulong > kvp in offsetmap )
2014-07-09 19:52:00 +01:00
{
2016-04-19 02:11:47 +01:00
if ( sectorAddress > = kvp . Value )
2014-07-09 19:52:00 +01:00
{
2016-04-19 02:11:47 +01:00
foreach ( Track _track in imageTracks )
2014-07-09 19:52:00 +01:00
{
2016-04-19 02:11:47 +01:00
if ( _track . TrackSequence = = kvp . Key )
2014-07-09 19:52:00 +01:00
{
2016-04-19 02:11:47 +01:00
if ( ( sectorAddress - kvp . Value ) < ( _track . TrackEndSector - _track . TrackStartSector ) )
2014-07-09 19:52:00 +01:00
return ReadSectors ( ( sectorAddress - kvp . Value ) , length , kvp . Key ) ;
}
}
}
}
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( sectorAddress ) , string . Format ( "Sector address {0} not found" , sectorAddress ) ) ;
2014-07-09 19:52:00 +01:00
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectorsTag ( ulong sectorAddress , uint length , SectorTagType tag )
2014-07-09 19:52:00 +01:00
{
2016-04-19 02:11:47 +01:00
foreach ( KeyValuePair < uint , ulong > kvp in offsetmap )
2014-07-09 19:52:00 +01:00
{
2016-04-19 02:11:47 +01:00
if ( sectorAddress > = kvp . Value )
2014-07-09 19:52:00 +01:00
{
2016-04-19 02:11:47 +01:00
foreach ( Track _track in imageTracks )
2014-07-09 19:52:00 +01:00
{
2016-04-19 02:11:47 +01:00
if ( _track . TrackSequence = = kvp . Key )
2014-07-09 19:52:00 +01:00
{
2016-04-19 02:11:47 +01:00
if ( ( sectorAddress - kvp . Value ) < ( _track . TrackEndSector - _track . TrackStartSector ) )
2014-07-09 19:52:00 +01:00
return ReadSectorsTag ( ( sectorAddress - kvp . Value ) , length , kvp . Key , tag ) ;
}
}
}
}
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( sectorAddress ) , string . Format ( "Sector address {0} not found" , sectorAddress ) ) ;
2014-07-09 19:52:00 +01:00
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectors ( ulong sectorAddress , uint length , uint track )
2014-07-09 19:52:00 +01:00
{
NeroTrack _track ;
2016-04-19 02:11:47 +01:00
if ( ! neroTracks . TryGetValue ( track , out _track ) )
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( track ) , "Track not found" ) ;
2014-07-09 19:52:00 +01:00
2016-04-19 02:11:47 +01:00
if ( length > _track . Sectors )
2016-08-08 18:44:08 +01:00
throw new ArgumentOutOfRangeException ( nameof ( length ) , string . Format ( "Requested more sectors ({0}) than present in track ({1}), won't cross tracks" , length , _track . Sectors ) ) ;
2014-07-09 19:52:00 +01:00
uint sector_offset ;
uint sector_size ;
uint sector_skip ;
2016-04-19 02:11:47 +01:00
switch ( ( DAOMode ) _track . Mode )
2014-07-09 19:52:00 +01:00
{
case DAOMode . Data :
case DAOMode . DataM2F1 :
{
sector_offset = 0 ;
sector_size = 2048 ;
sector_skip = 0 ;
break ;
}
case DAOMode . DataM2F2 :
{
sector_offset = 8 ;
sector_size = 2324 ;
sector_skip = 4 ;
break ;
}
case DAOMode . Audio :
{
sector_offset = 0 ;
sector_size = 2352 ;
sector_skip = 0 ;
break ;
}
case DAOMode . DataRaw :
{
sector_offset = 16 ;
sector_size = 2048 ;
sector_skip = 288 ;
break ;
}
case DAOMode . DataM2Raw :
{
2016-08-08 18:44:08 +01:00
sector_offset = 16 ;
sector_size = 2336 ;
sector_skip = 0 ;
2014-07-09 19:52:00 +01:00
break ;
}
2016-04-19 02:11:47 +01:00
// TODO: Supposing Nero suffixes the subchannel to the channel
2014-07-09 19:52:00 +01:00
case DAOMode . DataRawSub :
{
sector_offset = 16 ;
sector_size = 2048 ;
sector_skip = 288 + 96 ;
break ;
}
case DAOMode . DataM2RawSub :
{
2016-08-08 18:44:08 +01:00
sector_offset = 16 ;
sector_size = 2336 ;
sector_skip = 96 ;
2014-07-09 19:52:00 +01:00
break ;
}
case DAOMode . AudioSub :
{
sector_offset = 0 ;
sector_size = 2352 ;
sector_skip = 96 ;
break ;
}
default :
throw new FeatureSupportedButNotImplementedImageException ( "Unsupported track type" ) ;
}
byte [ ] buffer = new byte [ sector_size * length ] ;
imageStream = new FileStream ( _imagePath , FileMode . Open , FileAccess . Read ) ;
2016-04-19 02:11:47 +01:00
using ( BinaryReader br = new BinaryReader ( imageStream ) )
2014-07-09 19:52:00 +01:00
{
br . BaseStream . Seek ( ( long ) _track . Offset + ( long ) ( sectorAddress * ( sector_offset + sector_size + sector_skip ) ) , SeekOrigin . Begin ) ;
2016-04-19 02:11:47 +01:00
if ( sector_offset = = 0 & & sector_skip = = 0 )
2014-07-09 19:52:00 +01:00
buffer = br . ReadBytes ( ( int ) ( sector_size * length ) ) ;
else
{
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < length ; i + + )
2014-07-09 19:52:00 +01:00
{
byte [ ] sector ;
br . BaseStream . Seek ( sector_offset , SeekOrigin . Current ) ;
sector = br . ReadBytes ( ( int ) sector_size ) ;
br . BaseStream . Seek ( sector_skip , SeekOrigin . Current ) ;
Array . Copy ( sector , 0 , buffer , i * sector_size , sector_size ) ;
}
}
}
imageStream . Close ( ) ;
return buffer ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectorsTag ( ulong sectorAddress , uint length , uint track , SectorTagType tag )
2014-07-09 19:52:00 +01:00
{
NeroTrack _track ;
2016-04-19 02:11:47 +01:00
if ( ! neroTracks . TryGetValue ( track , out _track ) )
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( track ) , "Track not found" ) ;
2014-07-09 19:52:00 +01:00
2016-04-19 02:11:47 +01:00
if ( length > _track . Sectors )
2016-08-08 18:44:08 +01:00
throw new ArgumentOutOfRangeException ( nameof ( length ) , string . Format ( "Requested more sectors ({0}) than present in track ({1}), won't cross tracks" , length , _track . Sectors ) ) ;
2014-07-09 19:52:00 +01:00
uint sector_offset ;
uint sector_size ;
uint sector_skip ;
2016-04-19 02:11:47 +01:00
switch ( tag )
2014-07-09 19:52:00 +01:00
{
case SectorTagType . CDSectorECC :
case SectorTagType . CDSectorECC_P :
case SectorTagType . CDSectorECC_Q :
case SectorTagType . CDSectorEDC :
case SectorTagType . CDSectorHeader :
case SectorTagType . CDSectorSubchannel :
case SectorTagType . CDSectorSubHeader :
case SectorTagType . CDSectorSync :
break ;
case SectorTagType . CDTrackFlags :
{
byte [ ] flags = new byte [ 1 ] ;
flags [ 0 ] = 0x00 ;
2016-04-19 02:11:47 +01:00
if ( ( DAOMode ) _track . Mode ! = DAOMode . Audio & & ( DAOMode ) _track . Mode ! = DAOMode . AudioSub )
2014-07-09 19:52:00 +01:00
flags [ 0 ] + = 0x40 ;
return flags ;
}
case SectorTagType . CDTrackISRC :
return _track . ISRC ;
case SectorTagType . CDTrackText :
throw new FeatureSupportedButNotImplementedImageException ( "Feature not yet implemented" ) ;
default :
2016-07-28 22:25:26 +01:00
throw new ArgumentException ( "Unsupported tag requested" , nameof ( tag ) ) ;
2014-07-09 19:52:00 +01:00
}
2016-04-19 02:11:47 +01:00
switch ( ( DAOMode ) _track . Mode )
2014-07-09 19:52:00 +01:00
{
case DAOMode . Data :
case DAOMode . DataM2F1 :
2016-07-28 22:25:26 +01:00
throw new ArgumentException ( "No tags in image for requested track" , nameof ( tag ) ) ;
2014-07-09 19:52:00 +01:00
case DAOMode . DataM2F2 :
{
2016-04-19 02:11:47 +01:00
switch ( tag )
2014-07-09 19:52:00 +01:00
{
case SectorTagType . CDSectorSync :
case SectorTagType . CDSectorHeader :
case SectorTagType . CDSectorSubchannel :
case SectorTagType . CDSectorECC :
case SectorTagType . CDSectorECC_P :
case SectorTagType . CDSectorECC_Q :
2016-07-28 22:25:26 +01:00
throw new ArgumentException ( "Unsupported tag requested for this track" , nameof ( tag ) ) ;
2014-07-09 19:52:00 +01:00
case SectorTagType . CDSectorSubHeader :
{
sector_offset = 0 ;
sector_size = 8 ;
sector_skip = 2328 ;
break ;
}
case SectorTagType . CDSectorEDC :
{
sector_offset = 2332 ;
sector_size = 4 ;
sector_skip = 0 ;
break ;
}
default :
2016-07-28 22:25:26 +01:00
throw new ArgumentException ( "Unsupported tag requested" , nameof ( tag ) ) ;
2014-07-09 19:52:00 +01:00
}
break ;
}
case DAOMode . Audio :
2016-07-28 22:25:26 +01:00
throw new ArgumentException ( "There are no tags on audio tracks" , nameof ( tag ) ) ;
2014-07-09 19:52:00 +01:00
case DAOMode . DataRaw :
{
2016-04-19 02:11:47 +01:00
switch ( tag )
2014-07-09 19:52:00 +01:00
{
case SectorTagType . CDSectorSync :
{
sector_offset = 0 ;
sector_size = 12 ;
sector_skip = 2340 ;
break ;
}
case SectorTagType . CDSectorHeader :
{
sector_offset = 12 ;
sector_size = 4 ;
sector_skip = 2336 ;
break ;
}
case SectorTagType . CDSectorSubchannel :
case SectorTagType . CDSectorSubHeader :
2016-07-28 22:25:26 +01:00
throw new ArgumentException ( "Unsupported tag requested for this track" , nameof ( tag ) ) ;
2014-07-09 19:52:00 +01:00
case SectorTagType . CDSectorECC :
{
sector_offset = 2076 ;
sector_size = 276 ;
sector_skip = 0 ;
break ;
}
case SectorTagType . CDSectorECC_P :
{
sector_offset = 2076 ;
sector_size = 172 ;
sector_skip = 104 ;
break ;
}
case SectorTagType . CDSectorECC_Q :
{
sector_offset = 2248 ;
sector_size = 104 ;
sector_skip = 0 ;
break ;
}
case SectorTagType . CDSectorEDC :
{
sector_offset = 2064 ;
sector_size = 4 ;
sector_skip = 284 ;
break ;
}
default :
2016-07-28 22:25:26 +01:00
throw new ArgumentException ( "Unsupported tag requested" , nameof ( tag ) ) ;
2014-07-09 19:52:00 +01:00
}
break ;
}
2016-04-19 02:11:47 +01:00
// TODO
2014-07-09 19:52:00 +01:00
case DAOMode . DataM2RawSub :
throw new FeatureSupportedButNotImplementedImageException ( "Feature not yet implemented" ) ;
case DAOMode . DataRawSub :
{
2016-04-19 02:11:47 +01:00
switch ( tag )
2014-07-09 19:52:00 +01:00
{
case SectorTagType . CDSectorSync :
{
sector_offset = 0 ;
sector_size = 12 ;
sector_skip = 2340 + 96 ;
break ;
}
case SectorTagType . CDSectorHeader :
{
sector_offset = 12 ;
sector_size = 4 ;
sector_skip = 2336 + 96 ;
break ;
}
case SectorTagType . CDSectorSubchannel :
{
sector_offset = 2352 ;
sector_size = 96 ;
sector_skip = 0 ;
break ;
}
case SectorTagType . CDSectorSubHeader :
2016-07-28 22:25:26 +01:00
throw new ArgumentException ( "Unsupported tag requested for this track" , nameof ( tag ) ) ;
2014-07-09 19:52:00 +01:00
case SectorTagType . CDSectorECC :
{
sector_offset = 2076 ;
sector_size = 276 ;
sector_skip = 0 + 96 ;
break ;
}
case SectorTagType . CDSectorECC_P :
{
sector_offset = 2076 ;
sector_size = 172 ;
sector_skip = 104 + 96 ;
break ;
}
case SectorTagType . CDSectorECC_Q :
{
sector_offset = 2248 ;
sector_size = 104 ;
sector_skip = 0 + 96 ;
break ;
}
case SectorTagType . CDSectorEDC :
{
sector_offset = 2064 ;
sector_size = 4 ;
sector_skip = 284 + 96 ;
break ;
}
default :
2016-07-28 22:25:26 +01:00
throw new ArgumentException ( "Unsupported tag requested" , nameof ( tag ) ) ;
2014-07-09 19:52:00 +01:00
}
break ;
}
case DAOMode . AudioSub :
{
2016-04-19 02:11:47 +01:00
if ( tag ! = SectorTagType . CDSectorSubchannel )
2016-07-28 22:25:26 +01:00
throw new ArgumentException ( "Unsupported tag requested for this track" , nameof ( tag ) ) ;
2014-07-09 19:52:00 +01:00
sector_offset = 2352 ;
sector_size = 96 ;
sector_skip = 0 ;
break ;
}
default :
throw new FeatureSupportedButNotImplementedImageException ( "Unsupported track type" ) ;
}
byte [ ] buffer = new byte [ sector_size * length ] ;
imageStream = new FileStream ( _imagePath , FileMode . Open , FileAccess . Read ) ;
2016-04-19 02:11:47 +01:00
using ( BinaryReader br = new BinaryReader ( imageStream ) )
2014-07-09 19:52:00 +01:00
{
br . BaseStream . Seek ( ( long ) _track . Offset + ( long ) ( sectorAddress * ( sector_offset + sector_size + sector_skip ) ) , SeekOrigin . Begin ) ;
2016-04-19 02:11:47 +01:00
if ( sector_offset = = 0 & & sector_skip = = 0 )
2014-07-09 19:52:00 +01:00
buffer = br . ReadBytes ( ( int ) ( sector_size * length ) ) ;
else
{
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < length ; i + + )
2014-07-09 19:52:00 +01:00
{
byte [ ] sector ;
br . BaseStream . Seek ( sector_offset , SeekOrigin . Current ) ;
sector = br . ReadBytes ( ( int ) sector_size ) ;
br . BaseStream . Seek ( sector_skip , SeekOrigin . Current ) ;
Array . Copy ( sector , 0 , buffer , i * sector_size , sector_size ) ;
}
}
}
imageStream . Close ( ) ;
return buffer ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectorLong ( ulong sectorAddress )
2014-07-09 19:52:00 +01:00
{
return ReadSectorsLong ( sectorAddress , 1 ) ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectorLong ( ulong sectorAddress , uint track )
2014-07-09 19:52:00 +01:00
{
return ReadSectorsLong ( sectorAddress , 1 , track ) ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectorsLong ( ulong sectorAddress , uint length )
2014-07-09 19:52:00 +01:00
{
2016-04-19 02:11:47 +01:00
foreach ( KeyValuePair < uint , ulong > kvp in offsetmap )
2014-07-09 19:52:00 +01:00
{
2016-04-19 02:11:47 +01:00
if ( sectorAddress > = kvp . Value )
2014-07-09 19:52:00 +01:00
{
2016-04-19 02:11:47 +01:00
foreach ( Track _track in imageTracks )
2014-07-09 19:52:00 +01:00
{
2016-04-19 02:11:47 +01:00
if ( _track . TrackSequence = = kvp . Key )
2014-07-09 19:52:00 +01:00
{
2016-04-19 02:11:47 +01:00
if ( ( sectorAddress - kvp . Value ) < ( _track . TrackEndSector - _track . TrackStartSector ) )
2014-07-09 19:52:00 +01:00
return ReadSectorsLong ( ( sectorAddress - kvp . Value ) , length , kvp . Key ) ;
}
}
}
}
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( sectorAddress ) , string . Format ( "Sector address {0} not found" , sectorAddress ) ) ;
2014-07-09 19:52:00 +01:00
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectorsLong ( ulong sectorAddress , uint length , uint track )
2014-07-09 19:52:00 +01:00
{
NeroTrack _track ;
2016-04-19 02:11:47 +01:00
if ( ! neroTracks . TryGetValue ( track , out _track ) )
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( track ) , "Track not found" ) ;
2014-07-09 19:52:00 +01:00
2016-04-19 02:11:47 +01:00
if ( length > _track . Sectors )
2016-08-08 18:44:08 +01:00
throw new ArgumentOutOfRangeException ( nameof ( length ) , string . Format ( "Requested more sectors ({0}) than present in track ({1}), won't cross tracks" , length , _track . Sectors ) ) ;
2014-07-09 19:52:00 +01:00
uint sector_offset ;
uint sector_size ;
uint sector_skip ;
2016-04-19 02:11:47 +01:00
switch ( ( DAOMode ) _track . Mode )
2014-07-09 19:52:00 +01:00
{
case DAOMode . Data :
case DAOMode . DataM2F1 :
{
sector_offset = 0 ;
sector_size = 2048 ;
sector_skip = 0 ;
break ;
}
case DAOMode . DataM2F2 :
{
sector_offset = 0 ;
sector_size = 2336 ;
sector_skip = 0 ;
break ;
}
case DAOMode . DataRaw :
case DAOMode . DataM2Raw :
case DAOMode . Audio :
{
sector_offset = 0 ;
sector_size = 2352 ;
sector_skip = 0 ;
break ;
}
case DAOMode . DataRawSub :
case DAOMode . DataM2RawSub :
case DAOMode . AudioSub :
{
sector_offset = 0 ;
sector_size = 2448 ;
sector_skip = 0 ;
break ;
}
default :
throw new FeatureSupportedButNotImplementedImageException ( "Unsupported track type" ) ;
}
byte [ ] buffer = new byte [ sector_size * length ] ;
imageStream = new FileStream ( _imagePath , FileMode . Open , FileAccess . Read ) ;
BinaryReader br = new BinaryReader ( imageStream ) ;
br . BaseStream . Seek ( ( long ) _track . Offset + ( long ) ( sectorAddress * ( sector_offset + sector_size + sector_skip ) ) , SeekOrigin . Begin ) ;
2016-04-19 02:11:47 +01:00
if ( sector_offset = = 0 & & sector_skip = = 0 )
2014-07-09 19:52:00 +01:00
buffer = br . ReadBytes ( ( int ) ( sector_size * length ) ) ;
else
{
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < length ; i + + )
2014-07-09 19:52:00 +01:00
{
byte [ ] sector ;
br . BaseStream . Seek ( sector_offset , SeekOrigin . Current ) ;
sector = br . ReadBytes ( ( int ) sector_size ) ;
br . BaseStream . Seek ( sector_skip , SeekOrigin . Current ) ;
Array . Copy ( sector , 0 , buffer , i * sector_size , sector_size ) ;
}
}
imageStream . Close ( ) ;
return buffer ;
}
public override string GetImageFormat ( )
{
return "Nero Burning ROM" ;
}
public override string GetImageVersion ( )
{
2014-08-28 19:29:18 +01:00
return ImageInfo . imageVersion ;
2014-07-09 19:52:00 +01:00
}
public override string GetImageApplication ( )
{
2014-08-28 19:29:18 +01:00
return ImageInfo . imageApplication ;
2014-07-09 19:52:00 +01:00
}
public override string GetImageApplicationVersion ( )
{
2014-08-28 19:29:18 +01:00
return ImageInfo . imageApplicationVersion ;
2014-07-09 19:52:00 +01:00
}
public override DateTime GetImageCreationTime ( )
{
2014-08-28 19:29:18 +01:00
return ImageInfo . imageCreationTime ;
2014-07-09 19:52:00 +01:00
}
public override DateTime GetImageLastModificationTime ( )
{
2014-08-28 19:29:18 +01:00
return ImageInfo . imageLastModificationTime ;
2014-07-09 19:52:00 +01:00
}
2016-01-16 03:54:55 +00:00
public override string GetMediaBarcode ( )
2014-07-09 19:52:00 +01:00
{
2016-01-16 03:54:55 +00:00
return ImageInfo . mediaBarcode ;
2014-07-09 19:52:00 +01:00
}
2016-01-16 03:54:55 +00:00
public override MediaType GetMediaType ( )
2014-07-09 19:52:00 +01:00
{
2016-01-16 03:54:55 +00:00
return ImageInfo . mediaType ;
2014-07-09 19:52:00 +01:00
}
2016-07-28 22:25:26 +01:00
public override List < Partition > GetPartitions ( )
2014-07-09 19:52:00 +01:00
{
return ImagePartitions ;
}
public override List < Track > GetTracks ( )
{
return imageTracks ;
}
public override List < Track > GetSessionTracks ( Session session )
{
return GetSessionTracks ( session . SessionSequence ) ;
}
2016-07-28 22:25:26 +01:00
public override List < Track > GetSessionTracks ( ushort session )
2014-07-09 19:52:00 +01:00
{
List < Track > sessionTracks = new List < Track > ( ) ;
2016-04-19 02:11:47 +01:00
foreach ( Track _track in imageTracks )
if ( _track . TrackSession = = session )
2014-07-09 19:52:00 +01:00
sessionTracks . Add ( _track ) ;
return sessionTracks ;
}
public override List < Session > GetSessions ( )
{
return imageSessions ;
}
2016-07-28 22:25:26 +01:00
public override bool? VerifySector ( ulong sectorAddress )
2014-08-25 05:00:25 +01:00
{
byte [ ] buffer = ReadSectorLong ( sectorAddress ) ;
return Checksums . CDChecksums . CheckCDSector ( buffer ) ;
}
2016-07-28 22:25:26 +01:00
public override bool? VerifySector ( ulong sectorAddress , uint track )
2014-08-25 05:00:25 +01:00
{
byte [ ] buffer = ReadSectorLong ( sectorAddress , track ) ;
return Checksums . CDChecksums . CheckCDSector ( buffer ) ;
}
2016-07-28 22:25:26 +01:00
public override bool? VerifySectors ( ulong sectorAddress , uint length , out List < ulong > FailingLBAs , out List < ulong > UnknownLBAs )
2014-08-25 05:00:25 +01:00
{
byte [ ] buffer = ReadSectorsLong ( sectorAddress , length ) ;
int bps = ( int ) ( buffer . Length / length ) ;
byte [ ] sector = new byte [ bps ] ;
2016-07-28 22:25:26 +01:00
FailingLBAs = new List < ulong > ( ) ;
UnknownLBAs = new List < ulong > ( ) ;
2014-08-25 05:00:25 +01:00
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < length ; i + + )
2014-08-25 05:00:25 +01:00
{
Array . Copy ( buffer , i * bps , sector , 0 , bps ) ;
bool? sectorStatus = Checksums . CDChecksums . CheckCDSector ( sector ) ;
2016-04-19 02:11:47 +01:00
switch ( sectorStatus )
2014-08-25 05:00:25 +01:00
{
case null :
UnknownLBAs . Add ( ( ulong ) i + sectorAddress ) ;
break ;
case false :
FailingLBAs . Add ( ( ulong ) i + sectorAddress ) ;
break ;
}
}
2016-04-19 02:11:47 +01:00
if ( UnknownLBAs . Count > 0 )
2014-08-25 05:00:25 +01:00
return null ;
2016-04-19 02:11:47 +01:00
if ( FailingLBAs . Count > 0 )
2014-08-25 05:00:25 +01:00
return false ;
return true ;
}
2016-07-28 22:25:26 +01:00
public override bool? VerifySectors ( ulong sectorAddress , uint length , uint track , out List < ulong > FailingLBAs , out List < ulong > UnknownLBAs )
2014-08-25 05:00:25 +01:00
{
byte [ ] buffer = ReadSectorsLong ( sectorAddress , length , track ) ;
int bps = ( int ) ( buffer . Length / length ) ;
byte [ ] sector = new byte [ bps ] ;
2016-07-28 22:25:26 +01:00
FailingLBAs = new List < ulong > ( ) ;
UnknownLBAs = new List < ulong > ( ) ;
2014-08-25 05:00:25 +01:00
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < length ; i + + )
2014-08-25 05:00:25 +01:00
{
Array . Copy ( buffer , i * bps , sector , 0 , bps ) ;
bool? sectorStatus = Checksums . CDChecksums . CheckCDSector ( sector ) ;
2016-04-19 02:11:47 +01:00
switch ( sectorStatus )
2014-08-25 05:00:25 +01:00
{
case null :
UnknownLBAs . Add ( ( ulong ) i + sectorAddress ) ;
break ;
case false :
FailingLBAs . Add ( ( ulong ) i + sectorAddress ) ;
break ;
}
}
2016-04-19 02:11:47 +01:00
if ( UnknownLBAs . Count > 0 )
2014-08-25 05:00:25 +01:00
return null ;
2016-04-19 02:11:47 +01:00
if ( FailingLBAs . Count > 0 )
2014-08-25 05:00:25 +01:00
return false ;
return true ;
}
2016-01-16 03:54:55 +00:00
public override bool? VerifyMediaImage ( )
2014-08-25 05:00:25 +01:00
{
return null ;
}
2014-07-09 19:52:00 +01:00
#endregion
#region Private methods
2016-01-16 03:54:55 +00:00
static MediaType NeroMediaTypeToMediaType ( NeroMediaTypes type )
2014-07-09 19:52:00 +01:00
{
2016-04-19 02:11:47 +01:00
switch ( type )
2014-07-09 19:52:00 +01:00
{
case NeroMediaTypes . NERO_MTYP_DDCD :
2016-01-16 03:54:55 +00:00
return MediaType . DDCD ;
2014-07-09 19:52:00 +01:00
case NeroMediaTypes . NERO_MTYP_DVD_M :
case NeroMediaTypes . NERO_MTYP_DVD_M_R :
2016-01-16 03:54:55 +00:00
return MediaType . DVDR ;
2014-07-09 19:52:00 +01:00
case NeroMediaTypes . NERO_MTYP_DVD_P :
case NeroMediaTypes . NERO_MTYP_DVD_P_R :
2016-01-16 03:54:55 +00:00
return MediaType . DVDPR ;
2014-07-09 19:52:00 +01:00
case NeroMediaTypes . NERO_MTYP_DVD_RAM :
2016-01-16 03:54:55 +00:00
return MediaType . DVDRAM ;
2014-07-09 19:52:00 +01:00
case NeroMediaTypes . NERO_MTYP_ML :
case NeroMediaTypes . NERO_MTYP_MRW :
case NeroMediaTypes . NERO_MTYP_CDRW :
2016-01-16 03:54:55 +00:00
return MediaType . CDRW ;
2014-07-09 19:52:00 +01:00
case NeroMediaTypes . NERO_MTYP_CDR :
2016-01-16 03:54:55 +00:00
return MediaType . CDR ;
2014-07-09 19:52:00 +01:00
case NeroMediaTypes . NERO_MTYP_DVD_ROM :
2016-08-08 18:44:08 +01:00
case NeroMediaTypes . NERO_MTYP_DVD_ANY :
case NeroMediaTypes . NERO_MTYP_DVD_ANY_R9 :
case NeroMediaTypes . NERO_MTYP_DVD_ANY_OLD :
2016-01-16 03:54:55 +00:00
return MediaType . DVDROM ;
2014-07-09 19:52:00 +01:00
case NeroMediaTypes . NERO_MTYP_CDROM :
2016-01-16 03:54:55 +00:00
return MediaType . CDROM ;
2014-07-09 19:52:00 +01:00
case NeroMediaTypes . NERO_MTYP_DVD_M_RW :
2016-01-16 03:54:55 +00:00
return MediaType . DVDRW ;
2014-07-09 19:52:00 +01:00
case NeroMediaTypes . NERO_MTYP_DVD_P_RW :
2016-01-16 03:54:55 +00:00
return MediaType . DVDPRW ;
2014-07-09 19:52:00 +01:00
case NeroMediaTypes . NERO_MTYP_DVD_P_R9 :
2016-01-16 03:54:55 +00:00
return MediaType . DVDPRDL ;
2014-07-09 19:52:00 +01:00
case NeroMediaTypes . NERO_MTYP_DVD_M_R9 :
2016-01-16 03:54:55 +00:00
return MediaType . DVDRDL ;
2014-07-09 19:52:00 +01:00
case NeroMediaTypes . NERO_MTYP_BD :
case NeroMediaTypes . NERO_MTYP_BD_ANY :
case NeroMediaTypes . NERO_MTYP_BD_ROM :
2016-01-16 03:54:55 +00:00
return MediaType . BDROM ;
2014-07-09 19:52:00 +01:00
case NeroMediaTypes . NERO_MTYP_BD_R :
2016-01-16 03:54:55 +00:00
return MediaType . BDR ;
2014-07-09 19:52:00 +01:00
case NeroMediaTypes . NERO_MTYP_BD_RE :
2016-01-16 03:54:55 +00:00
return MediaType . BDRE ;
2014-07-09 19:52:00 +01:00
case NeroMediaTypes . NERO_MTYP_HD_DVD :
case NeroMediaTypes . NERO_MTYP_HD_DVD_ANY :
case NeroMediaTypes . NERO_MTYP_HD_DVD_ROM :
2016-01-16 03:54:55 +00:00
return MediaType . HDDVDROM ;
2014-07-09 19:52:00 +01:00
case NeroMediaTypes . NERO_MTYP_HD_DVD_R :
2016-01-16 03:54:55 +00:00
return MediaType . HDDVDR ;
2014-07-09 19:52:00 +01:00
case NeroMediaTypes . NERO_MTYP_HD_DVD_RW :
2016-01-16 03:54:55 +00:00
return MediaType . HDDVDRW ;
2014-07-09 19:52:00 +01:00
default :
2016-01-16 03:54:55 +00:00
return MediaType . CD ;
2014-07-09 19:52:00 +01:00
}
}
static TrackType NeroTrackModeToTrackType ( DAOMode mode )
{
2016-04-19 02:11:47 +01:00
switch ( mode )
2014-07-09 19:52:00 +01:00
{
case DAOMode . Data :
case DAOMode . DataRaw :
case DAOMode . DataRawSub :
return TrackType . CDMode1 ;
case DAOMode . DataM2F1 :
return TrackType . CDMode2Form1 ;
case DAOMode . DataM2F2 :
return TrackType . CDMode2Form2 ;
case DAOMode . DataM2RawSub :
case DAOMode . DataM2Raw :
return TrackType . CDMode2Formless ;
case DAOMode . Audio :
case DAOMode . AudioSub :
return TrackType . Audio ;
default :
return TrackType . Data ;
}
}
2016-07-28 22:25:26 +01:00
static ushort NeroTrackModeToBytesPerSector ( DAOMode mode )
2014-07-09 19:52:00 +01:00
{
2016-04-19 02:11:47 +01:00
switch ( mode )
2014-07-09 19:52:00 +01:00
{
case DAOMode . Data :
case DAOMode . DataM2F1 :
return 2048 ;
case DAOMode . DataM2F2 :
return 2336 ;
case DAOMode . DataRaw :
case DAOMode . DataM2Raw :
case DAOMode . Audio :
return 2352 ;
case DAOMode . DataM2RawSub :
case DAOMode . DataRawSub :
case DAOMode . AudioSub :
return 2448 ;
default :
return 2352 ;
}
}
#endregion
#region Unsupported features
2016-01-16 03:54:55 +00:00
public override int GetMediaSequence ( )
2014-07-09 19:52:00 +01:00
{
2016-08-08 18:44:08 +01:00
return ImageInfo . mediaSequence ;
2014-07-09 19:52:00 +01:00
}
public override int GetLastDiskSequence ( )
{
2016-08-08 18:44:08 +01:00
return ImageInfo . lastMediaSequence ;
2014-07-09 19:52:00 +01:00
}
public override string GetDriveManufacturer ( )
{
2016-08-08 18:44:08 +01:00
return ImageInfo . driveManufacturer ;
2014-07-09 19:52:00 +01:00
}
public override string GetDriveModel ( )
{
2016-08-08 18:44:08 +01:00
return ImageInfo . driveModel ;
2014-07-09 19:52:00 +01:00
}
public override string GetDriveSerialNumber ( )
{
2016-08-08 18:44:08 +01:00
return ImageInfo . driveSerialNumber ;
2014-07-09 19:52:00 +01:00
}
2016-01-16 03:54:55 +00:00
public override string GetMediaPartNumber ( )
2014-07-09 19:52:00 +01:00
{
2016-08-08 18:44:08 +01:00
return ImageInfo . mediaPartNumber ;
2014-07-09 19:52:00 +01:00
}
2016-01-16 03:54:55 +00:00
public override string GetMediaManufacturer ( )
2014-07-09 19:52:00 +01:00
{
2016-08-08 18:44:08 +01:00
return ImageInfo . mediaManufacturer ;
2014-07-09 19:52:00 +01:00
}
2016-01-16 03:54:55 +00:00
public override string GetMediaModel ( )
2014-07-09 19:52:00 +01:00
{
2016-08-08 18:44:08 +01:00
return ImageInfo . mediaModel ;
2014-07-09 19:52:00 +01:00
}
public override string GetImageName ( )
{
2016-08-08 18:44:08 +01:00
return ImageInfo . imageName ;
2014-07-09 19:52:00 +01:00
}
public override string GetImageCreator ( )
{
2016-08-08 18:44:08 +01:00
return ImageInfo . imageCreator ;
2014-07-09 19:52:00 +01:00
}
public override string GetImageComments ( )
{
2016-08-08 18:44:08 +01:00
return ImageInfo . imageComments ;
2014-07-09 19:52:00 +01:00
}
2016-01-16 03:54:55 +00:00
public override string GetMediaSerialNumber ( )
2014-07-09 19:52:00 +01:00
{
2016-08-08 18:44:08 +01:00
return ImageInfo . mediaSerialNumber ;
2014-07-09 19:52:00 +01:00
}
#endregion
}
}