2017-04-29 07:04:03 +01:00
//
// Author:
// Natalia Portillo claunia@claunia.com
//
// Copyright (c) 2017, © Claunia.com
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the distribution.
// * Neither the name of the [ORGANIZATION] nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
2017-12-30 00:32:21 +00:00
2017-04-29 08:43:43 +01:00
using System ;
using System.Collections.Generic ;
2017-05-03 01:54:02 +01:00
using System.IO ;
2017-04-29 08:43:43 +01:00
using DiscImageChef.CommonTypes ;
2017-12-30 00:32:21 +00:00
using DiscImageChef.Decoders.CD ;
using DiscImageChef.Decoders.DVD ;
2017-05-03 01:54:02 +01:00
using DiscImageChef.Decoders.PCMCIA ;
2017-12-30 00:32:21 +00:00
using DiscImageChef.DiscImages ;
2017-05-03 01:54:02 +01:00
using DiscImageChef.Filesystems ;
using DiscImageChef.Filters ;
2017-12-30 00:32:21 +00:00
using DiscImageChef.Metadata ;
2017-12-29 19:31:26 +00:00
using DiscImageChef.Partitions ;
2017-05-03 01:54:02 +01:00
using Schemas ;
2017-12-30 00:32:21 +00:00
using DMI = DiscImageChef . Decoders . Xbox . DMI ;
using MediaType = DiscImageChef . CommonTypes . MediaType ;
using Session = DiscImageChef . DiscImages . Session ;
using TrackType = Schemas . TrackType ;
using Tuple = DiscImageChef . Decoders . PCMCIA . Tuple ;
2017-04-29 08:43:43 +01:00
2017-05-10 21:04:42 +01:00
namespace osrepodbmgr.Core
2017-04-29 07:04:03 +01:00
{
2017-05-10 21:06:28 +01:00
public static partial class Workers
2017-04-29 07:04:03 +01:00
{
2017-04-29 08:43:43 +01:00
public static void AddMedia ( )
2017-04-29 07:04:03 +01:00
{
2017-12-30 00:32:21 +00:00
if ( string . IsNullOrWhiteSpace ( Context . SelectedFile ) )
2017-04-29 08:43:43 +01:00
{
2017-12-30 00:32:21 +00:00
Failed ? . Invoke ( "There is no file set" ) ;
2017-04-29 08:43:43 +01:00
return ;
}
string filesPath ;
2017-12-30 00:32:21 +00:00
if ( ! string . IsNullOrEmpty ( Context . TmpFolder ) & & Directory . Exists ( Context . TmpFolder ) )
filesPath = Context . TmpFolder ;
else filesPath = Context . Path ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
string selectedFile = Path . Combine ( filesPath , Context . SelectedFile ) ;
2017-04-29 08:43:43 +01:00
if ( ! File . Exists ( selectedFile ) )
{
2017-12-30 00:32:21 +00:00
Failed ? . Invoke ( "Selected file does not exist" ) ;
2017-04-29 08:43:43 +01:00
return ;
}
CICMMetadataType sidecar = new CICMMetadataType ( ) ;
2017-12-30 00:32:21 +00:00
PluginBase plugins = new PluginBase ( ) ;
2017-04-29 08:43:43 +01:00
long maxProgress = 4 ;
FiltersList filtersList = new FiltersList ( ) ;
2017-12-30 00:32:21 +00:00
UpdateProgress ? . Invoke ( null , "Detecting image filter" , 1 , maxProgress ) ;
2017-04-29 08:43:43 +01:00
2017-12-29 19:31:26 +00:00
IFilter inputFilter = filtersList . GetFilter ( selectedFile ) ;
2017-04-29 08:43:43 +01:00
if ( inputFilter = = null )
{
2017-12-30 00:32:21 +00:00
Failed ? . Invoke ( "Cannot open specified file." ) ;
2017-04-29 08:43:43 +01:00
return ;
}
try
{
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-05-19 03:24:34 +01:00
stopwatch . Restart ( ) ;
2017-12-30 00:32:21 +00:00
#endif
UpdateProgress ? . Invoke ( null , "Detecting image format" , 2 , maxProgress ) ;
IMediaImage imageFormat = ImageFormat . Detect ( inputFilter ) ;
#if DEBUG
2017-05-19 03:24:34 +01:00
stopwatch . Stop ( ) ;
2017-12-30 00:32:21 +00:00
Console . WriteLine ( "Core.AddMedia(): Took {0} seconds to detect image format" ,
stopwatch . Elapsed . TotalSeconds ) ;
#endif
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
if ( imageFormat = = null )
2017-04-29 08:43:43 +01:00
{
2017-12-30 00:32:21 +00:00
Failed ? . Invoke ( "Image format not identified, not proceeding with analysis." ) ;
2017-04-29 08:43:43 +01:00
return ;
}
try
{
2017-12-30 00:32:21 +00:00
if ( ! imageFormat . Open ( inputFilter ) )
2017-04-29 08:43:43 +01:00
{
2017-12-30 00:32:21 +00:00
Failed ? . Invoke ( "Unable to open image format\n" + "No error given" ) ;
2017-04-29 08:43:43 +01:00
return ;
}
}
catch ( Exception ex )
{
2017-12-30 00:32:21 +00:00
Failed ? . Invoke ( "Unable to open image format\n" + $"Error: {ex.Message}" ) ;
#if DEBUG
2017-06-13 18:21:12 +01:00
Console . WriteLine ( "Exception {0}\n{1}" , ex . Message , ex . InnerException ) ;
2017-12-30 00:32:21 +00:00
#endif
2017-04-29 08:43:43 +01:00
return ;
}
2017-12-30 00:32:21 +00:00
FileInfo fi = new FileInfo ( selectedFile ) ;
2017-04-29 08:43:43 +01:00
FileStream fs = new FileStream ( selectedFile , FileMode . Open , FileAccess . Read ) ;
Checksum imgChkWorker = new Checksum ( ) ;
2017-12-30 00:32:21 +00:00
UpdateProgress ? . Invoke ( null , "Hashing image file" , 3 , maxProgress ) ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-05-19 03:24:34 +01:00
stopwatch . Restart ( ) ;
2017-12-30 00:32:21 +00:00
#endif
2017-04-29 08:43:43 +01:00
byte [ ] data ;
2017-12-30 00:32:21 +00:00
long position = 0 ;
while ( position < fi . Length - 524288 )
2017-04-29 08:43:43 +01:00
{
2017-05-03 23:01:47 +01:00
data = new byte [ 524288 ] ;
fs . Read ( data , 0 , 524288 ) ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
UpdateProgress2 ? . Invoke ( null , $"{position} of {fi.Length} bytes" , position , fi . Length ) ;
2017-04-29 08:43:43 +01:00
imgChkWorker . Update ( data ) ;
2017-05-03 23:01:47 +01:00
position + = 524288 ;
2017-04-29 08:43:43 +01:00
}
2017-12-30 00:32:21 +00:00
data = new byte [ fi . Length - position ] ;
2017-04-29 08:43:43 +01:00
fs . Read ( data , 0 , ( int ) ( fi . Length - position ) ) ;
2017-12-30 00:32:21 +00:00
UpdateProgress2 ? . Invoke ( null , $"{position} of {fi.Length} bytes" , position , fi . Length ) ;
2017-04-29 08:43:43 +01:00
imgChkWorker . Update ( data ) ;
fs . Close ( ) ;
2017-12-30 00:32:21 +00:00
#if DEBUG
2017-05-19 03:24:34 +01:00
stopwatch . Stop ( ) ;
2017-12-30 00:32:21 +00:00
Console . WriteLine ( "Core.AddMedia(): Took {0} seconds to hash image file" ,
stopwatch . Elapsed . TotalSeconds ) ;
#endif
2017-04-29 08:43:43 +01:00
List < ChecksumType > imgChecksums = imgChkWorker . End ( ) ;
2017-12-30 00:32:21 +00:00
UpdateProgress2 ? . Invoke ( null , null , 0 , 0 ) ;
2017-05-03 01:54:02 +01:00
2017-12-30 00:32:21 +00:00
long currentProgress = 0 ;
switch ( imageFormat . Info . XmlMediaType )
2017-04-29 08:43:43 +01:00
{
case XmlMediaType . OpticalDisc :
2017-12-30 00:32:21 +00:00
{
maxProgress = 4 + imageFormat . Info . ReadableMediaTags . Count + imageFormat . Tracks . Count ;
UpdateProgress ? . Invoke ( null , "Hashing image file" , 3 , maxProgress ) ;
sidecar . OpticalDisc = new OpticalDiscType [ 1 ] ;
sidecar . OpticalDisc [ 0 ] = new OpticalDiscType
2017-04-29 08:43:43 +01:00
{
2017-12-30 00:32:21 +00:00
Checksums = imgChecksums . ToArray ( ) ,
Image = new ImageType
2017-04-29 08:43:43 +01:00
{
2017-12-30 00:32:21 +00:00
format = imageFormat . Format ,
offset = 0 ,
offsetSpecified = true ,
Value = Path . GetFileName ( selectedFile )
} ,
Size = fi . Length ,
Sequence = new SequenceType { MediaTitle = imageFormat . Info . MediaTitle }
} ;
if ( imageFormat . Info . MediaSequence ! = 0 & & imageFormat . Info . LastMediaSequence ! = 0 )
{
sidecar . OpticalDisc [ 0 ] . Sequence . MediaSequence = imageFormat . Info . MediaSequence ;
sidecar . OpticalDisc [ 0 ] . Sequence . TotalMedia = imageFormat . Info . LastMediaSequence ;
}
else
{
sidecar . OpticalDisc [ 0 ] . Sequence . MediaSequence = 1 ;
sidecar . OpticalDisc [ 0 ] . Sequence . TotalMedia = 1 ;
}
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
MediaType dskType = imageFormat . Info . MediaType ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
currentProgress = 3 ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
#if DEBUG
stopwatch . Restart ( ) ;
#endif
foreach ( MediaTagType tagType in imageFormat . Info . ReadableMediaTags )
{
currentProgress + + ;
UpdateProgress ? . Invoke ( null , $"Hashing file containing {tagType}" , currentProgress ,
maxProgress ) ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
switch ( tagType )
{
case MediaTagType . CD_ATIP :
sidecar . OpticalDisc [ 0 ] . ATIP = new DumpType ( ) ;
sidecar . OpticalDisc [ 0 ] . ATIP . Checksums = Checksum
. GetChecksums ( imageFormat
. ReadDiskTag ( MediaTagType
. CD_ATIP ) )
. ToArray ( ) ;
sidecar . OpticalDisc [ 0 ] . ATIP . Size =
imageFormat . ReadDiskTag ( MediaTagType . CD_ATIP ) . Length ;
ATIP . CDATIP ? atip = ATIP . Decode ( imageFormat . ReadDiskTag ( MediaTagType . CD_ATIP ) ) ;
if ( atip . HasValue )
if ( atip . Value . DDCD )
dskType = atip . Value . DiscType ? MediaType . DDCDRW : MediaType . DDCDR ;
else
dskType = atip . Value . DiscType ? MediaType . CDRW : MediaType . CDR ;
break ;
case MediaTagType . DVD_BCA :
sidecar . OpticalDisc [ 0 ] . BCA = new DumpType ( ) ;
sidecar . OpticalDisc [ 0 ] . BCA . Checksums = Checksum
. GetChecksums ( imageFormat
. ReadDiskTag ( MediaTagType
. DVD_BCA ) )
. ToArray ( ) ;
sidecar . OpticalDisc [ 0 ] . BCA . Size =
imageFormat . ReadDiskTag ( MediaTagType . DVD_BCA ) . Length ;
break ;
case MediaTagType . BD_BCA :
sidecar . OpticalDisc [ 0 ] . BCA = new DumpType ( ) ;
sidecar . OpticalDisc [ 0 ] . BCA . Checksums = Checksum
. GetChecksums ( imageFormat
. ReadDiskTag ( MediaTagType
. BD_BCA ) )
. ToArray ( ) ;
sidecar . OpticalDisc [ 0 ] . BCA . Size =
imageFormat . ReadDiskTag ( MediaTagType . BD_BCA ) . Length ;
break ;
case MediaTagType . DVD_CMI :
sidecar . OpticalDisc [ 0 ] . CMI = new DumpType ( ) ;
CSS_CPRM . LeadInCopyright ? cmi =
CSS_CPRM . DecodeLeadInCopyright ( imageFormat . ReadDiskTag ( MediaTagType . DVD_CMI ) ) ;
if ( cmi . HasValue )
switch ( cmi . Value . CopyrightType )
2017-04-29 08:43:43 +01:00
{
2017-12-30 00:32:21 +00:00
case CopyrightType . AACS :
sidecar . OpticalDisc [ 0 ] . CopyProtection = "AACS" ;
break ;
case CopyrightType . CSS :
sidecar . OpticalDisc [ 0 ] . CopyProtection = "CSS" ;
break ;
case CopyrightType . CPRM :
sidecar . OpticalDisc [ 0 ] . CopyProtection = "CPRM" ;
break ;
2017-04-29 08:43:43 +01:00
}
2017-12-30 00:32:21 +00:00
sidecar . OpticalDisc [ 0 ] . CMI . Checksums = Checksum
. GetChecksums ( imageFormat
. ReadDiskTag ( MediaTagType
. DVD_CMI ) )
. ToArray ( ) ;
sidecar . OpticalDisc [ 0 ] . CMI . Size =
imageFormat . ReadDiskTag ( MediaTagType . DVD_CMI ) . Length ;
break ;
case MediaTagType . DVD_DMI :
sidecar . OpticalDisc [ 0 ] . DMI = new DumpType ( ) ;
sidecar . OpticalDisc [ 0 ] . DMI . Checksums = Checksum
. GetChecksums ( imageFormat
. ReadDiskTag ( MediaTagType
. DVD_DMI ) )
. ToArray ( ) ;
sidecar . OpticalDisc [ 0 ] . DMI . Size =
imageFormat . ReadDiskTag ( MediaTagType . DVD_DMI ) . Length ;
if ( DMI . IsXbox ( imageFormat . ReadDiskTag ( MediaTagType . DVD_DMI ) ) )
{
dskType = MediaType . XGD ;
sidecar . OpticalDisc [ 0 ] . Dimensions = new DimensionsType { Diameter = 120 } ;
}
else if ( DMI . IsXbox360 ( imageFormat . ReadDiskTag ( MediaTagType . DVD_DMI ) ) )
{
dskType = MediaType . XGD2 ;
sidecar . OpticalDisc [ 0 ] . Dimensions = new DimensionsType { Diameter = 120 } ;
}
break ;
case MediaTagType . DVD_PFI :
sidecar . OpticalDisc [ 0 ] . PFI = new DumpType ( ) ;
sidecar . OpticalDisc [ 0 ] . PFI . Checksums = Checksum
. GetChecksums ( imageFormat
. ReadDiskTag ( MediaTagType
. DVD_PFI ) )
. ToArray ( ) ;
sidecar . OpticalDisc [ 0 ] . PFI . Size =
imageFormat . ReadDiskTag ( MediaTagType . DVD_PFI ) . Length ;
PFI . PhysicalFormatInformation ? pfi =
PFI . Decode ( imageFormat . ReadDiskTag ( MediaTagType . DVD_PFI ) ) ;
if ( pfi . HasValue )
if ( dskType ! = MediaType . XGD & & dskType ! = MediaType . XGD2 & &
dskType ! = MediaType . XGD3 )
2017-04-29 08:43:43 +01:00
{
2017-12-30 00:32:21 +00:00
switch ( pfi . Value . DiskCategory )
2017-04-29 08:43:43 +01:00
{
2017-12-30 00:32:21 +00:00
case DiskCategory . DVDPR :
dskType = MediaType . DVDPR ;
break ;
case DiskCategory . DVDPRDL :
dskType = MediaType . DVDPRDL ;
break ;
case DiskCategory . DVDPRW :
dskType = MediaType . DVDPRW ;
break ;
case DiskCategory . DVDPRWDL :
dskType = MediaType . DVDPRWDL ;
break ;
case DiskCategory . DVDR :
dskType = MediaType . DVDR ;
break ;
case DiskCategory . DVDRAM :
dskType = MediaType . DVDRAM ;
break ;
case DiskCategory . DVDROM :
dskType = MediaType . DVDROM ;
break ;
case DiskCategory . DVDRW :
dskType = MediaType . DVDRW ;
break ;
case DiskCategory . HDDVDR :
dskType = MediaType . HDDVDR ;
break ;
case DiskCategory . HDDVDRAM :
dskType = MediaType . HDDVDRAM ;
break ;
case DiskCategory . HDDVDROM :
dskType = MediaType . HDDVDROM ;
2017-04-29 08:43:43 +01:00
break ;
2017-12-30 00:32:21 +00:00
case DiskCategory . HDDVDRW :
dskType = MediaType . HDDVDRW ;
2017-04-29 08:43:43 +01:00
break ;
2017-12-30 00:32:21 +00:00
case DiskCategory . Nintendo :
dskType = MediaType . GOD ;
break ;
case DiskCategory . UMD :
dskType = MediaType . UMD ;
2017-04-29 08:43:43 +01:00
break ;
}
2017-12-30 00:32:21 +00:00
if ( dskType = = MediaType . DVDR & & pfi . Value . PartVersion = = 6 )
dskType = MediaType . DVDRDL ;
if ( dskType = = MediaType . DVDRW & & pfi . Value . PartVersion = = 3 )
dskType = MediaType . DVDRWDL ;
if ( dskType = = MediaType . GOD & & pfi . Value . DiscSize = = DVDSize . OneTwenty )
dskType = MediaType . WOD ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
sidecar . OpticalDisc [ 0 ] . Dimensions = new DimensionsType ( ) ;
if ( dskType = = MediaType . UMD )
sidecar . OpticalDisc [ 0 ] . Dimensions . Diameter = 60 ;
else if ( pfi . Value . DiscSize = = DVDSize . Eighty )
sidecar . OpticalDisc [ 0 ] . Dimensions . Diameter = 80 ;
else if ( pfi . Value . DiscSize = = DVDSize . OneTwenty )
sidecar . OpticalDisc [ 0 ] . Dimensions . Diameter = 120 ;
2017-04-29 08:43:43 +01:00
}
2017-12-30 00:32:21 +00:00
break ;
case MediaTagType . CD_PMA :
sidecar . OpticalDisc [ 0 ] . PMA = new DumpType ( ) ;
sidecar . OpticalDisc [ 0 ] . PMA . Checksums = Checksum
. GetChecksums ( imageFormat
. ReadDiskTag ( MediaTagType
. CD_PMA ) )
. ToArray ( ) ;
sidecar . OpticalDisc [ 0 ] . PMA . Size =
imageFormat . ReadDiskTag ( MediaTagType . CD_PMA ) . Length ;
break ;
2017-04-29 08:43:43 +01:00
}
2017-12-30 00:32:21 +00:00
}
#if DEBUG
stopwatch . Stop ( ) ;
Console . WriteLine ( "Core.AddMedia(): Took {0} seconds to hash media tags" ,
stopwatch . Elapsed . TotalSeconds ) ;
#endif
try
{
List < Session > sessions = imageFormat . Sessions ;
sidecar . OpticalDisc [ 0 ] . Sessions = sessions ? . Count ? ? 1 ;
}
catch { sidecar . OpticalDisc [ 0 ] . Sessions = 1 ; }
List < Track > tracks = imageFormat . Tracks ;
List < TrackType > trksLst = null ;
if ( tracks ! = null )
{
sidecar . OpticalDisc [ 0 ] . Tracks = new int [ 1 ] ;
sidecar . OpticalDisc [ 0 ] . Tracks [ 0 ] = tracks . Count ;
trksLst = new List < TrackType > ( ) ;
}
foreach ( Track trk in tracks )
{
currentProgress + + ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
TrackType xmlTrk = new TrackType ( ) ;
switch ( trk . TrackType )
2017-04-29 08:43:43 +01:00
{
2017-12-30 00:32:21 +00:00
case DiscImageChef . DiscImages . TrackType . Audio :
xmlTrk . TrackType1 = TrackTypeTrackType . audio ;
break ;
case DiscImageChef . DiscImages . TrackType . CdMode2Form2 :
xmlTrk . TrackType1 = TrackTypeTrackType . m2f2 ;
break ;
case DiscImageChef . DiscImages . TrackType . CdMode2Formless :
xmlTrk . TrackType1 = TrackTypeTrackType . mode2 ;
break ;
case DiscImageChef . DiscImages . TrackType . CdMode2Form1 :
xmlTrk . TrackType1 = TrackTypeTrackType . m2f1 ;
break ;
case DiscImageChef . DiscImages . TrackType . CdMode1 :
xmlTrk . TrackType1 = TrackTypeTrackType . mode1 ;
break ;
case DiscImageChef . DiscImages . TrackType . Data :
switch ( sidecar . OpticalDisc [ 0 ] . DiscType )
{
case "BD" :
xmlTrk . TrackType1 = TrackTypeTrackType . bluray ;
break ;
case "DDCD" :
xmlTrk . TrackType1 = TrackTypeTrackType . ddcd ;
break ;
case "DVD" :
xmlTrk . TrackType1 = TrackTypeTrackType . dvd ;
break ;
case "HD DVD" :
xmlTrk . TrackType1 = TrackTypeTrackType . hddvd ;
break ;
default :
xmlTrk . TrackType1 = TrackTypeTrackType . mode1 ;
break ;
}
break ;
2017-04-29 08:43:43 +01:00
}
2017-12-30 00:32:21 +00:00
xmlTrk . Sequence = new TrackSequenceType
2017-04-29 08:43:43 +01:00
{
2017-12-30 00:32:21 +00:00
Session = trk . TrackSession ,
TrackNumber = ( int ) trk . TrackSequence
} ;
xmlTrk . StartSector = ( long ) trk . TrackStartSector ;
xmlTrk . EndSector = ( long ) trk . TrackEndSector ;
if ( trk . Indexes ! = null & & trk . Indexes . ContainsKey ( 0 ) )
if ( trk . Indexes . TryGetValue ( 0 , out ulong idx0 ) )
xmlTrk . StartSector = ( long ) idx0 ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
switch ( sidecar . OpticalDisc [ 0 ] . DiscType )
2017-04-29 08:43:43 +01:00
{
2017-12-30 00:32:21 +00:00
case "CD" :
case "GD" :
xmlTrk . StartMSF = LbaToMsf ( xmlTrk . StartSector ) ;
xmlTrk . EndMSF = LbaToMsf ( xmlTrk . EndSector ) ;
break ;
case "DDCD" :
xmlTrk . StartMSF = DdcdLbaToMsf ( xmlTrk . StartSector ) ;
xmlTrk . EndMSF = DdcdLbaToMsf ( xmlTrk . EndSector ) ;
break ;
2017-04-29 08:43:43 +01:00
}
2017-12-30 00:32:21 +00:00
xmlTrk . Image = new ImageType { Value = Path . GetFileName ( trk . TrackFile ) } ;
if ( trk . TrackFileOffset > 0 )
2017-04-29 08:43:43 +01:00
{
2017-12-30 00:32:21 +00:00
xmlTrk . Image . offset = ( long ) trk . TrackFileOffset ;
xmlTrk . Image . offsetSpecified = true ;
}
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
xmlTrk . Image . format = trk . TrackFileType ;
xmlTrk . Size =
( xmlTrk . EndSector - xmlTrk . StartSector + 1 ) * trk . TrackRawBytesPerSector ;
xmlTrk . BytesPerSector = trk . TrackBytesPerSector ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
const uint SECTORS_TO_READ = 512 ;
ulong sectors = ( ulong ) ( xmlTrk . EndSector - xmlTrk . StartSector + 1 ) ;
ulong doneSectors = 0 ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
// If there is only one track, and it's the same as the image file (e.g. ".iso" files), don't re-checksum.
if ( imageFormat . Id = = new Guid ( "12345678-AAAA-BBBB-CCCC-123456789000" ) )
xmlTrk . Checksums = sidecar . OpticalDisc [ 0 ] . Checksums ;
else
{
UpdateProgress ? . Invoke ( null , $"Hashing track {trk.TrackSequence}" , currentProgress ,
maxProgress ) ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
Checksum trkChkWorker = new Checksum ( ) ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
#if DEBUG
stopwatch . Restart ( ) ;
#endif
while ( doneSectors < sectors )
{
byte [ ] sector ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
if ( sectors - doneSectors > = SECTORS_TO_READ )
{
sector = imageFormat . ReadSectorsLong ( doneSectors , SECTORS_TO_READ ,
( uint ) xmlTrk . Sequence . TrackNumber ) ;
UpdateProgress2 ? . Invoke ( null , $"Sector {doneSectors} of {sectors}" ,
( long ) doneSectors , ( long ) sectors ) ;
doneSectors + = SECTORS_TO_READ ;
}
else
{
sector = imageFormat . ReadSectorsLong ( doneSectors , ( uint ) ( sectors - doneSectors ) ,
( uint ) xmlTrk . Sequence . TrackNumber ) ;
UpdateProgress2 ? . Invoke ( null , $"Sector {doneSectors} of {sectors}" ,
( long ) doneSectors , ( long ) sectors ) ;
doneSectors + = sectors - doneSectors ;
}
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
trkChkWorker . Update ( sector ) ;
2017-06-20 07:20:39 +01:00
}
2017-12-30 00:32:21 +00:00
List < ChecksumType > trkChecksums = trkChkWorker . End ( ) ;
#if DEBUG
stopwatch . Stop ( ) ;
Console . WriteLine ( "Core.AddMedia(): Took {0} seconds to hash track {1}" ,
stopwatch . Elapsed . TotalSeconds , trk . TrackSequence ) ;
#endif
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
xmlTrk . Checksums = trkChecksums . ToArray ( ) ;
}
2017-06-20 07:20:39 +01:00
2017-12-30 00:32:21 +00:00
UpdateProgress2 ? . Invoke ( null , null , 0 , 0 ) ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
if ( trk . TrackSubchannelType ! = TrackSubchannelType . None )
{
UpdateProgress ? . Invoke ( null , $"Hashing subchannel of track {trk.TrackSequence}" ,
currentProgress , maxProgress ) ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
xmlTrk . SubChannel = new SubChannelType { Image = new ImageType ( ) } ;
switch ( trk . TrackSubchannelType )
{
case TrackSubchannelType . Packed :
case TrackSubchannelType . PackedInterleaved :
xmlTrk . SubChannel . Image . format = "rw" ;
break ;
case TrackSubchannelType . Raw :
case TrackSubchannelType . RawInterleaved :
xmlTrk . SubChannel . Image . format = "rw_raw" ;
break ;
case TrackSubchannelType . Q16 :
case TrackSubchannelType . Q16Interleaved :
xmlTrk . SubChannel . Image . format = "q16" ;
break ;
2017-06-20 07:20:39 +01:00
}
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
if ( trk . TrackFileOffset > 0 )
2017-04-29 08:43:43 +01:00
{
2017-12-30 00:32:21 +00:00
xmlTrk . SubChannel . Image . offset = ( long ) trk . TrackSubchannelOffset ;
xmlTrk . SubChannel . Image . offsetSpecified = true ;
}
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
xmlTrk . SubChannel . Image . Value = trk . TrackSubchannelFile ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
// TODO: Packed subchannel has different size?
xmlTrk . SubChannel . Size = ( xmlTrk . EndSector - xmlTrk . StartSector + 1 ) * 96 ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
Checksum subChkWorker = new Checksum ( ) ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
sectors = ( ulong ) ( xmlTrk . EndSector - xmlTrk . StartSector + 1 ) ;
doneSectors = 0 ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
#if DEBUG
stopwatch . Restart ( ) ;
#endif
while ( doneSectors < sectors )
{
byte [ ] sector ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
if ( sectors - doneSectors > = SECTORS_TO_READ )
2017-04-29 08:43:43 +01:00
{
2017-12-30 00:32:21 +00:00
sector = imageFormat . ReadSectorsTag ( doneSectors , SECTORS_TO_READ ,
( uint ) xmlTrk . Sequence . TrackNumber ,
SectorTagType . CdSectorSubchannel ) ;
UpdateProgress2 ? . Invoke ( null , $"Sector {doneSectors} of {sectors}" , position ,
fi . Length ) ;
doneSectors + = SECTORS_TO_READ ;
}
else
{
sector = imageFormat . ReadSectorsTag ( doneSectors , ( uint ) ( sectors - doneSectors ) ,
( uint ) xmlTrk . Sequence . TrackNumber ,
SectorTagType . CdSectorSubchannel ) ;
UpdateProgress2 ? . Invoke ( null , $"Sector {doneSectors} of {sectors}" , position ,
fi . Length ) ;
doneSectors + = sectors - doneSectors ;
2017-04-29 08:43:43 +01:00
}
2017-12-30 00:32:21 +00:00
subChkWorker . Update ( sector ) ;
2017-04-29 08:43:43 +01:00
}
2017-12-30 00:32:21 +00:00
List < ChecksumType > subChecksums = subChkWorker . End ( ) ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
xmlTrk . SubChannel . Checksums = subChecksums . ToArray ( ) ;
#if DEBUG
stopwatch . Stop ( ) ;
Console . WriteLine ( "Core.AddMedia(): Took {0} seconds to hash subchannel of track {1}" ,
stopwatch . Elapsed . TotalSeconds , trk . TrackSequence ) ;
#endif
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
UpdateProgress2 ? . Invoke ( null , null , 0 , 0 ) ;
}
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
UpdateProgress ? . Invoke ( null , "Checking filesystems" , maxProgress - 1 , maxProgress ) ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
#if DEBUG
stopwatch . Restart ( ) ;
#endif
List < Partition > partitions = new List < Partition > ( ) ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
foreach ( IPartition partplugin in plugins . PartPluginsList . Values )
if ( partplugin . GetInformation ( imageFormat , out List < Partition > _partitions , 0 )
) // TODO: Subpartitions
partitions . AddRange ( _partitions ) ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
xmlTrk . FileSystemInformation = new PartitionType [ 1 ] ;
if ( partitions . Count > 0 )
{
xmlTrk . FileSystemInformation = new PartitionType [ partitions . Count ] ;
for ( int i = 0 ; i < partitions . Count ; i + + )
2017-04-29 08:43:43 +01:00
{
2017-12-30 00:32:21 +00:00
xmlTrk . FileSystemInformation [ i ] = new PartitionType
2017-12-29 19:31:26 +00:00
{
2017-12-30 00:32:21 +00:00
Description = partitions [ i ] . Description ,
EndSector = ( int ) partitions [ i ] . End ,
Name = partitions [ i ] . Name ,
Sequence = ( int ) partitions [ i ] . Sequence ,
StartSector = ( int ) partitions [ i ] . Start ,
Type = partitions [ i ] . Type
2017-12-29 19:31:26 +00:00
} ;
2017-04-29 08:43:43 +01:00
List < FileSystemType > lstFs = new List < FileSystemType > ( ) ;
2017-12-30 00:32:21 +00:00
foreach ( IFilesystem plugin in plugins . PluginsList . Values )
2017-04-29 08:43:43 +01:00
try
{
2017-12-30 00:32:21 +00:00
if ( ! plugin . Identify ( imageFormat , partitions [ i ] ) ) continue ;
plugin . GetInformation ( imageFormat , partitions [ i ] , out _ , null ) ;
lstFs . Add ( plugin . XmlFsType ) ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
switch ( plugin . XmlFsType . Type )
{
case "Opera" :
2017-04-29 08:43:43 +01:00
dskType = MediaType . ThreeDO ;
2017-12-30 00:32:21 +00:00
break ;
case "PC Engine filesystem" :
2017-04-29 08:43:43 +01:00
dskType = MediaType . SuperCDROM2 ;
2017-12-30 00:32:21 +00:00
break ;
case "Nintendo Wii filesystem" :
2017-04-29 08:43:43 +01:00
dskType = MediaType . WOD ;
2017-12-30 00:32:21 +00:00
break ;
case "Nintendo Gamecube filesystem" :
2017-04-29 08:43:43 +01:00
dskType = MediaType . GOD ;
2017-12-30 00:32:21 +00:00
break ;
2017-04-29 08:43:43 +01:00
}
}
2017-12-30 00:32:21 +00:00
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
2017-04-29 08:43:43 +01:00
catch
2017-12-30 00:32:21 +00:00
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
2017-04-29 08:43:43 +01:00
{
//DicConsole.DebugWriteLine("Create-sidecar command", "Plugin {0} crashed", _plugin.Name);
}
2017-12-30 00:32:21 +00:00
if ( lstFs . Count > 0 ) xmlTrk . FileSystemInformation [ i ] . FileSystems = lstFs . ToArray ( ) ;
2017-04-29 08:43:43 +01:00
}
}
2017-12-30 00:32:21 +00:00
else
{
xmlTrk . FileSystemInformation [ 0 ] = new PartitionType
{
EndSector = ( int ) xmlTrk . EndSector ,
StartSector = ( int ) xmlTrk . StartSector
} ;
Partition xmlPart = new Partition
{
Start = ( ulong ) xmlTrk . StartSector ,
Length = ( ulong ) ( xmlTrk . EndSector - xmlTrk . StartSector + 1 )
} ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
List < FileSystemType > lstFs = new List < FileSystemType > ( ) ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
foreach ( IFilesystem _plugin in plugins . PluginsList . Values )
try
{
if ( ! _plugin . Identify ( imageFormat , xmlPart ) ) continue ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
_plugin . GetInformation ( imageFormat , xmlPart , out _ , null ) ;
lstFs . Add ( _plugin . XmlFsType ) ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
switch ( _plugin . XmlFsType . Type )
{
case "Opera" :
dskType = MediaType . ThreeDO ;
break ;
case "PC Engine filesystem" :
dskType = MediaType . SuperCDROM2 ;
break ;
case "Nintendo Wii filesystem" :
dskType = MediaType . WOD ;
break ;
case "Nintendo Gamecube filesystem" :
dskType = MediaType . GOD ;
break ;
}
}
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
catch
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
{
//DicConsole.DebugWriteLine("Create-sidecar command", "Plugin {0} crashed", _plugin.Name);
}
if ( lstFs . Count > 0 ) xmlTrk . FileSystemInformation [ 0 ] . FileSystems = lstFs . ToArray ( ) ;
2017-04-29 08:43:43 +01:00
}
2017-12-30 00:32:21 +00:00
#if DEBUG
stopwatch . Stop ( ) ;
Console . WriteLine ( "Core.AddMedia(): Took {0} seconds to check all filesystems on track {1}" ,
stopwatch . Elapsed . TotalSeconds , trk . TrackSequence ) ;
#endif
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
trksLst . Add ( xmlTrk ) ;
2017-04-29 08:43:43 +01:00
}
2017-12-30 00:32:21 +00:00
UpdateProgress ? . Invoke ( null , "Finishing" , maxProgress , maxProgress ) ;
if ( trksLst ! = null ) sidecar . OpticalDisc [ 0 ] . Track = trksLst . ToArray ( ) ;
DiscImageChef . Metadata . MediaType . MediaTypeToString ( dskType , out string dscType ,
out string dscSubType ) ;
sidecar . OpticalDisc [ 0 ] . DiscType = dscType ;
sidecar . OpticalDisc [ 0 ] . DiscSubType = dscSubType ;
if ( ! string . IsNullOrEmpty ( imageFormat . Info . DriveManufacturer ) | |
! string . IsNullOrEmpty ( imageFormat . Info . DriveModel ) | |
! string . IsNullOrEmpty ( imageFormat . Info . DriveFirmwareRevision ) | |
! string . IsNullOrEmpty ( imageFormat . Info . DriveSerialNumber ) )
2017-04-29 08:43:43 +01:00
{
2017-12-30 00:32:21 +00:00
sidecar . OpticalDisc [ 0 ] . DumpHardwareArray = new DumpHardwareType [ 1 ] ;
sidecar . OpticalDisc [ 0 ] . DumpHardwareArray [ 0 ] . Extents = new ExtentType [ 0 ] ;
sidecar . OpticalDisc [ 0 ] . DumpHardwareArray [ 0 ] . Extents [ 0 ] . Start = 0 ;
sidecar . OpticalDisc [ 0 ] . DumpHardwareArray [ 0 ] . Extents [ 0 ] . End = imageFormat . Info . Sectors ;
sidecar . OpticalDisc [ 0 ] . DumpHardwareArray [ 0 ] . Manufacturer =
imageFormat . Info . DriveManufacturer ;
sidecar . OpticalDisc [ 0 ] . DumpHardwareArray [ 0 ] . Model = imageFormat . Info . DriveModel ;
sidecar . OpticalDisc [ 0 ] . DumpHardwareArray [ 0 ] . Firmware =
imageFormat . Info . DriveFirmwareRevision ;
sidecar . OpticalDisc [ 0 ] . DumpHardwareArray [ 0 ] . Serial = imageFormat . Info . DriveSerialNumber ;
sidecar . OpticalDisc [ 0 ] . DumpHardwareArray [ 0 ] . Software = new SoftwareType
2017-04-29 08:43:43 +01:00
{
2017-12-30 00:32:21 +00:00
Name = imageFormat . Info . Application ,
Version = imageFormat . Info . ApplicationVersion
} ;
}
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
Context . WorkingDisc = sidecar . OpticalDisc [ 0 ] ;
Finished ? . Invoke ( ) ;
return ;
}
case XmlMediaType . BlockMedia :
{
maxProgress = 3 + imageFormat . Info . ReadableMediaTags . Count ;
UpdateProgress ? . Invoke ( null , "Hashing image file" , 3 , maxProgress ) ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
sidecar . BlockMedia = new BlockMediaType [ 1 ] ;
sidecar . BlockMedia [ 0 ] = new BlockMediaType
{
Checksums = imgChecksums . ToArray ( ) ,
Image = new ImageType
2017-04-29 08:43:43 +01:00
{
2017-12-30 00:32:21 +00:00
format = imageFormat . Format ,
offset = 0 ,
offsetSpecified = true ,
Value = Path . GetFileName ( selectedFile )
} ,
Size = fi . Length ,
Sequence = new SequenceType { MediaTitle = imageFormat . Info . MediaTitle }
} ;
if ( imageFormat . Info . MediaSequence ! = 0 & & imageFormat . Info . LastMediaSequence ! = 0 )
{
sidecar . BlockMedia [ 0 ] . Sequence . MediaSequence = imageFormat . Info . MediaSequence ;
sidecar . BlockMedia [ 0 ] . Sequence . TotalMedia = imageFormat . Info . LastMediaSequence ;
}
else
{
sidecar . BlockMedia [ 0 ] . Sequence . MediaSequence = 1 ;
sidecar . BlockMedia [ 0 ] . Sequence . TotalMedia = 1 ;
}
2017-05-03 01:54:02 +01:00
2017-12-30 00:32:21 +00:00
currentProgress = 3 ;
#if DEBUG
stopwatch . Restart ( ) ;
#endif
foreach ( MediaTagType tagType in imageFormat . Info . ReadableMediaTags )
{
currentProgress + + ;
UpdateProgress ? . Invoke ( null , $"Hashing file containing {tagType}" , currentProgress ,
maxProgress ) ;
switch ( tagType )
{
case MediaTagType . ATAPI_IDENTIFY :
sidecar . BlockMedia [ 0 ] . ATA = new ATAType ( ) ;
sidecar . BlockMedia [ 0 ] . ATA . Identify = new DumpType ( ) ;
sidecar . BlockMedia [ 0 ] . ATA . Identify . Checksums = Checksum
. GetChecksums ( imageFormat
. ReadDiskTag ( MediaTagType
. ATAPI_IDENTIFY ) )
. ToArray ( ) ;
sidecar . BlockMedia [ 0 ] . ATA . Identify . Size =
imageFormat . ReadDiskTag ( MediaTagType . ATAPI_IDENTIFY ) . Length ;
break ;
case MediaTagType . ATA_IDENTIFY :
sidecar . BlockMedia [ 0 ] . ATA = new ATAType ( ) ;
sidecar . BlockMedia [ 0 ] . ATA . Identify = new DumpType ( ) ;
sidecar . BlockMedia [ 0 ] . ATA . Identify . Checksums = Checksum
. GetChecksums ( imageFormat
. ReadDiskTag ( MediaTagType
. ATA_IDENTIFY ) )
. ToArray ( ) ;
sidecar . BlockMedia [ 0 ] . ATA . Identify . Size =
imageFormat . ReadDiskTag ( MediaTagType . ATA_IDENTIFY ) . Length ;
break ;
case MediaTagType . PCMCIA_CIS :
byte [ ] cis =
imageFormat . ReadDiskTag ( MediaTagType . PCMCIA_CIS ) ;
sidecar . BlockMedia [ 0 ] . PCMCIA = new PCMCIAType ( ) ;
sidecar . BlockMedia [ 0 ] . PCMCIA . CIS = new DumpType ( ) ;
sidecar . BlockMedia [ 0 ] . PCMCIA . CIS . Checksums = Checksum . GetChecksums ( cis ) . ToArray ( ) ;
sidecar . BlockMedia [ 0 ] . PCMCIA . CIS . Size = cis . Length ;
Tuple [ ] tuples = CIS . GetTuples ( cis ) ;
if ( tuples ! = null )
foreach ( Tuple tuple in tuples )
if ( tuple . Code = = TupleCodes . CISTPL_MANFID )
2017-04-29 08:43:43 +01:00
{
2017-12-30 00:32:21 +00:00
ManufacturerIdentificationTuple manfid =
CIS . DecodeManufacturerIdentificationTuple ( tuple ) ;
if ( manfid ! = null )
2017-04-29 08:43:43 +01:00
{
2017-12-30 00:32:21 +00:00
sidecar . BlockMedia [ 0 ] . PCMCIA . ManufacturerCode =
manfid . ManufacturerID ;
sidecar . BlockMedia [ 0 ] . PCMCIA . CardCode =
manfid . CardID ;
sidecar . BlockMedia [ 0 ] . PCMCIA . ManufacturerCodeSpecified = true ;
sidecar . BlockMedia [ 0 ] . PCMCIA . CardCodeSpecified = true ;
2017-04-29 08:43:43 +01:00
}
2017-12-30 00:32:21 +00:00
}
else if ( tuple . Code = = TupleCodes . CISTPL_VERS_1 )
{
Level1VersionTuple vers = CIS . DecodeLevel1VersionTuple ( tuple ) ;
if ( vers ! = null )
2017-04-29 08:43:43 +01:00
{
2017-12-30 00:32:21 +00:00
sidecar . BlockMedia [ 0 ] . PCMCIA . Manufacturer = vers . Manufacturer ;
sidecar . BlockMedia [ 0 ] . PCMCIA . ProductName = vers . Product ;
sidecar . BlockMedia [ 0 ] . PCMCIA . Compliance =
$"{vers.MajorVersion}.{vers.MinorVersion}" ;
sidecar . BlockMedia [ 0 ] . PCMCIA . AdditionalInformation =
vers . AdditionalInformation ;
2017-04-29 08:43:43 +01:00
}
}
2017-12-30 00:32:21 +00:00
break ;
case MediaTagType . SCSI_INQUIRY :
sidecar . BlockMedia [ 0 ] . SCSI = new SCSIType ( ) ;
sidecar . BlockMedia [ 0 ] . SCSI . Inquiry = new DumpType ( ) ;
sidecar . BlockMedia [ 0 ] . SCSI . Inquiry . Checksums = Checksum
. GetChecksums ( imageFormat
. ReadDiskTag ( MediaTagType
. SCSI_INQUIRY ) )
. ToArray ( ) ;
sidecar . BlockMedia [ 0 ] . SCSI . Inquiry . Size =
imageFormat . ReadDiskTag ( MediaTagType . SCSI_INQUIRY ) . Length ;
break ;
case MediaTagType . SD_CID :
if ( sidecar . BlockMedia [ 0 ] . SecureDigital = = null )
sidecar . BlockMedia [ 0 ] . SecureDigital = new SecureDigitalType ( ) ;
sidecar . BlockMedia [ 0 ] . SecureDigital . CID = new DumpType ( ) ;
sidecar . BlockMedia [ 0 ] . SecureDigital . CID . Checksums = Checksum
. GetChecksums ( imageFormat
. ReadDiskTag ( MediaTagType
. SD_CID ) )
. ToArray ( ) ;
sidecar . BlockMedia [ 0 ] . SecureDigital . CID . Size =
imageFormat . ReadDiskTag ( MediaTagType . SD_CID ) . Length ;
break ;
case MediaTagType . SD_CSD :
if ( sidecar . BlockMedia [ 0 ] . SecureDigital = = null )
sidecar . BlockMedia [ 0 ] . SecureDigital = new SecureDigitalType ( ) ;
sidecar . BlockMedia [ 0 ] . SecureDigital . CSD = new DumpType ( ) ;
sidecar . BlockMedia [ 0 ] . SecureDigital . CSD . Checksums = Checksum
. GetChecksums ( imageFormat
. ReadDiskTag ( MediaTagType
. SD_CSD ) )
. ToArray ( ) ;
sidecar . BlockMedia [ 0 ] . SecureDigital . CSD . Size =
imageFormat . ReadDiskTag ( MediaTagType . SD_CSD ) . Length ;
break ;
case MediaTagType . MMC_ExtendedCSD :
if ( sidecar . BlockMedia [ 0 ] . SecureDigital = = null )
sidecar . BlockMedia [ 0 ] . SecureDigital =
new SecureDigitalType ( ) ;
sidecar . BlockMedia [ 0 ] . MultiMediaCard . ExtendedCSD = new DumpType ( ) ;
sidecar . BlockMedia [ 0 ] . MultiMediaCard . ExtendedCSD . Checksums = Checksum
. GetChecksums ( imageFormat
. ReadDiskTag ( MediaTagType
. MMC_ExtendedCSD ) )
. ToArray ( ) ;
sidecar . BlockMedia [ 0 ] . MultiMediaCard . ExtendedCSD . Size =
imageFormat . ReadDiskTag ( MediaTagType . MMC_ExtendedCSD ) . Length ;
break ;
2017-06-20 07:20:39 +01:00
}
2017-12-30 00:32:21 +00:00
}
#if DEBUG
stopwatch . Stop ( ) ;
Console . WriteLine ( "Core.AddMedia(): Took {0} seconds to hash media tags" ,
stopwatch . Elapsed . TotalSeconds ) ;
#endif
// If there is only one track, and it's the same as the image file (e.g. ".iso" files), don't re-checksum.
if ( imageFormat . Id = = new Guid ( "12345678-AAAA-BBBB-CCCC-123456789000" ) )
sidecar . BlockMedia [ 0 ] . ContentChecksums = sidecar . BlockMedia [ 0 ] . Checksums ;
else
{
const uint SECTORS_TO_READ = 512 ;
ulong sectors = imageFormat . Info . Sectors ;
ulong doneSectors = 0 ;
2017-06-20 07:20:39 +01:00
2017-12-30 00:32:21 +00:00
UpdateProgress ? . Invoke ( null , "Hashing media contents" , currentProgress , maxProgress ) ;
2017-06-20 07:20:39 +01:00
2017-12-30 00:32:21 +00:00
Checksum cntChkWorker = new Checksum ( ) ;
2017-06-20 07:20:39 +01:00
2017-12-30 00:32:21 +00:00
#if DEBUG
stopwatch . Restart ( ) ;
#endif
while ( doneSectors < sectors )
{
byte [ ] sector ;
2017-06-20 07:20:39 +01:00
2017-12-30 00:32:21 +00:00
if ( sectors - doneSectors > = SECTORS_TO_READ )
2017-06-20 07:20:39 +01:00
{
2017-12-30 00:32:21 +00:00
sector = imageFormat . ReadSectors ( doneSectors , SECTORS_TO_READ ) ;
UpdateProgress2 ? . Invoke ( null , $"Sector {doneSectors} of {sectors}" ,
( long ) doneSectors , ( long ) sectors ) ;
doneSectors + = SECTORS_TO_READ ;
}
else
{
sector = imageFormat . ReadSectors ( doneSectors , ( uint ) ( sectors - doneSectors ) ) ;
UpdateProgress2 ? . Invoke ( null , $"Sector {doneSectors} of {sectors}" ,
( long ) doneSectors , ( long ) sectors ) ;
doneSectors + = sectors - doneSectors ;
2017-06-20 07:20:39 +01:00
}
2017-12-30 00:32:21 +00:00
cntChkWorker . Update ( sector ) ;
2017-06-20 07:20:39 +01:00
}
2017-12-30 00:32:21 +00:00
List < ChecksumType > cntChecksums = cntChkWorker . End ( ) ;
#if DEBUG
stopwatch . Stop ( ) ;
Console . WriteLine ( "Core.AddMedia(): Took {0} seconds to hash media contents" ,
stopwatch . Elapsed . TotalSeconds ) ;
#endif
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
sidecar . BlockMedia [ 0 ] . ContentChecksums = cntChecksums . ToArray ( ) ;
}
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
DiscImageChef . Metadata . MediaType . MediaTypeToString ( imageFormat . Info . MediaType ,
out string dskType , out string dskSubType ) ;
sidecar . BlockMedia [ 0 ] . DiskType = dskType ;
sidecar . BlockMedia [ 0 ] . DiskSubType = dskSubType ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
sidecar . BlockMedia [ 0 ] . Dimensions =
Dimensions . DimensionsFromMediaType ( imageFormat . Info . MediaType ) ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
sidecar . BlockMedia [ 0 ] . LogicalBlocks = ( long ) imageFormat . Info . Sectors ;
sidecar . BlockMedia [ 0 ] . LogicalBlockSize = ( int ) imageFormat . Info . SectorSize ;
// TODO: Detect it
sidecar . BlockMedia [ 0 ] . PhysicalBlockSize = ( int ) imageFormat . Info . SectorSize ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
UpdateProgress ? . Invoke ( null , "Checking filesystems" , maxProgress - 1 , maxProgress ) ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
#if DEBUG
stopwatch . Restart ( ) ;
#endif
List < Partition > partitions = new List < Partition > ( ) ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
foreach ( IPartition partplugin in plugins . PartPluginsList . Values )
{
if ( ! partplugin . GetInformation ( imageFormat , out partitions , 0 ) ) continue ;
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
break ;
}
2017-04-29 08:43:43 +01:00
2017-12-30 00:32:21 +00:00
sidecar . BlockMedia [ 0 ] . FileSystemInformation = new PartitionType [ 1 ] ;
if ( partitions . Count > 0 )
{
sidecar . BlockMedia [ 0 ] . FileSystemInformation = new PartitionType [ partitions . Count ] ;
for ( int i = 0 ; i < partitions . Count ; i + + )
2017-04-29 08:43:43 +01:00
{
2017-12-30 00:32:21 +00:00
sidecar . BlockMedia [ 0 ] . FileSystemInformation [ i ] = new PartitionType
2017-12-29 19:31:26 +00:00
{
2017-12-30 00:32:21 +00:00
Description = partitions [ i ] . Description ,
EndSector = ( int ) partitions [ i ] . End ,
Name = partitions [ i ] . Name ,
Sequence = ( int ) partitions [ i ] . Sequence ,
StartSector = ( int ) partitions [ i ] . Start ,
Type = partitions [ i ] . Type
2017-12-29 19:31:26 +00:00
} ;
2017-04-29 08:43:43 +01:00
List < FileSystemType > lstFs = new List < FileSystemType > ( ) ;
2017-12-30 00:32:21 +00:00
foreach ( IFilesystem plugin in plugins . PluginsList . Values )
2017-04-29 08:43:43 +01:00
try
{
2017-12-30 00:32:21 +00:00
if ( ! plugin . Identify ( imageFormat , partitions [ i ] ) ) continue ;
plugin . GetInformation ( imageFormat , partitions [ i ] , out _ , null ) ;
lstFs . Add ( plugin . XmlFsType ) ;
2017-04-29 08:43:43 +01:00
}
2017-12-30 00:32:21 +00:00
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
2017-04-29 08:43:43 +01:00
catch
2017-12-30 00:32:21 +00:00
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
2017-04-29 08:43:43 +01:00
{
//DicConsole.DebugWriteLine("Create-sidecar command", "Plugin {0} crashed", _plugin.Name);
}
if ( lstFs . Count > 0 )
2017-12-30 00:32:21 +00:00
sidecar . BlockMedia [ 0 ] . FileSystemInformation [ i ] . FileSystems = lstFs . ToArray ( ) ;
2017-04-29 08:43:43 +01:00
}
}
2017-12-30 00:32:21 +00:00
else
2017-04-29 08:43:43 +01:00
{
2017-12-30 00:32:21 +00:00
sidecar . BlockMedia [ 0 ] . FileSystemInformation [ 0 ] = new PartitionType
{
StartSector = 0 ,
EndSector = ( int ) ( imageFormat . Info . Sectors - 1 )
} ;
Partition wholePart = new Partition { Start = 0 , Length = imageFormat . Info . Sectors } ;
List < FileSystemType > lstFs = new List < FileSystemType > ( ) ;
foreach ( IFilesystem _plugin in plugins . PluginsList . Values )
try
{
if ( ! _plugin . Identify ( imageFormat , wholePart ) ) continue ;
_plugin . GetInformation ( imageFormat , wholePart , out _ , null ) ;
lstFs . Add ( _plugin . XmlFsType ) ;
}
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
catch
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
{
//DicConsole.DebugWriteLine("Create-sidecar command", "Plugin {0} crashed", _plugin.Name);
}
if ( lstFs . Count > 0 )
sidecar . BlockMedia [ 0 ] . FileSystemInformation [ 0 ] . FileSystems = lstFs . ToArray ( ) ;
2017-04-29 08:43:43 +01:00
}
2017-12-30 00:32:21 +00:00
#if DEBUG
stopwatch . Stop ( ) ;
Console . WriteLine ( "Core.AddMedia(): Took {0} seconds to check all filesystems" ,
stopwatch . Elapsed . TotalSeconds ) ;
#endif
// TODO: Implement support for getting CHS
UpdateProgress ? . Invoke ( null , "Finishing" , maxProgress , maxProgress ) ;
Context . WorkingDisk = sidecar . BlockMedia [ 0 ] ;
Finished ? . Invoke ( ) ;
return ;
}
case XmlMediaType . LinearMedia :
{
Failed ? . Invoke ( "Linear media not yet supported." ) ;
return ;
}
2017-04-29 08:43:43 +01:00
case XmlMediaType . AudioMedia :
2017-12-30 00:32:21 +00:00
{
Failed ? . Invoke ( "Audio media not yet supported." ) ;
return ;
}
2017-04-29 08:43:43 +01:00
}
2017-12-30 00:32:21 +00:00
Failed ? . Invoke ( "Should've not arrived here." ) ;
2017-04-29 08:43:43 +01:00
}
catch ( Exception ex )
{
2017-12-30 00:32:21 +00:00
Failed ? . Invoke ( $"Error reading file: {ex.Message}\n{ex.StackTrace}" ) ;
#if DEBUG
2017-06-13 18:21:12 +01:00
Console . WriteLine ( "Exception {0}\n{1}" , ex . Message , ex . InnerException ) ;
2017-12-30 00:32:21 +00:00
#endif
2017-04-29 08:43:43 +01:00
}
}
static string LbaToMsf ( long lba )
{
long m , s , f ;
if ( lba > = - 150 )
{
2017-12-30 00:32:21 +00:00
m = ( lba + 150 ) / ( 75 * 60 ) ;
lba - = m * ( 75 * 60 ) ;
s = ( lba + 150 ) / 75 ;
lba - = s * 75 ;
f = lba + 150 ;
2017-04-29 08:43:43 +01:00
}
else
{
2017-12-30 00:32:21 +00:00
m = ( lba + 450150 ) / ( 75 * 60 ) ;
lba - = m * ( 75 * 60 ) ;
s = ( lba + 450150 ) / 75 ;
lba - = s * 75 ;
f = lba + 450150 ;
2017-04-29 08:43:43 +01:00
}
2017-12-30 00:32:21 +00:00
return $"{m}:{s:D2}:{f:D2}" ;
2017-04-29 07:04:03 +01:00
}
2017-04-29 08:43:43 +01:00
static string DdcdLbaToMsf ( long lba )
2017-04-29 07:04:03 +01:00
{
2017-04-29 08:43:43 +01:00
long h , m , s , f ;
if ( lba > = - 150 )
{
2017-12-30 00:32:21 +00:00
h = ( lba + 150 ) / ( 75 * 60 * 60 ) ;
lba - = h * ( 75 * 60 * 60 ) ;
m = ( lba + 150 ) / ( 75 * 60 ) ;
lba - = m * ( 75 * 60 ) ;
s = ( lba + 150 ) / 75 ;
lba - = s * 75 ;
f = lba + 150 ;
2017-04-29 08:43:43 +01:00
}
else
{
2017-12-30 00:32:21 +00:00
h = ( lba + 450150 * 2 ) / ( 75 * 60 * 60 ) ;
lba - = h * ( 75 * 60 * 60 ) ;
m = ( lba + 450150 * 2 ) / ( 75 * 60 ) ;
lba - = m * ( 75 * 60 ) ;
s = ( lba + 450150 * 2 ) / 75 ;
lba - = s * 75 ;
f = lba + 450150 * 2 ;
2017-04-29 08:43:43 +01:00
}
return string . Format ( "{3}:{0:D2}:{1:D2}:{2:D2}" , m , s , f , h ) ;
2017-04-29 07:04:03 +01:00
}
}
2017-12-30 00:32:21 +00:00
}