2018-07-23 23:25:43 +01:00
// /***************************************************************************
2020-02-27 12:31:25 +00:00
// Aaru Data Preservation Suite
2016-07-28 18:13:49 +01:00
// ----------------------------------------------------------------------------
//
2018-07-23 23:25:43 +01:00
// Filename : Read.cs
2016-07-28 18:13:49 +01:00
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
2017-12-19 03:50:57 +00:00
// Component : Disk image plugins.
2016-07-28 18:13:49 +01:00
//
// --[ Description ] ----------------------------------------------------------
//
2018-07-23 23:25:43 +01:00
// Reads Nero Burning ROM disc images.
2016-07-28 18:13:49 +01:00
//
// --[ 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/>.
//
// ----------------------------------------------------------------------------
2022-02-18 10:02:53 +00:00
// Copyright © 2011-2022 Natalia Portillo
2016-07-28 18:13:49 +01:00
// ****************************************************************************/
2014-07-09 19:52:00 +01:00
2022-03-07 07:36:44 +00:00
namespace Aaru.DiscImages ;
2014-07-09 19:52:00 +01:00
using System ;
using System.Collections.Generic ;
2017-12-19 19:33:46 +00:00
using System.IO ;
using System.Linq ;
2017-12-21 14:30:38 +00:00
using System.Text ;
2020-02-27 00:33:26 +00:00
using Aaru.CommonTypes ;
using Aaru.CommonTypes.Enums ;
using Aaru.CommonTypes.Interfaces ;
using Aaru.CommonTypes.Structs ;
using Aaru.Console ;
using Aaru.Decoders.CD ;
2020-07-20 15:43:52 +01:00
using Aaru.Helpers ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
public sealed partial class Nero
2014-07-09 19:52:00 +01:00
{
2022-03-06 13:29:38 +00:00
/// <inheritdoc />
public ErrorNumber Open ( IFilter imageFilter )
2014-07-09 19:52:00 +01:00
{
2022-03-06 13:29:38 +00:00
try
2014-07-09 19:52:00 +01:00
{
2022-03-06 13:29:38 +00:00
// Look for the footer
_imageStream = imageFilter . GetDataForkStream ( ) ;
var footerV1 = new FooterV1 ( ) ;
var footerV2 = new FooterV2 ( ) ;
_imageStream . Seek ( - 8 , SeekOrigin . End ) ;
2022-03-07 07:36:44 +00:00
var buffer = new byte [ 8 ] ;
2022-03-06 13:29:38 +00:00
_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 ) ;
AaruConsole . DebugWriteLine ( "Nero plugin" , "imageStream.Length = {0}" , _imageStream . Length ) ;
AaruConsole . DebugWriteLine ( "Nero plugin" , "footerV1.ChunkID = 0x{0:X8} (\"{1}\")" , footerV1 . ChunkId ,
Encoding . ASCII . GetString ( BigEndianBitConverter . GetBytes ( footerV1 . ChunkId ) ) ) ;
AaruConsole . DebugWriteLine ( "Nero plugin" , "footerV1.FirstChunkOffset = {0}" , footerV1 . FirstChunkOffset ) ;
AaruConsole . DebugWriteLine ( "Nero plugin" , "footerV2.ChunkID = 0x{0:X8} (\"{1}\")" , footerV2 . ChunkId ,
Encoding . ASCII . GetString ( BigEndianBitConverter . GetBytes ( footerV2 . ChunkId ) ) ) ;
AaruConsole . DebugWriteLine ( "Nero plugin" , "footerV2.FirstChunkOffset = {0}" , footerV2 . FirstChunkOffset ) ;
// Check footer version
if ( footerV1 . ChunkId = = NERO_FOOTER_V1 & &
footerV1 . FirstChunkOffset < ( ulong ) _imageStream . Length )
_imageNewFormat = false ;
else if ( footerV2 . ChunkId = = NERO_FOOTER_V2 & &
footerV2 . FirstChunkOffset < ( ulong ) _imageStream . Length )
_imageNewFormat = true ;
else
2017-12-24 00:12:31 +00:00
{
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWrite ( "Nero plugin" , "Nero version not recognized." ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
return ErrorNumber . NotSupported ;
}
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
// Seek to first chunk
if ( _imageNewFormat )
_imageStream . Seek ( ( long ) footerV2 . FirstChunkOffset , SeekOrigin . Begin ) ;
else
_imageStream . Seek ( footerV1 . FirstChunkOffset , SeekOrigin . Begin ) ;
2014-07-09 19:52:00 +01:00
2022-03-07 07:36:44 +00:00
var parsing = true ;
2022-03-06 13:29:38 +00:00
ushort currentSession = 1 ;
uint currentTrack = 1 ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
Tracks = new List < Track > ( ) ;
_trackIsrCs = new Dictionary < uint , byte [ ] > ( ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
_imageInfo . MediaType = CommonTypes . MediaType . CD ;
_imageInfo . Sectors = 0 ;
_imageInfo . SectorSize = 0 ;
2022-03-07 07:36:44 +00:00
var oldFormat = false ;
int currentLba = - 150 ;
var corruptedTrackMode = false ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
// Parse chunks
while ( parsing )
{
2022-03-07 07:36:44 +00:00
var chunkHeaderBuffer = new byte [ 8 ] ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
_imageStream . Read ( chunkHeaderBuffer , 0 , 8 ) ;
2022-03-07 07:36:44 +00:00
var chunkId = BigEndianBitConverter . ToUInt32 ( chunkHeaderBuffer , 0 ) ;
var chunkLength = BigEndianBitConverter . ToUInt32 ( chunkHeaderBuffer , 4 ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "ChunkID = 0x{0:X8} (\"{1}\")" , chunkId ,
Encoding . ASCII . GetString ( BigEndianBitConverter . GetBytes ( chunkId ) ) ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "ChunkLength = {0}" , chunkLength ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
switch ( chunkId )
{
case NERO_CUE_V1 :
2017-12-24 00:12:31 +00:00
{
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "Found \"CUES\" chunk, parsing {0} bytes" ,
chunkLength ) ;
var newCuesheetV1 = new CuesheetV1
2017-12-24 00:12:31 +00:00
{
2022-03-06 13:29:38 +00:00
ChunkId = chunkId ,
ChunkSize = chunkLength ,
Entries = new List < CueEntryV1 > ( )
} ;
2014-07-09 19:52:00 +01:00
2022-03-07 07:36:44 +00:00
var tmpBuffer = new byte [ 8 ] ;
2014-07-09 19:52:00 +01:00
2022-03-07 07:36:44 +00:00
for ( var i = 0 ; i < newCuesheetV1 . ChunkSize ; i + = 8 )
2022-03-06 13:29:38 +00:00
{
var entry = new CueEntryV1 ( ) ;
_imageStream . Read ( tmpBuffer , 0 , 8 ) ;
entry . Mode = tmpBuffer [ 0 ] ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
entry . TrackNumber = ( byte ) ( ( ( tmpBuffer [ 1 ] & 0xF0 ) > > 4 ) * 10 + ( tmpBuffer [ 1 ] & 0xF ) ) ;
entry . IndexNumber = ( byte ) ( ( ( tmpBuffer [ 2 ] & 0xF0 ) > > 4 ) * 10 + ( tmpBuffer [ 2 ] & 0xF ) ) ;
2022-03-06 13:29:38 +00:00
entry . Dummy = BigEndianBitConverter . ToUInt16 ( tmpBuffer , 3 ) ;
2022-03-07 07:36:44 +00:00
entry . Minute = ( byte ) ( ( ( tmpBuffer [ 5 ] & 0xF0 ) > > 4 ) * 10 + ( tmpBuffer [ 5 ] & 0xF ) ) ;
entry . Second = ( byte ) ( ( ( tmpBuffer [ 6 ] & 0xF0 ) > > 4 ) * 10 + ( tmpBuffer [ 6 ] & 0xF ) ) ;
entry . Frame = ( byte ) ( ( ( tmpBuffer [ 7 ] & 0xF0 ) > > 4 ) * 10 + ( tmpBuffer [ 7 ] & 0xF ) ) ;
2021-06-11 01:32:51 +01:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "Cuesheet entry {0}" , i / 8 + 1 ) ;
2014-07-09 19:52:00 +01:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Mode = {1:X2}" , i / 8 + 1 ,
2022-03-06 13:29:38 +00:00
entry . Mode ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].TrackNumber = {1:X2}" , i / 8 + 1 ,
entry . TrackNumber ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].IndexNumber = {1:X2}" , i / 8 + 1 ,
entry . IndexNumber ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Dummy = {1:X4}" , i / 8 + 1 ,
2022-03-06 13:29:38 +00:00
entry . Dummy ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Minute = {1:X2}" , i / 8 + 1 ,
2022-03-06 13:29:38 +00:00
entry . Minute ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Second = {1:X2}" , i / 8 + 1 ,
2022-03-06 13:29:38 +00:00
entry . Second ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Frame = {1:X2}" , i / 8 + 1 ,
2022-03-06 13:29:38 +00:00
entry . Frame ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
newCuesheetV1 . Entries . Add ( entry ) ;
}
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
if ( _cuesheetV1 is null )
_cuesheetV1 = newCuesheetV1 ;
else
_cuesheetV1 . Entries . AddRange ( newCuesheetV1 . Entries ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2020-06-21 01:30:30 +01:00
2022-03-06 13:29:38 +00:00
case NERO_CUE_V2 :
{
AaruConsole . DebugWriteLine ( "Nero plugin" , "Found \"CUEX\" chunk, parsing {0} bytes" ,
chunkLength ) ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
var newCuesheetV2 = new CuesheetV2
2017-12-24 00:12:31 +00:00
{
2022-03-06 13:29:38 +00:00
ChunkId = chunkId ,
ChunkSize = chunkLength ,
Entries = new List < CueEntryV2 > ( )
} ;
2014-07-09 19:52:00 +01:00
2022-03-07 07:36:44 +00:00
var tmpBuffer = new byte [ 8 ] ;
2014-07-09 19:52:00 +01:00
2022-03-07 07:36:44 +00:00
for ( var i = 0 ; i < newCuesheetV2 . ChunkSize ; i + = 8 )
2022-03-06 13:29:38 +00:00
{
var entry = new CueEntryV2 ( ) ;
_imageStream . Read ( tmpBuffer , 0 , 8 ) ;
entry . Mode = tmpBuffer [ 0 ] ;
2022-03-07 07:36:44 +00:00
entry . TrackNumber = ( byte ) ( ( ( tmpBuffer [ 1 ] & 0xF0 ) > > 4 ) * 10 + ( tmpBuffer [ 1 ] & 0xF ) ) ;
entry . IndexNumber = ( byte ) ( ( ( tmpBuffer [ 2 ] & 0xF0 ) > > 4 ) * 10 + ( tmpBuffer [ 2 ] & 0xF ) ) ;
2022-03-06 13:29:38 +00:00
entry . Dummy = tmpBuffer [ 3 ] ;
entry . LbaStart = BigEndianBitConverter . ToInt32 ( tmpBuffer , 4 ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "Cuesheet entry {0}" , i / 8 + 1 ) ;
2014-07-09 19:52:00 +01:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Mode = 0x{1:X2}" , i / 8 + 1 ,
2022-03-06 13:29:38 +00:00
entry . Mode ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].TrackNumber = {1:X2}" , i / 8 + 1 ,
entry . TrackNumber ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].IndexNumber = {1:X2}" , i / 8 + 1 ,
entry . IndexNumber ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Dummy = {1:X2}" , i / 8 + 1 ,
2022-03-06 13:29:38 +00:00
entry . Dummy ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].LBAStart = {1}" , i / 8 + 1 ,
2022-03-06 13:29:38 +00:00
entry . LbaStart ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
newCuesheetV2 . Entries . Add ( entry ) ;
}
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
if ( _cuesheetV2 is null )
_cuesheetV2 = newCuesheetV2 ;
else
_cuesheetV2 . Entries . AddRange ( newCuesheetV2 . Entries ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2020-06-21 01:30:30 +01:00
2022-03-06 13:29:38 +00:00
case NERO_DAO_V1 :
{
AaruConsole . DebugWriteLine ( "Nero plugin" , "Found \"DAOI\" chunk, parsing {0} bytes" ,
chunkLength ) ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
_neroDaov1 = new DaoV1
2017-12-24 00:12:31 +00:00
{
2022-03-06 13:29:38 +00:00
ChunkId = chunkId ,
ChunkSizeBe = chunkLength
} ;
2014-07-09 19:52:00 +01:00
2022-03-07 07:36:44 +00:00
var tmpBuffer = new byte [ 22 ] ;
2022-03-06 13:29:38 +00:00
_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 < DaoEntryV1 > ( ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "neroDAOV1.ChunkSizeLe = {0} bytes" ,
_neroDaov1 . ChunkSizeLe ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "neroDAOV1.UPC = \"{0}\"" ,
StringHandlers . CToString ( _neroDaov1 . Upc ) ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "neroDAOV1.TocType = 0x{0:X4}" , _neroDaov1 . TocType ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "neroDAOV1.FirstTrack = {0}" , _neroDaov1 . FirstTrack ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "neroDAOV1.LastTrack = {0}" , _neroDaov1 . LastTrack ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
_upc = _neroDaov1 . Upc ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
tmpBuffer = new byte [ 30 ] ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
for ( var i = 0 ; i < _neroDaov1 . ChunkSizeBe - 22 ; i + = 30 )
2022-03-06 13:29:38 +00:00
{
var entry = new DaoEntryV1 ( ) ;
_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 ) ;
// MagicISO
if ( entry . SectorSize = = 2352 )
2022-11-13 19:38:03 +00:00
switch ( entry . Mode )
2022-03-06 13:29:38 +00:00
{
2022-11-13 19:38:03 +00:00
case 0x0000 :
corruptedTrackMode = true ;
entry . Mode = 0x0005 ;
break ;
case 0x0002 or 0x0003 :
corruptedTrackMode = true ;
entry . Mode = 0x0006 ;
break ;
2022-03-06 13:29:38 +00:00
}
2021-07-10 03:33:15 +01:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "Disc-At-Once entry {0}" , i / 32 + 1 ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].ISRC = \"{1}\"" , i / 32 + 1 ,
2022-03-06 13:29:38 +00:00
StringHandlers . CToString ( entry . Isrc ) ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].SectorSize = {1}" , i / 32 + 1 ,
entry . SectorSize ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Mode = {1} (0x{2:X4})" ,
2022-03-07 07:36:44 +00:00
i / 32 + 1 , ( DaoMode ) entry . Mode , entry . Mode ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Unknown = 0x{1:X4}" , i / 32 + 1 ,
entry . Unknown ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Index0 = {1}" , i / 32 + 1 ,
2022-03-06 13:29:38 +00:00
entry . Index0 ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Index1 = {1}" , i / 32 + 1 ,
2022-03-06 13:29:38 +00:00
entry . Index1 ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].EndOfTrack = {1}" , i / 32 + 1 ,
entry . EndOfTrack ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
_neroDaov1 . Tracks . Add ( entry ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
if ( entry . SectorSize > _imageInfo . SectorSize )
_imageInfo . SectorSize = entry . SectorSize ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
_trackIsrCs . Add ( currentTrack , entry . Isrc ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
var neroTrack = new NeroTrack
{
EndOfTrack = entry . EndOfTrack ,
Isrc = entry . Isrc ,
Length = entry . EndOfTrack - entry . Index0 ,
Mode = entry . Mode ,
Offset = entry . Index0 ,
SectorSize = entry . SectorSize ,
Index0 = entry . Index0 ,
Index1 = entry . Index1 ,
Sequence = currentTrack
} ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
_neroTracks . Add ( currentTrack , neroTrack ) ;
currentTrack + + ;
2017-12-24 00:12:31 +00:00
}
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
case NERO_DAO_V2 :
{
AaruConsole . DebugWriteLine ( "Nero plugin" , "Found \"DAOX\" chunk, parsing {0} bytes" ,
chunkLength ) ;
_neroDaov2 = new DaoV2
{
ChunkId = chunkId ,
ChunkSizeBe = chunkLength
} ;
2014-07-09 19:52:00 +01:00
2022-03-07 07:36:44 +00:00
var tmpBuffer = new byte [ 22 ] ;
2022-03-06 13:29:38 +00:00
_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 ) ;
_neroDaov2 . FirstTrack = tmpBuffer [ 20 ] ;
_neroDaov2 . LastTrack = tmpBuffer [ 21 ] ;
_neroDaov2 . Tracks = new List < DaoEntryV2 > ( ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
_upc = _neroDaov2 . Upc ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "neroDAOV2.ChunkSizeLe = {0} bytes" ,
_neroDaov2 . ChunkSizeLe ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "neroDAOV2.UPC = \"{0}\"" ,
StringHandlers . CToString ( _neroDaov2 . Upc ) ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "neroDAOV2.TocType = 0x{0:X4}" , _neroDaov2 . TocType ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "neroDAOV2.FirstTrack = {0}" , _neroDaov2 . FirstTrack ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "neroDAOV2.LastTrack = {0}" , _neroDaov2 . LastTrack ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
tmpBuffer = new byte [ 42 ] ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
for ( var i = 0 ; i < _neroDaov2 . ChunkSizeBe - 22 ; i + = 42 )
2022-03-06 13:29:38 +00:00
{
var entry = new DaoEntryV2 ( ) ;
_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 ) ;
// MagicISO
if ( entry . SectorSize = = 2352 )
2022-11-13 19:38:03 +00:00
switch ( entry . Mode )
2021-07-10 03:33:15 +01:00
{
2022-11-13 19:38:03 +00:00
case 0x0000 :
corruptedTrackMode = true ;
entry . Mode = 0x0005 ;
break ;
case 0x0002 or 0x0003 :
corruptedTrackMode = true ;
entry . Mode = 0x0006 ;
break ;
2021-07-10 03:33:15 +01:00
}
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "Disc-At-Once entry {0}" , i / 32 + 1 ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].ISRC = \"{1}\"" , i / 32 + 1 ,
2022-03-06 13:29:38 +00:00
StringHandlers . CToString ( entry . Isrc ) ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].SectorSize = {1}" , i / 32 + 1 ,
entry . SectorSize ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Mode = {1} (0x{2:X4})" ,
2022-03-07 07:36:44 +00:00
i / 32 + 1 , ( DaoMode ) entry . Mode , entry . Mode ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Unknown = {1:X2}" , i / 32 + 1 ,
entry . Unknown ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Index0 = {1}" , i / 32 + 1 ,
2022-03-06 13:29:38 +00:00
entry . Index0 ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Index1 = {1}" , i / 32 + 1 ,
2022-03-06 13:29:38 +00:00
entry . Index1 ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].EndOfTrack = {1}" , i / 32 + 1 ,
entry . EndOfTrack ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
_neroDaov2 . Tracks . Add ( entry ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
if ( entry . SectorSize > _imageInfo . SectorSize )
_imageInfo . SectorSize = entry . SectorSize ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
_trackIsrCs . Add ( currentTrack , entry . Isrc ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
var neroTrack = new NeroTrack
{
EndOfTrack = entry . EndOfTrack ,
Isrc = entry . Isrc ,
Length = entry . EndOfTrack - entry . Index0 ,
Mode = entry . Mode ,
Offset = entry . Index0 ,
SectorSize = entry . SectorSize ,
Index0 = entry . Index0 ,
Index1 = entry . Index1 ,
Sequence = currentTrack
} ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
_neroTracks . Add ( currentTrack , neroTrack ) ;
currentTrack + + ;
2017-12-24 00:12:31 +00:00
}
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
case NERO_CDTEXT :
{
AaruConsole . DebugWriteLine ( "Nero plugin" , "Found \"CDTX\" chunk, parsing {0} bytes" ,
chunkLength ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
_cdtxt = new CdText
{
ChunkId = chunkId ,
ChunkSize = chunkLength ,
Packs = new List < CdTextPack > ( )
} ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
var tmpBuffer = new byte [ 18 ] ;
2014-07-09 19:52:00 +01:00
2022-03-07 07:36:44 +00:00
for ( var i = 0 ; i < _cdtxt . ChunkSize ; i + = 18 )
2022-03-06 13:29:38 +00:00
{
var entry = new CdTextPack ( ) ;
_imageStream . Read ( tmpBuffer , 0 , 18 ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
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 ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "CD-TEXT entry {0}" , i / 18 + 1 ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].PackType = 0x{1:X2}" , i / 18 + 1 ,
entry . PackType ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].TrackNumber = 0x{1:X2}" ,
2022-03-07 07:36:44 +00:00
i / 18 + 1 , entry . TrackNumber ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].PackNumber = 0x{1:X2}" ,
2022-03-07 07:36:44 +00:00
i / 18 + 1 , entry . PackNumber ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].BlockNumber = 0x{1:X2}" ,
2022-03-07 07:36:44 +00:00
i / 18 + 1 , entry . BlockNumber ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Text = \"{1}\"" , i / 18 + 1 ,
2022-03-06 13:29:38 +00:00
StringHandlers . CToString ( entry . Text ) ) ;
2014-07-09 19:52:00 +01:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].CRC = 0x{1:X4}" , i / 18 + 1 ,
2022-03-06 13:29:38 +00:00
entry . Crc ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
_cdtxt . Packs . Add ( entry ) ;
2017-12-24 00:12:31 +00:00
}
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2021-06-11 12:26:54 +01:00
2022-03-06 13:29:38 +00:00
case NERO_TAO_V0 :
{
AaruConsole . DebugWriteLine ( "Nero plugin" , "Found \"TINF\" chunk, parsing {0} bytes" ,
chunkLength ) ;
2021-06-11 12:26:54 +01:00
2022-03-06 13:29:38 +00:00
oldFormat = true ;
2021-06-11 12:26:54 +01:00
2022-03-06 13:29:38 +00:00
_taoV0 = new TaoV0
{
ChunkId = chunkId ,
ChunkSize = chunkLength ,
Tracks = new List < TaoEntryV0 > ( )
} ;
2021-06-11 12:26:54 +01:00
2022-03-07 07:36:44 +00:00
var tmpBuffer = new byte [ 12 ] ;
2021-06-11 12:26:54 +01:00
2022-03-07 07:36:44 +00:00
for ( var i = 0 ; i < _taoV0 . ChunkSize ; i + = 12 )
2022-03-06 13:29:38 +00:00
{
var entry = new TaoEntryV0 ( ) ;
_imageStream . Read ( tmpBuffer , 0 , 12 ) ;
2021-06-11 12:26:54 +01:00
2022-03-06 13:29:38 +00:00
entry . Offset = BigEndianBitConverter . ToUInt32 ( tmpBuffer , 0 ) ;
entry . Length = BigEndianBitConverter . ToUInt32 ( tmpBuffer , 4 ) ;
entry . Mode = BigEndianBitConverter . ToUInt32 ( tmpBuffer , 8 ) ;
2021-06-11 12:26:54 +01:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "Track-at-Once entry {0}" , i / 20 + 1 ) ;
2021-06-11 12:26:54 +01:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Offset = {1}" , i / 20 + 1 ,
2022-03-06 13:29:38 +00:00
entry . Offset ) ;
2021-06-11 12:26:54 +01:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Length = {1} bytes" , i / 20 + 1 ,
entry . Length ) ;
2021-06-11 12:26:54 +01:00
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Mode = {1} (0x{2:X4})" ,
2022-03-07 07:36:44 +00:00
i / 20 + 1 , ( DaoMode ) entry . Mode , entry . Mode ) ;
2021-06-11 12:26:54 +01:00
2022-03-06 13:29:38 +00:00
_taoV0 . Tracks . Add ( entry ) ;
2021-06-11 12:26:54 +01:00
2022-03-06 13:29:38 +00:00
if ( NeroTrackModeToBytesPerSector ( ( DaoMode ) entry . Mode ) > _imageInfo . SectorSize )
_imageInfo . SectorSize = NeroTrackModeToBytesPerSector ( ( DaoMode ) entry . Mode ) ;
2021-06-11 12:26:54 +01:00
2022-03-06 13:29:38 +00:00
// StartLba points to INDEX 0 and Nero always introduces a pregap of 150 sectors,
2021-06-11 12:26:54 +01:00
2022-03-06 13:29:38 +00:00
var neroTrack = new NeroTrack
{
EndOfTrack = entry . Offset + entry . Length ,
Isrc = new byte [ 12 ] ,
Length = entry . Length ,
Mode = entry . Mode ,
Offset = entry . Offset ,
SectorSize = NeroTrackModeToBytesPerSector ( ( DaoMode ) entry . Mode ) ,
UseLbaForIndex = true ,
Sequence = currentTrack ,
StartLba = currentLba > 0 ? ( ulong ) currentLba : 0
} ;
_neroTracks . Add ( currentTrack , neroTrack ) ;
currentTrack + + ;
currentLba + = ( int ) ( neroTrack . Length / neroTrack . SectorSize ) ;
2021-06-11 12:26:54 +01:00
}
2022-03-06 13:29:38 +00:00
break ;
}
case NERO_TAO_V1 :
{
AaruConsole . DebugWriteLine ( "Nero plugin" , "Found \"ETNF\" chunk, parsing {0} bytes" ,
chunkLength ) ;
_taoV1 = new TaoV1
2017-12-24 00:12:31 +00:00
{
2022-03-06 13:29:38 +00:00
ChunkId = chunkId ,
ChunkSize = chunkLength ,
Tracks = new List < TaoEntryV1 > ( )
} ;
2014-07-09 19:52:00 +01:00
2022-03-07 07:36:44 +00:00
var tmpBuffer = new byte [ 20 ] ;
2014-07-09 19:52:00 +01:00
2022-03-07 07:36:44 +00:00
for ( var i = 0 ; i < _taoV1 . ChunkSize ; i + = 20 )
2022-03-06 13:29:38 +00:00
{
var entry = new TaoEntryV1 ( ) ;
_imageStream . Read ( tmpBuffer , 0 , 20 ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
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 ) ;
2014-07-09 19:52:00 +01:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "Track-at-Once entry {0}" , i / 20 + 1 ) ;
2014-07-09 19:52:00 +01:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Offset = {1}" , i / 20 + 1 ,
2022-03-06 13:29:38 +00:00
entry . Offset ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Length = {1} bytes" , i / 20 + 1 ,
entry . Length ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Mode = {1} (0x{2:X4})" ,
2022-03-07 07:36:44 +00:00
i / 20 + 1 , ( DaoMode ) entry . Mode , entry . Mode ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].StartLBA = {1}" , i / 20 + 1 ,
2022-03-06 13:29:38 +00:00
entry . StartLba ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Unknown = 0x{1:X4}" , i / 20 + 1 ,
entry . Unknown ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
_taoV1 . Tracks . Add ( entry ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
if ( NeroTrackModeToBytesPerSector ( ( DaoMode ) entry . Mode ) > _imageInfo . SectorSize )
_imageInfo . SectorSize = NeroTrackModeToBytesPerSector ( ( DaoMode ) entry . Mode ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
// StartLba points to INDEX 0 and Nero always introduces a pregap of 150 sectors,
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
var neroTrack = new NeroTrack
{
EndOfTrack = entry . Offset + entry . Length ,
Isrc = new byte [ 12 ] ,
Length = entry . Length ,
Mode = entry . Mode ,
Offset = entry . Offset ,
SectorSize = NeroTrackModeToBytesPerSector ( ( DaoMode ) entry . Mode ) ,
UseLbaForIndex = true ,
Sequence = currentTrack ,
StartLba = entry . StartLba
} ;
2021-06-11 01:32:51 +01:00
2022-03-06 13:29:38 +00:00
_neroTracks . Add ( currentTrack , neroTrack ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
currentTrack + + ;
2017-12-24 00:12:31 +00:00
}
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
case NERO_TAO_V2 :
{
AaruConsole . DebugWriteLine ( "Nero plugin" , "Found \"ETN2\" chunk, parsing {0} bytes" ,
chunkLength ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
_taoV2 = new TaoV2
{
ChunkId = chunkId ,
ChunkSize = chunkLength ,
Tracks = new List < TaoEntryV2 > ( )
} ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
var tmpBuffer = new byte [ 32 ] ;
2014-07-09 19:52:00 +01:00
2022-03-07 07:36:44 +00:00
for ( var i = 0 ; i < _taoV2 . ChunkSize ; i + = 32 )
2022-03-06 13:29:38 +00:00
{
var entry = new TaoEntryV2 ( ) ;
_imageStream . Read ( tmpBuffer , 0 , 32 ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
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 ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "Track-at-Once entry {0}" , i / 32 + 1 ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Offset = {1}" , i / 32 + 1 ,
2022-03-06 13:29:38 +00:00
entry . Offset ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Length = {1} bytes" , i / 32 + 1 ,
entry . Length ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Mode = {1} (0x{2:X4})" ,
2022-03-07 07:36:44 +00:00
i / 32 + 1 , ( DaoMode ) entry . Mode , entry . Mode ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].StartLBA = {1}" , i / 32 + 1 ,
2022-03-06 13:29:38 +00:00
entry . StartLba ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Unknown = 0x{1:X4}" , i / 32 + 1 ,
entry . Unknown ) ;
2014-07-09 19:52:00 +01:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t _entry[{0}].Sectors = {1}" , i / 32 + 1 ,
2022-03-06 13:29:38 +00:00
entry . Sectors ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
_taoV2 . Tracks . Add ( entry ) ;
2021-06-11 01:32:51 +01:00
2022-03-06 13:29:38 +00:00
ushort v2Bps = NeroTrackModeToBytesPerSector ( ( DaoMode ) entry . Mode ) ;
2021-06-11 01:32:51 +01:00
2022-03-06 13:29:38 +00:00
if ( NeroTrackModeToBytesPerSector ( ( DaoMode ) entry . Mode ) > _imageInfo . SectorSize )
_imageInfo . SectorSize = v2Bps ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
// StartLba points to INDEX 1 and Nero always introduces a pregap of 150 sectors,
// so let's move it to INDEX 0 and fix the pointers
if ( entry . StartLba > = 150 )
{
entry . StartLba - = 150 ;
entry . Offset - = ( ulong ) ( 150 * v2Bps ) ;
entry . Length + = ( ulong ) ( 150 * v2Bps ) ;
2017-12-24 00:12:31 +00:00
}
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
var neroTrack = new NeroTrack
{
EndOfTrack = entry . Offset + entry . Length ,
Isrc = new byte [ 12 ] ,
Length = entry . Length ,
Mode = entry . Mode ,
Offset = entry . Offset ,
StartLba = entry . StartLba ,
UseLbaForIndex = true ,
SectorSize = NeroTrackModeToBytesPerSector ( ( DaoMode ) entry . Mode ) ,
Sequence = currentTrack
} ;
_neroTracks . Add ( currentTrack , neroTrack ) ;
currentTrack + + ;
2017-12-24 00:12:31 +00:00
}
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
case NERO_SESSION :
{
AaruConsole . DebugWriteLine ( "Nero plugin" , "Found \"SINF\" chunk, parsing {0} bytes" ,
chunkLength ) ;
2014-07-09 19:52:00 +01:00
2022-03-07 07:36:44 +00:00
var tmpBuffer = new byte [ 4 ] ;
2022-03-06 13:29:38 +00:00
_imageStream . Read ( tmpBuffer , 0 , 4 ) ;
2022-03-07 07:36:44 +00:00
var sessionTracks = BigEndianBitConverter . ToUInt32 ( tmpBuffer , 0 ) ;
2022-03-06 13:29:38 +00:00
_neroSessions . Add ( currentSession , sessionTracks ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\tSession {0} has {1} tracks" , currentSession ,
sessionTracks ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
currentSession + + ;
break ;
}
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
case NERO_DISC_TYPE :
{
AaruConsole . DebugWriteLine ( "Nero plugin" , "Found \"MTYP\" chunk, parsing {0} bytes" ,
chunkLength ) ;
_mediaType = new MediaType
2017-12-24 00:12:31 +00:00
{
2022-03-06 13:29:38 +00:00
ChunkId = chunkId ,
ChunkSize = chunkLength
} ;
2014-07-09 19:52:00 +01:00
2022-03-07 07:36:44 +00:00
var tmpBuffer = new byte [ 4 ] ;
2022-03-06 13:29:38 +00:00
_imageStream . Read ( tmpBuffer , 0 , 4 ) ;
_mediaType . Type = BigEndianBitConverter . ToUInt32 ( tmpBuffer , 0 ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\tMedia type is {0} ({1})" ,
( NeroMediaTypes ) _mediaType . Type , _mediaType . Type ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
_imageInfo . MediaType = NeroMediaTypeToMediaType ( ( NeroMediaTypes ) _mediaType . Type ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
case NERO_DISC_INFO :
{
AaruConsole . DebugWriteLine ( "Nero plugin" , "Found \"DINF\" chunk, parsing {0} bytes" ,
chunkLength ) ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
_discInfo = new DiscInformation
2017-12-24 00:12:31 +00:00
{
2022-03-06 13:29:38 +00:00
ChunkId = chunkId ,
ChunkSize = chunkLength
} ;
2014-07-09 19:52:00 +01:00
2022-03-07 07:36:44 +00:00
var tmpBuffer = new byte [ 4 ] ;
2022-03-06 13:29:38 +00:00
_imageStream . Read ( tmpBuffer , 0 , 4 ) ;
_discInfo . Unknown = BigEndianBitConverter . ToUInt32 ( tmpBuffer , 0 ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\tneroDiscInfo.Unknown = 0x{0:X4} ({0})" ,
_discInfo . Unknown ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
case NERO_RELOCATION :
{
AaruConsole . DebugWriteLine ( "Nero plugin" , "Found \"RELO\" chunk, parsing {0} bytes" ,
chunkLength ) ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
_relo = new ReloChunk
2017-12-24 00:12:31 +00:00
{
2022-03-06 13:29:38 +00:00
ChunkId = chunkId ,
ChunkSize = chunkLength
} ;
2014-07-09 19:52:00 +01:00
2022-03-07 07:36:44 +00:00
var tmpBuffer = new byte [ 4 ] ;
2022-03-06 13:29:38 +00:00
_imageStream . Read ( tmpBuffer , 0 , 4 ) ;
_relo . Unknown = BigEndianBitConverter . ToUInt32 ( tmpBuffer , 0 ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\tneroRELO.Unknown = 0x{0:X4} ({0})" , _relo . Unknown ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
case NERO_TOC :
{
AaruConsole . DebugWriteLine ( "Nero plugin" , "Found \"TOCT\" chunk, parsing {0} bytes" ,
chunkLength ) ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
_toc = new TocChunk
2017-12-24 00:12:31 +00:00
{
2022-03-06 13:29:38 +00:00
ChunkId = chunkId ,
ChunkSize = chunkLength
} ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
var tmpBuffer = new byte [ 2 ] ;
2022-03-06 13:29:38 +00:00
_imageStream . Read ( tmpBuffer , 0 , 2 ) ;
_toc . Unknown = BigEndianBitConverter . ToUInt16 ( tmpBuffer , 0 ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
switch ( tmpBuffer [ 0 ] )
{
case 0 :
_imageInfo . MediaType = CommonTypes . MediaType . CDROM ;
2021-06-11 12:26:54 +01:00
2022-03-06 13:29:38 +00:00
break ;
case 0x10 :
_imageInfo . MediaType = CommonTypes . MediaType . CDI ;
2021-06-11 12:26:54 +01:00
2022-03-06 13:29:38 +00:00
break ;
case 0x20 :
_imageInfo . MediaType = CommonTypes . MediaType . CDROMXA ;
2021-06-11 12:26:54 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2021-06-11 12:26:54 +01:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\tneroTOC.Unknown = 0x{0:X4} ({0})" , _toc . Unknown ) ;
2017-12-24 00:12:31 +00:00
2022-03-06 13:29:38 +00:00
break ;
}
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
case NERO_END :
{
AaruConsole . DebugWriteLine ( "Nero plugin" , "Found \"END!\" chunk, finishing parse" ) ;
parsing = false ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
break ;
}
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
default :
{
AaruConsole . DebugWriteLine ( "Nero plugin" , "Unknown chunk ID \"{0}\", skipping..." ,
2022-03-07 07:36:44 +00:00
Encoding . ASCII . GetString ( BigEndianBitConverter . GetBytes ( chunkId ) ) ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
_imageStream . Seek ( chunkLength , SeekOrigin . Current ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
break ;
2017-12-24 00:12:31 +00:00
}
}
2022-03-06 13:29:38 +00:00
}
2017-12-24 00:12:31 +00:00
2022-03-06 13:29:38 +00:00
if ( corruptedTrackMode )
AaruConsole .
ErrorWriteLine ( "Inconsistent track mode and track sector size found. A best try to fix has been done. It is recommended this disc is dumped with another software." ) ;
_imageInfo . HasPartitions = true ;
_imageInfo . HasSessions = true ;
_imageInfo . Creator = null ;
_imageInfo . CreationTime = imageFilter . CreationTime ;
_imageInfo . LastModificationTime = imageFilter . LastWriteTime ;
_imageInfo . MediaTitle = Path . GetFileNameWithoutExtension ( imageFilter . Filename ) ;
_imageInfo . Comments = null ;
_imageInfo . MediaManufacturer = null ;
_imageInfo . MediaModel = null ;
_imageInfo . MediaSerialNumber = null ;
_imageInfo . MediaBarcode = null ;
_imageInfo . MediaPartNumber = null ;
_imageInfo . DriveManufacturer = null ;
_imageInfo . DriveModel = null ;
_imageInfo . DriveSerialNumber = null ;
_imageInfo . DriveFirmwareRevision = null ;
_imageInfo . MediaSequence = 0 ;
_imageInfo . LastMediaSequence = 0 ;
_imageInfo . Application = "Nero Burning ROM" ;
if ( _imageNewFormat )
{
_imageInfo . ImageSize = footerV2 . FirstChunkOffset ;
_imageInfo . Version = "Nero Burning ROM >= 5.5" ;
_imageInfo . ApplicationVersion = ">= 5.5" ;
}
else if ( oldFormat )
{
_imageInfo . ImageSize = footerV1 . FirstChunkOffset ;
_imageInfo . Version = "Nero Burning ROM 4" ;
_imageInfo . ApplicationVersion = "4" ;
}
else
{
_imageInfo . ImageSize = footerV1 . FirstChunkOffset ;
_imageInfo . Version = "Nero Burning ROM <= 5.0" ;
_imageInfo . ApplicationVersion = "<= 5.0" ;
}
2017-12-19 20:33:03 +00:00
2022-03-06 13:29:38 +00:00
if ( _neroSessions . Count = = 0 )
_neroSessions . Add ( 1 , currentTrack ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "Building offset, track and session maps" ) ;
2014-07-09 19:52:00 +01:00
2022-03-16 11:47:00 +00:00
bool onlyOneSession = currentSession is 1 or 2 ;
2022-03-06 13:29:38 +00:00
currentSession = 1 ;
_neroSessions . TryGetValue ( 1 , out uint currentSessionMaxTrack ) ;
uint currentSessionCurrentTrack = 1 ;
var currentSessionStruct = new CommonTypes . Structs . Session ( ) ;
ulong partitionSequence = 0 ;
ulong partitionStartByte = 0 ;
2022-03-07 07:36:44 +00:00
var trackCounter = 1 ;
2022-03-06 13:29:38 +00:00
_trackFlags = new Dictionary < uint , byte > ( ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
if ( currentSessionMaxTrack = = 0 )
currentSessionMaxTrack = 1 ;
2021-07-01 12:26:07 +01:00
2022-03-06 13:29:38 +00:00
bool moreTracksThanSessionTracks = currentSessionMaxTrack < _neroTracks . Count ;
2021-07-01 12:26:07 +01:00
2022-03-06 13:29:38 +00:00
// Process tracks
foreach ( NeroTrack neroTrack in _neroTracks . Values )
{
if ( neroTrack . Offset > = ( _imageNewFormat ? footerV2 . FirstChunkOffset : footerV1 . FirstChunkOffset ) )
2014-07-09 19:52:00 +01:00
{
2022-03-07 07:36:44 +00:00
AaruConsole . ErrorWriteLine ( "This image contains a track that is set to start outside the file." ) ;
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
AaruConsole . ErrorWriteLine ( "Breaking track processing and trying recovery of information." ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
break ;
}
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\tcurrentSession = {0}" , currentSession ) ;
AaruConsole . DebugWriteLine ( "Nero plugin" , "\tcurrentSessionMaxTrack = {0}" , currentSessionMaxTrack ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\tcurrentSessionCurrentTrack = {0}" ,
currentSessionCurrentTrack ) ;
2020-06-21 01:30:30 +01:00
2022-03-06 13:29:38 +00:00
var track = new Track ( ) ;
2020-06-21 01:30:30 +01:00
2022-03-06 13:29:38 +00:00
// Process indexes
if ( _cuesheetV1 ? . Entries ? . Count > 0 )
foreach ( CueEntryV1 entry in _cuesheetV1 . Entries . Where ( e = > e . TrackNumber = = neroTrack . Sequence ) .
OrderBy ( e = > e . IndexNumber ) )
2020-06-21 01:30:30 +01:00
{
2022-03-06 13:29:38 +00:00
track . Indexes [ entry . IndexNumber ] =
2022-03-07 07:36:44 +00:00
entry . Minute * 60 * 75 + entry . Second * 75 + entry . Frame - 150 ;
2021-06-11 01:32:51 +01:00
2022-03-06 13:29:38 +00:00
_trackFlags [ entry . TrackNumber ] = ( byte ) ( ( entry . Mode & 0xF0 ) > > 4 ) ;
}
else if ( _cuesheetV2 ? . Entries ? . Count > 0 )
foreach ( CueEntryV2 entry in _cuesheetV2 . Entries . Where ( e = > e . TrackNumber = = neroTrack . Sequence ) .
OrderBy ( e = > e . IndexNumber ) )
{
track . Indexes [ entry . IndexNumber ] = entry . LbaStart ;
_trackFlags [ entry . TrackNumber ] = ( byte ) ( ( entry . Mode & 0xF0 ) > > 4 ) ;
2020-06-21 01:30:30 +01:00
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
// Act if there are no indexes
if ( track . Indexes . Count = = 0 )
{
if ( ! neroTrack . UseLbaForIndex )
continue ; // This track start is unknown, continue and pray the goddess
2020-06-21 01:30:30 +01:00
2022-03-06 13:29:38 +00:00
// This always happens in TAO discs and Nero uses 150 sectors of pregap for them
// but we need to move the offsets if it's the first track of a session
if ( currentSessionCurrentTrack = = 1 )
2021-06-11 01:32:51 +01:00
{
2022-03-06 13:29:38 +00:00
track . Indexes [ 1 ] = ( int ) neroTrack . StartLba ;
track . Indexes [ 0 ] = track . Indexes [ 1 ] - 150 ;
neroTrack . Offset - = ( ulong ) ( 150 * neroTrack . SectorSize ) ;
neroTrack . Length + = ( ulong ) ( 150 * neroTrack . SectorSize ) ;
2021-06-11 01:32:51 +01:00
}
else
{
2022-03-06 13:29:38 +00:00
track . Indexes [ 0 ] = ( int ) neroTrack . StartLba ;
track . Indexes [ 1 ] = track . Indexes [ 0 ] + 150 ;
2021-06-11 01:32:51 +01:00
}
2022-03-06 13:29:38 +00:00
}
2021-06-11 01:32:51 +01:00
2022-03-06 13:29:38 +00:00
// Prevent duplicate index 0
if ( track . Indexes . ContainsKey ( 0 ) & &
track . Indexes [ 0 ] = = track . Indexes [ 1 ] )
track . Indexes . Remove ( 0 ) ;
2021-06-11 01:32:51 +01:00
2022-03-06 13:29:38 +00:00
// There's a pregap
if ( track . Indexes . ContainsKey ( 0 ) )
{
track . Pregap = ( ulong ) ( track . Indexes [ 1 ] - track . Indexes [ 0 ] ) ;
2021-06-11 01:32:51 +01:00
2022-03-06 13:29:38 +00:00
// Negative pregap, skip it
if ( track . Indexes [ 0 ] < 0 )
2021-06-11 01:32:51 +01:00
{
2022-03-06 13:29:38 +00:00
neroTrack . Length - = track . Pregap * neroTrack . SectorSize ;
neroTrack . Offset + = track . Pregap * neroTrack . SectorSize ;
track . StartSector = ( ulong ) track . Indexes [ 1 ] ;
2021-06-11 01:32:51 +01:00
}
2022-03-06 13:29:38 +00:00
else
track . StartSector = ( ulong ) track . Indexes [ 0 ] ;
}
else
track . StartSector = ( ulong ) track . Indexes [ 1 ] ;
2021-06-11 01:32:51 +01:00
2022-03-06 13:29:38 +00:00
// Handle hidden tracks
if ( neroTrack . Sequence = = 1 & &
track . StartSector > 0 )
{
neroTrack . Length + = track . StartSector * neroTrack . SectorSize ;
neroTrack . Offset - = track . StartSector * neroTrack . SectorSize ;
track . StartSector = 0 ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
// Common track data
track . Description = StringHandlers . CToString ( neroTrack . Isrc ) ;
2022-03-07 07:36:44 +00:00
track . EndSector = neroTrack . Length / neroTrack . SectorSize + track . StartSector - 1 ;
2022-03-06 13:29:38 +00:00
track . Sequence = neroTrack . Sequence ;
track . Session = currentSession ;
track . Type = NeroTrackModeToTrackType ( ( DaoMode ) neroTrack . Mode ) ;
track . File = imageFilter . Filename ;
track . Filter = imageFilter ;
track . FileOffset = neroTrack . Offset ;
track . FileType = "BINARY" ;
track . SubchannelType = TrackSubchannelType . None ;
neroTrack . Sectors = neroTrack . Length / neroTrack . SectorSize ;
// Flags not set for this track
if ( ! _trackFlags . ContainsKey ( track . Sequence ) )
switch ( track . Type )
2014-07-09 19:52:00 +01:00
{
2022-03-06 13:29:38 +00:00
case TrackType . Audio :
_trackFlags [ track . Sequence ] = 0 ;
2020-01-11 22:44:25 +00:00
2017-12-24 00:12:31 +00:00
break ;
2022-03-06 13:29:38 +00:00
case TrackType . Data :
case TrackType . CdMode1 :
case TrackType . CdMode2Formless :
case TrackType . CdMode2Form1 :
case TrackType . CdMode2Form2 :
_trackFlags [ track . Sequence ] = 4 ;
2020-01-11 22:44:25 +00:00
2017-12-24 00:12:31 +00:00
break ;
2022-03-06 13:29:38 +00:00
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
// If ISRC is not empty
if ( ! string . IsNullOrWhiteSpace ( track . Description ) )
{
_trackIsrCs [ neroTrack . Sequence ] = neroTrack . Isrc ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
if ( ! _imageInfo . ReadableSectorTags . Contains ( SectorTagType . CdTrackIsrc ) )
_imageInfo . ReadableSectorTags . Add ( SectorTagType . CdTrackIsrc ) ;
}
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
var rawMode1 = false ;
var rawMode2 = false ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
switch ( ( DaoMode ) neroTrack . Mode )
{
case DaoMode . AudioAlt :
case DaoMode . Audio :
track . BytesPerSector = 2352 ;
track . RawBytesPerSector = 2352 ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
break ;
case DaoMode . AudioSub :
track . BytesPerSector = 2352 ;
track . RawBytesPerSector = 2352 ;
track . SubchannelType = TrackSubchannelType . RawInterleaved ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
break ;
case DaoMode . Data :
case DaoMode . DataM2F1 :
track . BytesPerSector = 2048 ;
track . RawBytesPerSector = 2048 ;
2017-12-19 20:33:03 +00:00
2022-03-06 13:29:38 +00:00
break ;
case DaoMode . DataM2F2 :
track . BytesPerSector = 2336 ;
track . RawBytesPerSector = 2336 ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
break ;
case DaoMode . DataM2Raw :
track . BytesPerSector = 2352 ;
track . RawBytesPerSector = 2352 ;
rawMode2 = true ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
break ;
case DaoMode . DataM2RawSub :
track . BytesPerSector = 2352 ;
track . RawBytesPerSector = 2352 ;
track . SubchannelType = TrackSubchannelType . RawInterleaved ;
rawMode2 = true ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
break ;
case DaoMode . DataRaw :
track . BytesPerSector = 2048 ;
track . RawBytesPerSector = 2352 ;
rawMode1 = true ;
2017-12-19 20:33:03 +00:00
2022-03-06 13:29:38 +00:00
break ;
case DaoMode . DataRawSub :
track . BytesPerSector = 2048 ;
track . RawBytesPerSector = 2352 ;
track . SubchannelType = TrackSubchannelType . RawInterleaved ;
rawMode1 = true ;
2021-06-11 01:32:51 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2021-06-11 01:32:51 +01:00
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t\t _track.Description = {0}" , track . Description ) ;
2021-06-11 01:32:51 +01:00
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t\t _track.EndSector = {0}" , track . EndSector ) ;
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t\t _track.Pregap = {0}" , track . Pregap ) ;
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t\t _track.Sequence = {0}" , track . Sequence ) ;
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t\t _track.Session = {0}" , track . Session ) ;
2021-06-11 01:32:51 +01:00
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t\t _track.StartSector = {0}" , track . StartSector ) ;
2021-06-11 01:32:51 +01:00
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t\t _track.Type = {0}" , track . Type ) ;
2021-06-11 01:32:51 +01:00
2022-03-06 13:29:38 +00:00
// Check readability of sector tags
if ( rawMode1 | | rawMode2 )
{
if ( ! _imageInfo . ReadableSectorTags . Contains ( SectorTagType . CdSectorSync ) )
_imageInfo . ReadableSectorTags . Add ( SectorTagType . CdSectorSync ) ;
2021-06-11 01:32:51 +01:00
2022-03-06 13:29:38 +00:00
if ( ! _imageInfo . ReadableSectorTags . Contains ( SectorTagType . CdSectorHeader ) )
_imageInfo . ReadableSectorTags . Add ( SectorTagType . CdSectorHeader ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
if ( ! _imageInfo . ReadableSectorTags . Contains ( SectorTagType . CdSectorSubHeader ) & & rawMode2 )
_imageInfo . ReadableSectorTags . Add ( SectorTagType . CdSectorSubHeader ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
if ( ! _imageInfo . ReadableSectorTags . Contains ( SectorTagType . CdSectorEdc ) )
_imageInfo . ReadableSectorTags . Add ( SectorTagType . CdSectorEdc ) ;
}
2017-12-19 20:33:03 +00:00
2022-03-06 13:29:38 +00:00
if ( track . SubchannelType = = TrackSubchannelType . RawInterleaved )
{
track . SubchannelFilter = imageFilter ;
track . SubchannelFile = imageFilter . Filename ;
track . SubchannelOffset = neroTrack . Offset ;
if ( ! _imageInfo . ReadableSectorTags . Contains ( SectorTagType . CdSectorSubchannel ) )
_imageInfo . ReadableSectorTags . Add ( SectorTagType . CdSectorSubchannel ) ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
Tracks . Add ( track ) ;
2017-12-19 20:33:03 +00:00
2022-03-06 13:29:38 +00:00
// Build session
if ( currentSessionCurrentTrack = = 1 )
currentSessionStruct = new CommonTypes . Structs . Session
2017-12-24 00:12:31 +00:00
{
2022-03-06 13:29:38 +00:00
Sequence = currentSession ,
StartSector = track . StartSector ,
StartTrack = track . Sequence
2017-12-24 00:12:31 +00:00
} ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
currentSessionCurrentTrack + + ;
2017-12-19 20:33:03 +00:00
2022-03-06 13:29:38 +00:00
if ( currentSessionCurrentTrack > currentSessionMaxTrack )
{
currentSession + + ;
_neroSessions . TryGetValue ( currentSession , out currentSessionMaxTrack ) ;
currentSessionCurrentTrack = 1 ;
currentSessionStruct . EndTrack = track . Sequence ;
currentSessionStruct . EndSector = track . EndSector ;
Sessions . Add ( currentSessionStruct ) ;
2020-06-21 01:30:30 +01:00
}
2022-03-06 13:29:38 +00:00
else if ( trackCounter = = _neroTracks . Count )
2021-07-01 14:51:32 +01:00
{
2022-03-06 13:29:38 +00:00
_neroSessions . TryGetValue ( currentSession , out currentSessionMaxTrack ) ;
currentSessionCurrentTrack = 1 ;
currentSessionStruct . EndTrack = track . Sequence ;
currentSessionStruct . EndSector = track . EndSector ;
Sessions . Add ( currentSessionStruct ) ;
}
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
// Add to offset map
_offsetmap . Add ( track . Sequence , track . StartSector ) ;
2021-07-01 14:51:32 +01:00
2022-03-07 07:36:44 +00:00
AaruConsole . DebugWriteLine ( "Nero plugin" , "\t\t Offset[{0}]: {1}" , track . Sequence , track . StartSector ) ;
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
// Create partition
var partition = new Partition
{
Description = $"Track {track.Sequence}" ,
Size = neroTrack . EndOfTrack - neroTrack . Index1 ,
Name = StringHandlers . CToString ( neroTrack . Isrc ) ,
Sequence = partitionSequence ,
Offset = partitionStartByte ,
Start = ( ulong ) track . Indexes [ 1 ] ,
Type = NeroTrackModeToTrackType ( ( DaoMode ) neroTrack . Mode ) . ToString ( )
} ;
partition . Length = partition . Size / neroTrack . SectorSize ;
Partitions . Add ( partition ) ;
partitionSequence + + ;
partitionStartByte + = partition . Size ;
if ( track . EndSector + 1 > _imageInfo . Sectors )
_imageInfo . Sectors = track . EndSector + 1 ;
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
trackCounter + + ;
}
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
if ( Tracks . Count = = 0 )
{
if ( _neroTracks . Count ! = 1 | |
! _neroTracks . ContainsKey ( 1 ) | |
( _imageNewFormat ? footerV2 . FirstChunkOffset : footerV1 . FirstChunkOffset ) %
_neroTracks [ 1 ] . SectorSize ! = 0 )
{
AaruConsole . ErrorWriteLine ( "Image corrupted beyond recovery, cannot open." ) ;
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
return ErrorNumber . InvalidArgument ;
}
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
var track = new Track ( ) ;
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
// Common track data
track . Description = StringHandlers . CToString ( _neroTracks [ 1 ] . Isrc ) ;
2021-07-01 14:51:32 +01:00
2022-03-07 07:36:44 +00:00
track . EndSector = ( _imageNewFormat ? footerV2 . FirstChunkOffset : footerV1 . FirstChunkOffset ) /
_neroTracks [ 1 ] . SectorSize - 150 ;
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
track . Sequence = _neroTracks [ 1 ] . Sequence ;
track . Session = currentSession ;
track . Type = NeroTrackModeToTrackType ( ( DaoMode ) _neroTracks [ 1 ] . Mode ) ;
track . File = imageFilter . Filename ;
track . Filter = imageFilter ;
track . FileType = "BINARY" ;
track . SubchannelType = TrackSubchannelType . None ;
track . Indexes [ 1 ] = 0 ;
2021-07-01 14:51:32 +01:00
2022-03-07 07:36:44 +00:00
var rawMode1 = false ;
var rawMode2 = false ;
var subSize = 0 ;
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
switch ( ( DaoMode ) _neroTracks [ 1 ] . Mode )
{
case DaoMode . AudioAlt :
case DaoMode . Audio :
track . BytesPerSector = 2352 ;
track . RawBytesPerSector = 2352 ;
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
case DaoMode . AudioSub :
track . BytesPerSector = 2352 ;
track . RawBytesPerSector = 2352 ;
track . SubchannelType = TrackSubchannelType . RawInterleaved ;
subSize = 96 ;
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
case DaoMode . Data :
case DaoMode . DataM2F1 :
track . BytesPerSector = 2048 ;
track . RawBytesPerSector = 2048 ;
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
case DaoMode . DataM2F2 :
track . BytesPerSector = 2336 ;
track . RawBytesPerSector = 2336 ;
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
case DaoMode . DataM2Raw :
track . BytesPerSector = 2352 ;
track . RawBytesPerSector = 2352 ;
rawMode2 = true ;
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
case DaoMode . DataM2RawSub :
track . BytesPerSector = 2352 ;
track . RawBytesPerSector = 2352 ;
track . SubchannelType = TrackSubchannelType . RawInterleaved ;
rawMode2 = true ;
subSize = 96 ;
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
case DaoMode . DataRaw :
track . BytesPerSector = 2048 ;
track . RawBytesPerSector = 2352 ;
rawMode1 = true ;
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
case DaoMode . DataRawSub :
track . BytesPerSector = 2048 ;
track . RawBytesPerSector = 2352 ;
track . SubchannelType = TrackSubchannelType . RawInterleaved ;
rawMode1 = true ;
subSize = 96 ;
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
// Check readability of sector tags
if ( rawMode1 | | rawMode2 )
{
if ( ! _imageInfo . ReadableSectorTags . Contains ( SectorTagType . CdSectorSync ) )
_imageInfo . ReadableSectorTags . Add ( SectorTagType . CdSectorSync ) ;
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
if ( ! _imageInfo . ReadableSectorTags . Contains ( SectorTagType . CdSectorHeader ) )
_imageInfo . ReadableSectorTags . Add ( SectorTagType . CdSectorHeader ) ;
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
if ( ! _imageInfo . ReadableSectorTags . Contains ( SectorTagType . CdSectorSubHeader ) & & rawMode2 )
_imageInfo . ReadableSectorTags . Add ( SectorTagType . CdSectorSubHeader ) ;
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
if ( ! _imageInfo . ReadableSectorTags . Contains ( SectorTagType . CdSectorEdc ) )
_imageInfo . ReadableSectorTags . Add ( SectorTagType . CdSectorEdc ) ;
}
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
if ( track . SubchannelType = = TrackSubchannelType . RawInterleaved )
{
track . SubchannelFilter = imageFilter ;
track . SubchannelFile = imageFilter . Filename ;
track . SubchannelOffset = ( ulong ) ( 150 * ( track . RawBytesPerSector + subSize ) ) ;
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
if ( ! _imageInfo . ReadableSectorTags . Contains ( SectorTagType . CdSectorSubchannel ) )
_imageInfo . ReadableSectorTags . Add ( SectorTagType . CdSectorSubchannel ) ;
}
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
track . FileOffset = ( ulong ) ( 150 * ( track . RawBytesPerSector + subSize ) ) ;
_neroTracks [ 1 ] . Offset = track . FileOffset ;
_neroTracks [ 1 ] . Sectors = track . EndSector - track . StartSector + 1 ;
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
// Add to offset map
_offsetmap . Add ( track . Sequence , track . StartSector ) ;
2021-07-01 14:51:32 +01:00
2022-03-06 13:29:38 +00:00
// This is basically what MagicISO does with DVD images
if ( track . RawBytesPerSector = = 2048 )
{
_imageInfo . MediaType = CommonTypes . MediaType . DVDROM ;
track . Type = TrackType . Data ;
2021-07-01 14:51:32 +01:00
}
2022-03-06 13:29:38 +00:00
_imageInfo . Sectors = track . EndSector + 1 ;
2021-07-01 12:26:07 +01:00
2022-03-06 13:29:38 +00:00
Tracks . Add ( track ) ;
2021-07-01 12:26:07 +01:00
2022-03-06 13:29:38 +00:00
// Create partition
var partition = new Partition
{
Description = $"Track {track.Sequence}" ,
Length = track . EndSector - track . StartSector + 1 ,
Name = StringHandlers . CToString ( _neroTracks [ 1 ] . Isrc ) ,
Sequence = 1 ,
Offset = 0 ,
Start = ( ulong ) track . Indexes [ 1 ] ,
Type = track . Type . ToString ( )
} ;
partition . Size = partition . Length * _neroTracks [ 1 ] . SectorSize ;
Partitions . Add ( partition ) ;
Sessions . Add ( new CommonTypes . Structs . Session
{
Sequence = 1 ,
StartSector = 0 ,
StartTrack = 1 ,
EndTrack = 1 ,
EndSector = track . EndSector
} ) ;
AaruConsole . ErrorWriteLine ( "Warning! This image is missing the last 150 sectors." ) ;
}
2021-07-01 12:26:07 +01:00
2022-03-06 13:29:38 +00:00
// MagicISO meets these conditions when disc contains more than 15 tracks and a single session
if ( _imageNewFormat & &
Tracks . Count > 0xF & &
moreTracksThanSessionTracks & &
onlyOneSession & &
Tracks . Any ( t = > t . Session > 0 ) )
{
foreach ( Track track in Tracks )
track . Session = 1 ;
2021-07-01 12:26:07 +01:00
2022-03-06 13:29:38 +00:00
Sessions . Clear ( ) ;
2021-06-11 01:32:51 +01:00
2022-03-06 13:29:38 +00:00
Track firstTrack = Tracks . First ( ) ;
Track lastTrack = Tracks . Last ( ) ;
2017-12-19 20:33:03 +00:00
2022-03-06 13:29:38 +00:00
Sessions . Add ( new CommonTypes . Structs . Session
2017-12-24 00:12:31 +00:00
{
2022-03-06 13:29:38 +00:00
EndSector = lastTrack . EndSector ,
StartSector = firstTrack . StartSector ,
Sequence = 1 ,
EndTrack = lastTrack . Sequence ,
StartTrack = firstTrack . Sequence
} ) ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
if ( _trackFlags . Count > 0 & &
! _imageInfo . ReadableSectorTags . Contains ( SectorTagType . CdTrackFlags ) )
_imageInfo . ReadableSectorTags . Add ( SectorTagType . CdTrackFlags ) ;
2017-12-19 20:33:03 +00:00
2022-03-06 13:29:38 +00:00
_neroFilter = imageFilter ;
2017-12-19 20:33:03 +00:00
2022-03-16 11:47:00 +00:00
if ( _imageInfo . MediaType is CommonTypes . MediaType . Unknown or CommonTypes . MediaType . CD )
2022-03-06 13:29:38 +00:00
{
2022-03-07 07:36:44 +00:00
var data = false ;
var mode2 = false ;
var firstAudio = false ;
var firstData = false ;
var audio = false ;
2021-06-11 02:47:10 +01:00
2022-03-07 07:36:44 +00:00
for ( var i = 0 ; i < _neroTracks . Count ; i + + )
2021-06-06 14:58:40 +01:00
{
2022-03-06 13:29:38 +00:00
// First track is audio
firstAudio | = i = = 0 & & ( ( DaoMode ) _neroTracks . ElementAt ( i ) . Value . Mode = = DaoMode . Audio | |
( DaoMode ) _neroTracks . ElementAt ( i ) . Value . Mode = = DaoMode . AudioAlt | |
( DaoMode ) _neroTracks . ElementAt ( i ) . Value . Mode = = DaoMode . AudioSub ) ;
// First track is data
firstData | = i = = 0 & & ( DaoMode ) _neroTracks . ElementAt ( i ) . Value . Mode ! = DaoMode . Audio & &
( DaoMode ) _neroTracks . ElementAt ( i ) . Value . Mode ! = DaoMode . AudioAlt & &
( DaoMode ) _neroTracks . ElementAt ( i ) . Value . Mode ! = DaoMode . AudioSub ;
// Any non first track is data
data | = i ! = 0 & & ( DaoMode ) _neroTracks . ElementAt ( i ) . Value . Mode ! = DaoMode . Audio & &
( DaoMode ) _neroTracks . ElementAt ( i ) . Value . Mode ! = DaoMode . AudioAlt & &
( DaoMode ) _neroTracks . ElementAt ( i ) . Value . Mode ! = DaoMode . AudioSub ;
// Any non first track is audio
audio | = i ! = 0 & & ( ( DaoMode ) _neroTracks . ElementAt ( i ) . Value . Mode = = DaoMode . Audio | |
( DaoMode ) _neroTracks . ElementAt ( i ) . Value . Mode = = DaoMode . AudioAlt | |
( DaoMode ) _neroTracks . ElementAt ( i ) . Value . Mode = = DaoMode . AudioSub ) ;
switch ( ( DaoMode ) _neroTracks . ElementAt ( i ) . Value . Mode )
{
case DaoMode . DataM2F1 :
case DaoMode . DataM2F2 :
case DaoMode . DataM2Raw :
case DaoMode . DataM2RawSub :
mode2 = true ;
break ;
}
2021-06-06 14:58:40 +01:00
}
2022-03-06 13:29:38 +00:00
if ( ! data & &
! firstData )
_imageInfo . MediaType = CommonTypes . MediaType . CDDA ;
else if ( firstAudio & &
data & &
Sessions . Count > 1 & &
mode2 )
_imageInfo . MediaType = CommonTypes . MediaType . CDPLUS ;
2022-03-07 07:36:44 +00:00
else if ( firstData & & audio | | mode2 )
2022-03-06 13:29:38 +00:00
_imageInfo . MediaType = CommonTypes . MediaType . CDROMXA ;
else if ( ! audio )
_imageInfo . MediaType = CommonTypes . MediaType . CDROM ;
else
_imageInfo . MediaType = CommonTypes . MediaType . CD ;
}
2021-06-11 02:47:10 +01:00
2022-03-06 13:29:38 +00:00
_imageInfo . XmlMediaType = XmlMediaType . OpticalDisc ;
AaruConsole . VerboseWriteLine ( "Nero image contains a disc of type {0}" , _imageInfo . MediaType ) ;
_sectorBuilder = new SectorBuilder ( ) ;
2022-03-16 11:47:00 +00:00
_isCd = _imageInfo . MediaType is CommonTypes . MediaType . CD or CommonTypes . MediaType . CDDA
or CommonTypes . MediaType . CDG
or CommonTypes . MediaType . CDEG
or CommonTypes . MediaType . CDI
or CommonTypes . MediaType . CDROM
or CommonTypes . MediaType . CDROMXA
or CommonTypes . MediaType . CDPLUS
or CommonTypes . MediaType . CDMO
or CommonTypes . MediaType . CDR
or CommonTypes . MediaType . CDRW
or CommonTypes . MediaType . CDMRW
or CommonTypes . MediaType . VCD
or CommonTypes . MediaType . SVCD
or CommonTypes . MediaType . PCD
or CommonTypes . MediaType . DTSCD
or CommonTypes . MediaType . CDMIDI
or CommonTypes . MediaType . CDV
or CommonTypes . MediaType . CDIREADY
or CommonTypes . MediaType . FMTOWNS
or CommonTypes . MediaType . PS1CD
or CommonTypes . MediaType . PS2CD
or CommonTypes . MediaType . MEGACD
or CommonTypes . MediaType . SATURNCD
or CommonTypes . MediaType . GDROM
or CommonTypes . MediaType . GDR
or CommonTypes . MediaType . MilCD
or CommonTypes . MediaType . SuperCDROM2
or CommonTypes . MediaType . JaguarCD
or CommonTypes . MediaType . ThreeDO
or CommonTypes . MediaType . PCFX
or CommonTypes . MediaType . NeoGeoCD
or CommonTypes . MediaType . CDTV
or CommonTypes . MediaType . CD32
or CommonTypes . MediaType . Playdia
or CommonTypes . MediaType . Pippin
or CommonTypes . MediaType . VideoNow
or CommonTypes . MediaType . VideoNowColor
or CommonTypes . MediaType . VideoNowXp
or CommonTypes . MediaType . CVD ;
2022-03-06 13:29:38 +00:00
if ( _isCd )
2021-09-16 19:10:39 +01:00
return ErrorNumber . NoError ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
foreach ( Track track in Tracks )
{
track . Pregap = 0 ;
track . Indexes ? . Clear ( ) ;
2017-12-24 00:12:31 +00:00
}
2017-12-19 20:33:03 +00:00
2022-03-06 13:29:38 +00:00
_imageInfo . ReadableMediaTags . Remove ( MediaTagType . CD_MCN ) ;
_imageInfo . ReadableSectorTags . Remove ( SectorTagType . CdTrackIsrc ) ;
_imageInfo . ReadableSectorTags . Remove ( SectorTagType . CdTrackFlags ) ;
return ErrorNumber . NoError ;
}
catch
2017-12-24 00:12:31 +00:00
{
2022-03-06 13:29:38 +00:00
AaruConsole . DebugWrite ( "Nero plugin" , "Exception occurred opening file." ) ;
2021-09-18 15:01:31 +01:00
2022-03-06 13:29:38 +00:00
return ErrorNumber . UnexpectedException ;
}
}
2021-09-18 15:01:31 +01:00
2022-03-06 13:29:38 +00:00
/// <inheritdoc />
public ErrorNumber ReadMediaTag ( MediaTagType tag , out byte [ ] buffer )
{
buffer = null ;
2021-09-18 15:01:31 +01:00
2022-03-06 13:29:38 +00:00
switch ( tag )
{
case MediaTagType . CD_MCN :
buffer = _upc ? . Clone ( ) as byte [ ] ;
2017-12-19 20:33:03 +00:00
2022-03-06 13:29:38 +00:00
return buffer ! = null ? ErrorNumber . NoError : ErrorNumber . NoData ;
2017-12-19 20:33:03 +00:00
2022-03-06 13:29:38 +00:00
case MediaTagType . CD_TEXT : return ErrorNumber . NotImplemented ;
default : return ErrorNumber . NotSupported ;
}
}
2017-12-19 20:33:03 +00:00
2022-03-06 13:29:38 +00:00
/// <inheritdoc />
2022-03-07 07:36:44 +00:00
public ErrorNumber ReadSector ( ulong sectorAddress , out byte [ ] buffer ) = > ReadSectors ( sectorAddress , 1 , out buffer ) ;
2017-12-19 20:33:03 +00:00
2022-03-06 13:29:38 +00:00
/// <inheritdoc />
public ErrorNumber ReadSectorTag ( ulong sectorAddress , SectorTagType tag , out byte [ ] buffer ) = >
ReadSectorsTag ( sectorAddress , 1 , tag , out buffer ) ;
2017-12-19 20:33:03 +00:00
2022-03-06 13:29:38 +00:00
/// <inheritdoc />
public ErrorNumber ReadSector ( ulong sectorAddress , uint track , out byte [ ] buffer ) = >
ReadSectors ( sectorAddress , 1 , track , out buffer ) ;
2021-09-19 21:16:47 +01:00
2022-03-06 13:29:38 +00:00
/// <inheritdoc />
public ErrorNumber ReadSectorTag ( ulong sectorAddress , uint track , SectorTagType tag , out byte [ ] buffer ) = >
ReadSectorsTag ( sectorAddress , 1 , track , tag , out buffer ) ;
2021-09-19 21:16:47 +01:00
2022-03-06 13:29:38 +00:00
/// <inheritdoc />
public ErrorNumber ReadSectors ( ulong sectorAddress , uint length , out byte [ ] buffer )
{
buffer = null ;
2017-12-19 20:33:03 +00:00
2022-03-06 13:29:38 +00:00
foreach ( KeyValuePair < uint , ulong > kvp in from kvp in _offsetmap where sectorAddress > = kvp . Value
2022-03-07 07:36:44 +00:00
from track in Tracks where track . Sequence = = kvp . Key
where sectorAddress - kvp . Value < = track . EndSector - track . StartSector
select kvp )
2022-03-06 13:29:38 +00:00
return ReadSectors ( sectorAddress - kvp . Value , length , kvp . Key , out buffer ) ;
2021-09-20 20:52:18 +01:00
2022-03-06 13:29:38 +00:00
return ErrorNumber . SectorNotFound ;
}
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
/// <inheritdoc />
public ErrorNumber ReadSectorsTag ( ulong sectorAddress , uint length , SectorTagType tag , out byte [ ] buffer )
{
buffer = null ;
2021-09-20 20:52:18 +01:00
2022-03-06 13:29:38 +00:00
foreach ( KeyValuePair < uint , ulong > kvp in from kvp in _offsetmap where sectorAddress > = kvp . Value
2022-03-07 07:36:44 +00:00
from track in Tracks where track . Sequence = = kvp . Key
where sectorAddress - kvp . Value < = track . EndSector - track . StartSector
select kvp )
2022-03-06 13:29:38 +00:00
return ReadSectorsTag ( sectorAddress - kvp . Value , length , kvp . Key , tag , out buffer ) ;
return ErrorNumber . SectorNotFound ;
}
2021-09-21 01:38:54 +01:00
2022-03-06 13:29:38 +00:00
/// <inheritdoc />
public ErrorNumber ReadSectors ( ulong sectorAddress , uint length , uint track , out byte [ ] buffer )
{
buffer = null ;
2017-12-19 20:33:03 +00:00
2022-03-06 13:29:38 +00:00
if ( ! _neroTracks . TryGetValue ( track , out NeroTrack aaruTrack ) )
return ErrorNumber . SectorNotFound ;
2017-12-19 20:33:03 +00:00
2022-03-06 13:29:38 +00:00
if ( length > aaruTrack . Sectors )
return ErrorNumber . OutOfRange ;
2017-12-19 20:33:03 +00:00
2022-03-06 13:29:38 +00:00
uint sectorOffset ;
uint sectorSize ;
uint sectorSkip ;
2022-03-07 07:36:44 +00:00
var mode2 = false ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
switch ( ( DaoMode ) aaruTrack . Mode )
{
case DaoMode . Data :
case DaoMode . DataM2F1 :
{
sectorOffset = 0 ;
sectorSize = 2048 ;
sectorSkip = 0 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
case DaoMode . DataM2F2 :
{
mode2 = true ;
sectorOffset = 0 ;
sectorSize = 2336 ;
sectorSkip = 0 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
case DaoMode . Audio :
case DaoMode . AudioAlt :
{
sectorOffset = 0 ;
sectorSize = 2352 ;
sectorSkip = 0 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
case DaoMode . DataRaw :
{
sectorOffset = 16 ;
sectorSize = 2048 ;
sectorSkip = 288 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
case DaoMode . DataM2Raw :
{
mode2 = true ;
sectorOffset = 0 ;
sectorSize = 2352 ;
sectorSkip = 0 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
case DaoMode . DataRawSub :
{
sectorOffset = 16 ;
sectorSize = 2048 ;
sectorSkip = 288 + 96 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
case DaoMode . DataM2RawSub :
{
mode2 = true ;
sectorOffset = 0 ;
sectorSize = 2352 ;
sectorSkip = 96 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
case DaoMode . AudioSub :
{
sectorOffset = 0 ;
sectorSize = 2352 ;
sectorSkip = 96 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
2017-12-24 00:12:31 +00:00
}
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
default : return ErrorNumber . NotSupported ;
}
2017-12-19 20:33:03 +00:00
2022-03-06 13:29:38 +00:00
buffer = new byte [ sectorSize * length ] ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
_imageStream = _neroFilter . GetDataForkStream ( ) ;
var br = new BinaryReader ( _imageStream ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
br . BaseStream . Seek ( ( long ) aaruTrack . Offset + ( long ) ( sectorAddress * ( sectorOffset + sectorSize + sectorSkip ) ) ,
SeekOrigin . Begin ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
if ( mode2 )
{
var mode2Ms = new MemoryStream ( ( int ) ( sectorSize * length ) ) ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
buffer = br . ReadBytes ( ( int ) ( ( sectorSize + sectorSkip ) * length ) ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
for ( var i = 0 ; i < length ; i + + )
2022-03-06 13:29:38 +00:00
{
2022-03-07 07:36:44 +00:00
var sector = new byte [ sectorSize ] ;
2022-03-06 13:29:38 +00:00
Array . Copy ( buffer , ( sectorSize + sectorSkip ) * i , sector , 0 , sectorSize ) ;
sector = Sector . GetUserData ( sector ) ;
mode2Ms . Write ( sector , 0 , sector . Length ) ;
2020-01-11 22:44:25 +00:00
}
2017-12-19 20:33:03 +00:00
2022-03-06 13:29:38 +00:00
buffer = mode2Ms . ToArray ( ) ;
2017-12-24 00:12:31 +00:00
}
2022-03-06 13:29:38 +00:00
else if ( sectorOffset = = 0 & &
sectorSkip = = 0 )
buffer = br . ReadBytes ( ( int ) ( sectorSize * length ) ) ;
else
2022-03-07 07:36:44 +00:00
for ( var i = 0 ; i < length ; i + + )
2022-03-06 13:29:38 +00:00
{
br . BaseStream . Seek ( sectorOffset , SeekOrigin . Current ) ;
byte [ ] sector = br . ReadBytes ( ( int ) sectorSize ) ;
br . BaseStream . Seek ( sectorSkip , SeekOrigin . Current ) ;
Array . Copy ( sector , 0 , buffer , i * sectorSize , sectorSize ) ;
}
2017-12-19 20:33:03 +00:00
2022-03-06 13:29:38 +00:00
return ErrorNumber . NoError ;
}
2021-09-21 03:42:15 +01:00
2022-03-06 13:29:38 +00:00
/// <inheritdoc />
public ErrorNumber ReadSectorsTag ( ulong sectorAddress , uint length , uint track , SectorTagType tag ,
out byte [ ] buffer )
{
buffer = null ;
2020-06-14 23:45:26 +01:00
2022-03-16 11:47:00 +00:00
if ( tag is SectorTagType . CdTrackFlags or SectorTagType . CdTrackIsrc )
2022-03-06 13:29:38 +00:00
track = ( uint ) sectorAddress ;
2017-12-20 17:15:26 +00:00
2022-03-06 13:29:38 +00:00
if ( ! _neroTracks . TryGetValue ( track , out NeroTrack aaruTrack ) )
return ErrorNumber . SectorNotFound ;
2017-12-20 17:15:26 +00:00
2022-03-06 13:29:38 +00:00
if ( length > aaruTrack . Sectors )
return ErrorNumber . OutOfRange ;
2017-12-20 17:15:26 +00:00
2022-03-06 13:29:38 +00:00
uint sectorOffset ;
uint sectorSize ;
uint sectorSkip ;
switch ( tag )
{
case SectorTagType . CdSectorEcc :
case SectorTagType . CdSectorEccP :
case SectorTagType . CdSectorEccQ :
case SectorTagType . CdSectorEdc :
case SectorTagType . CdSectorHeader :
case SectorTagType . CdSectorSubchannel :
case SectorTagType . CdSectorSubHeader :
case SectorTagType . CdSectorSync : break ;
case SectorTagType . CdTrackFlags :
if ( ! _trackFlags . TryGetValue ( track , out byte flag ) )
return ErrorNumber . NoData ;
buffer = new [ ]
{
flag
} ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
return ErrorNumber . NoError ;
case SectorTagType . CdTrackIsrc :
buffer = aaruTrack . Isrc ;
2021-09-21 03:42:15 +01:00
2022-03-06 13:29:38 +00:00
return ErrorNumber . NoError ;
case SectorTagType . CdTrackText : return ErrorNumber . NotImplemented ;
default : return ErrorNumber . NotSupported ;
}
2017-12-19 20:33:03 +00:00
2022-03-06 13:29:38 +00:00
switch ( ( DaoMode ) aaruTrack . Mode )
{
case DaoMode . Data :
case DaoMode . DataM2F1 : return ErrorNumber . NoData ;
case DaoMode . DataM2F2 :
2017-12-24 00:12:31 +00:00
{
2022-03-06 13:29:38 +00:00
switch ( tag )
2017-12-24 00:12:31 +00:00
{
2022-03-06 13:29:38 +00:00
case SectorTagType . CdSectorSync :
case SectorTagType . CdSectorHeader :
case SectorTagType . CdSectorSubchannel :
case SectorTagType . CdSectorEcc :
case SectorTagType . CdSectorEccP :
case SectorTagType . CdSectorEccQ : return ErrorNumber . NotSupported ;
case SectorTagType . CdSectorSubHeader :
2017-12-24 00:12:31 +00:00
{
2022-03-06 13:29:38 +00:00
sectorOffset = 0 ;
sectorSize = 8 ;
sectorSkip = 2328 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
case SectorTagType . CdSectorEdc :
{
sectorOffset = 2332 ;
sectorSize = 4 ;
sectorSkip = 0 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
2017-12-24 00:12:31 +00:00
}
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
default : return ErrorNumber . NotSupported ;
2017-12-24 00:12:31 +00:00
}
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
case DaoMode . Audio :
case DaoMode . AudioAlt : return ErrorNumber . NoData ;
case DaoMode . DataRaw :
{
switch ( tag )
2017-12-24 00:12:31 +00:00
{
2022-03-06 13:29:38 +00:00
case SectorTagType . CdSectorSync :
2017-12-24 00:12:31 +00:00
{
2022-03-06 13:29:38 +00:00
sectorOffset = 0 ;
sectorSize = 12 ;
sectorSkip = 2340 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
case SectorTagType . CdSectorHeader :
{
sectorOffset = 12 ;
sectorSize = 4 ;
sectorSkip = 2336 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
case SectorTagType . CdSectorSubchannel :
case SectorTagType . CdSectorSubHeader : return ErrorNumber . NotSupported ;
case SectorTagType . CdSectorEcc :
{
sectorOffset = 2076 ;
sectorSize = 276 ;
sectorSkip = 0 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
case SectorTagType . CdSectorEccP :
{
sectorOffset = 2076 ;
sectorSize = 172 ;
sectorSkip = 104 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
case SectorTagType . CdSectorEccQ :
{
sectorOffset = 2248 ;
sectorSize = 104 ;
sectorSkip = 0 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
case SectorTagType . CdSectorEdc :
{
sectorOffset = 2064 ;
sectorSize = 4 ;
sectorSkip = 284 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
2014-07-09 19:52:00 +01:00
}
2022-03-06 13:29:38 +00:00
default : return ErrorNumber . NotSupported ;
2014-07-09 19:52:00 +01:00
}
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2021-06-11 01:50:42 +01:00
2022-03-06 13:29:38 +00:00
case DaoMode . DataM2RawSub :
switch ( tag )
{
case SectorTagType . CdSectorSync :
{
sectorOffset = 0 ;
sectorSize = 12 ;
sectorSkip = 2340 + 96 ;
2021-06-11 01:50:42 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2021-06-11 01:50:42 +01:00
2022-03-06 13:29:38 +00:00
case SectorTagType . CdSectorHeader :
{
sectorOffset = 12 ;
sectorSize = 4 ;
sectorSkip = 2336 + 96 ;
2021-06-11 01:50:42 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2021-06-11 01:50:42 +01:00
2022-03-06 13:29:38 +00:00
case SectorTagType . CdSectorSubHeader :
{
sectorOffset = 16 ;
sectorSize = 8 ;
sectorSkip = 2328 + 96 ;
2021-06-11 01:50:42 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2021-06-11 01:50:42 +01:00
2022-03-06 13:29:38 +00:00
case SectorTagType . CdSectorEdc :
{
sectorOffset = 2348 ;
sectorSize = 4 ;
sectorSkip = 0 + 96 ;
2021-06-11 01:50:42 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2021-06-11 01:50:42 +01:00
2022-03-06 13:29:38 +00:00
case SectorTagType . CdSectorSubchannel :
{
sectorOffset = 2352 ;
sectorSize = 96 ;
sectorSkip = 0 ;
2021-06-11 01:50:42 +01:00
2022-03-06 13:29:38 +00:00
break ;
2021-06-11 01:50:42 +01:00
}
2022-03-06 13:29:38 +00:00
default : return ErrorNumber . NotSupported ;
}
break ;
case DaoMode . DataRawSub :
{
switch ( tag )
2014-07-09 19:52:00 +01:00
{
2022-03-06 13:29:38 +00:00
case SectorTagType . CdSectorSync :
2014-07-09 19:52:00 +01:00
{
2022-03-06 13:29:38 +00:00
sectorOffset = 0 ;
sectorSize = 12 ;
sectorSkip = 2340 + 96 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
case SectorTagType . CdSectorHeader :
{
sectorOffset = 12 ;
sectorSize = 4 ;
sectorSkip = 2336 + 96 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
case SectorTagType . CdSectorSubchannel :
{
sectorOffset = 2352 ;
sectorSize = 96 ;
sectorSkip = 0 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
case SectorTagType . CdSectorSubHeader : return ErrorNumber . NotSupported ;
case SectorTagType . CdSectorEcc :
{
sectorOffset = 2076 ;
sectorSize = 276 ;
sectorSkip = 0 + 96 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
case SectorTagType . CdSectorEccP :
{
sectorOffset = 2076 ;
sectorSize = 172 ;
sectorSkip = 104 + 96 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
case SectorTagType . CdSectorEccQ :
{
sectorOffset = 2248 ;
sectorSize = 104 ;
sectorSkip = 0 + 96 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
case SectorTagType . CdSectorEdc :
{
sectorOffset = 2064 ;
sectorSize = 4 ;
sectorSkip = 284 + 96 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
2017-12-21 06:06:19 +00:00
}
2015-12-06 05:09:31 +00:00
2022-03-06 13:29:38 +00:00
default : return ErrorNumber . NotSupported ;
2017-12-24 00:12:31 +00:00
}
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
case DaoMode . AudioSub :
{
if ( tag ! = SectorTagType . CdSectorSubchannel )
return ErrorNumber . NotSupported ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
sectorOffset = 2352 ;
sectorSize = 96 ;
sectorSkip = 0 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
2017-12-24 00:12:31 +00:00
}
2017-12-21 06:06:19 +00:00
2022-03-06 13:29:38 +00:00
default : return ErrorNumber . NotSupported ;
}
2017-12-21 06:06:19 +00:00
2022-03-06 13:29:38 +00:00
buffer = new byte [ sectorSize * length ] ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
_imageStream = _neroFilter . GetDataForkStream ( ) ;
var br = new BinaryReader ( _imageStream ) ;
2020-01-11 22:44:25 +00:00
2022-03-07 07:36:44 +00:00
br . BaseStream . Seek ( ( long ) aaruTrack . Offset + ( long ) ( sectorAddress * ( sectorOffset + sectorSize + sectorSkip ) ) ,
SeekOrigin . Begin ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
if ( sectorOffset = = 0 & &
sectorSkip = = 0 )
buffer = br . ReadBytes ( ( int ) ( sectorSize * length ) ) ;
else
2022-03-07 07:36:44 +00:00
for ( var i = 0 ; i < length ; i + + )
2022-03-06 13:29:38 +00:00
{
br . BaseStream . Seek ( sectorOffset , SeekOrigin . Current ) ;
byte [ ] sector = br . ReadBytes ( ( int ) sectorSize ) ;
br . BaseStream . Seek ( sectorSkip , SeekOrigin . Current ) ;
Array . Copy ( sector , 0 , buffer , i * sectorSize , sectorSize ) ;
}
2016-08-08 18:44:08 +01:00
2022-03-06 13:29:38 +00:00
return ErrorNumber . NoError ;
}
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
/// <inheritdoc />
public ErrorNumber ReadSectorLong ( ulong sectorAddress , out byte [ ] buffer ) = >
ReadSectorsLong ( sectorAddress , 1 , out buffer ) ;
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
/// <inheritdoc />
public ErrorNumber ReadSectorLong ( ulong sectorAddress , uint track , out byte [ ] buffer ) = >
ReadSectorsLong ( sectorAddress , 1 , track , out buffer ) ;
2021-09-20 14:22:22 +01:00
2022-03-06 13:29:38 +00:00
/// <inheritdoc />
public ErrorNumber ReadSectorsLong ( ulong sectorAddress , uint length , out byte [ ] buffer )
{
buffer = null ;
2021-09-20 14:22:22 +01:00
2022-03-06 13:29:38 +00:00
foreach ( KeyValuePair < uint , ulong > kvp in from kvp in _offsetmap where sectorAddress > = kvp . Value
2022-03-07 07:36:44 +00:00
from track in Tracks where track . Sequence = = kvp . Key
where sectorAddress - kvp . Value < = track . EndSector - track . StartSector
select kvp )
2022-03-06 13:29:38 +00:00
return ReadSectorsLong ( sectorAddress - kvp . Value , length , kvp . Key , out buffer ) ;
2015-12-05 17:21:47 +00:00
2022-03-06 13:29:38 +00:00
return ErrorNumber . SectorNotFound ;
}
2021-09-21 01:38:54 +01:00
2022-03-06 13:29:38 +00:00
/// <inheritdoc />
public ErrorNumber ReadSectorsLong ( ulong sectorAddress , uint length , uint track , out byte [ ] buffer )
{
buffer = null ;
2021-06-11 02:47:10 +01:00
2022-03-06 13:29:38 +00:00
if ( ! _isCd )
return ReadSectors ( sectorAddress , length , track , out buffer ) ;
2016-08-08 18:44:08 +01:00
2022-03-06 13:29:38 +00:00
if ( ! _neroTracks . TryGetValue ( track , out NeroTrack aaruTrack ) )
return ErrorNumber . SectorNotFound ;
2016-08-08 18:44:08 +01:00
2022-03-06 13:29:38 +00:00
if ( length > aaruTrack . Sectors )
return ErrorNumber . OutOfRange ;
2016-08-08 18:44:08 +01:00
2022-03-06 13:29:38 +00:00
uint sectorOffset ;
uint sectorSize ;
uint sectorSkip ;
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
switch ( ( DaoMode ) aaruTrack . Mode )
{
case DaoMode . Data :
case DaoMode . DataM2F1 :
{
sectorOffset = 0 ;
sectorSize = 2048 ;
sectorSkip = 0 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
case DaoMode . DataM2F2 :
{
sectorOffset = 0 ;
sectorSize = 2336 ;
sectorSkip = 0 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
case DaoMode . DataRaw :
case DaoMode . DataM2Raw :
case DaoMode . Audio :
case DaoMode . AudioAlt :
{
sectorOffset = 0 ;
sectorSize = 2352 ;
sectorSkip = 0 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
2020-01-11 22:44:25 +00:00
2022-03-06 13:29:38 +00:00
case DaoMode . DataRawSub :
case DaoMode . DataM2RawSub :
case DaoMode . AudioSub :
{
sectorOffset = 0 ;
sectorSize = 2352 ;
sectorSkip = 96 ;
2019-05-11 20:49:32 +01:00
2022-03-06 13:29:38 +00:00
break ;
2017-12-24 00:12:31 +00:00
}
2016-08-08 18:44:08 +01:00
2022-03-06 13:29:38 +00:00
default : return ErrorNumber . NotSupported ;
}
2016-08-08 18:44:08 +01:00
2022-03-06 13:29:38 +00:00
buffer = new byte [ sectorSize * length ] ;
2016-08-08 18:44:08 +01:00
2022-03-06 13:29:38 +00:00
_imageStream = _neroFilter . GetDataForkStream ( ) ;
var br = new BinaryReader ( _imageStream ) ;
2017-12-24 00:12:31 +00:00
2022-03-07 07:36:44 +00:00
br . BaseStream . Seek ( ( long ) aaruTrack . Offset + ( long ) ( sectorAddress * ( sectorOffset + sectorSize + sectorSkip ) ) ,
SeekOrigin . Begin ) ;
2016-08-08 18:44:08 +01:00
2022-03-06 13:29:38 +00:00
if ( sectorOffset = = 0 & &
sectorSkip = = 0 )
buffer = br . ReadBytes ( ( int ) ( sectorSize * length ) ) ;
else
2022-03-07 07:36:44 +00:00
for ( var i = 0 ; i < length ; i + + )
2020-06-21 22:30:07 +01:00
{
2022-03-06 13:29:38 +00:00
br . BaseStream . Seek ( sectorOffset , SeekOrigin . Current ) ;
byte [ ] sector = br . ReadBytes ( ( int ) sectorSize ) ;
br . BaseStream . Seek ( sectorSkip , SeekOrigin . Current ) ;
2020-06-21 22:30:07 +01:00
2022-03-06 13:29:38 +00:00
Array . Copy ( sector , 0 , buffer , i * sectorSize , sectorSize ) ;
}
2020-06-21 22:30:07 +01:00
2022-03-06 13:29:38 +00:00
switch ( ( DaoMode ) aaruTrack . Mode )
{
case DaoMode . Data :
{
2022-03-07 07:36:44 +00:00
var fullSector = new byte [ 2352 ] ;
var fullBuffer = new byte [ 2352 * length ] ;
2020-06-21 22:30:07 +01:00
2022-03-06 13:29:38 +00:00
for ( uint i = 0 ; i < length ; i + + )
2020-06-21 22:30:07 +01:00
{
2022-03-06 13:29:38 +00:00
Array . Copy ( buffer , i * 2048 , fullSector , 16 , 2048 ) ;
_sectorBuilder . ReconstructPrefix ( ref fullSector , TrackType . CdMode1 , ( long ) ( sectorAddress + i ) ) ;
_sectorBuilder . ReconstructEcc ( ref fullSector , TrackType . CdMode1 ) ;
Array . Copy ( fullSector , 0 , fullBuffer , i * 2352 , 2352 ) ;
}
2020-06-21 22:30:07 +01:00
2022-03-06 13:29:38 +00:00
buffer = fullBuffer ;
2020-06-21 22:30:07 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
case DaoMode . DataM2F1 :
{
2022-03-07 07:36:44 +00:00
var fullSector = new byte [ 2352 ] ;
var fullBuffer = new byte [ 2352 * length ] ;
2020-06-21 22:30:07 +01:00
2022-03-06 13:29:38 +00:00
for ( uint i = 0 ; i < length ; i + + )
{
Array . Copy ( buffer , i * 2048 , fullSector , 24 , 2048 ) ;
2020-06-21 22:30:07 +01:00
2022-03-07 07:36:44 +00:00
_sectorBuilder . ReconstructPrefix ( ref fullSector , TrackType . CdMode2Form1 , ( long ) ( sectorAddress + i ) ) ;
2020-06-21 22:30:07 +01:00
2022-03-06 13:29:38 +00:00
_sectorBuilder . ReconstructEcc ( ref fullSector , TrackType . CdMode2Form1 ) ;
Array . Copy ( fullSector , 0 , fullBuffer , i * 2352 , 2352 ) ;
2020-06-21 22:30:07 +01:00
}
2022-03-06 13:29:38 +00:00
buffer = fullBuffer ;
2020-06-21 22:30:07 +01:00
2022-03-06 13:29:38 +00:00
break ;
}
case DaoMode . DataM2F2 :
{
2022-03-07 07:36:44 +00:00
var fullSector = new byte [ 2352 ] ;
var fullBuffer = new byte [ 2352 * length ] ;
2020-06-21 22:30:07 +01:00
2022-03-06 13:29:38 +00:00
for ( uint i = 0 ; i < length ; i + + )
{
_sectorBuilder . ReconstructPrefix ( ref fullSector , TrackType . CdMode2Formless ,
( long ) ( sectorAddress + i ) ) ;
2020-06-21 22:30:07 +01:00
2022-03-06 13:29:38 +00:00
Array . Copy ( buffer , i * 2336 , fullSector , 16 , 2336 ) ;
Array . Copy ( fullSector , 0 , fullBuffer , i * 2352 , 2352 ) ;
2020-06-21 22:30:07 +01:00
}
2022-03-06 13:29:38 +00:00
buffer = fullBuffer ;
2015-12-05 17:21:47 +00:00
2022-03-06 13:29:38 +00:00
break ;
}
}
2014-07-09 19:52:00 +01:00
2022-03-06 13:29:38 +00:00
return ErrorNumber . NoError ;
2014-07-09 19:52:00 +01:00
}
2022-03-06 13:29:38 +00:00
/// <inheritdoc />
public List < Track > GetSessionTracks ( CommonTypes . Structs . Session session ) = > GetSessionTracks ( session . Sequence ) ;
/// <inheritdoc />
public List < Track > GetSessionTracks ( ushort session ) = > Tracks . Where ( track = > track . Session = = session ) . ToList ( ) ;
2014-07-09 19:52:00 +01:00
}