2017-08-08 13:40:32 +01:00
|
|
|
|
// /***************************************************************************
|
|
|
|
|
|
// The Disc Image Chef
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
//
|
|
|
|
|
|
// Filename : OpticalDisc.cs
|
2017-12-19 03:50:57 +00:00
|
|
|
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
2017-08-08 13:40:32 +01:00
|
|
|
|
//
|
2017-12-19 03:50:57 +00:00
|
|
|
|
// Component : Core algorithms.
|
2017-08-08 13:40:32 +01:00
|
|
|
|
//
|
|
|
|
|
|
// --[ Description ] ----------------------------------------------------------
|
|
|
|
|
|
//
|
2017-12-19 03:50:57 +00:00
|
|
|
|
// Contains logic to create sidecar from an optical media dump.
|
2017-08-08 13:40:32 +01:00
|
|
|
|
//
|
|
|
|
|
|
// --[ License ] --------------------------------------------------------------
|
|
|
|
|
|
//
|
|
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
|
|
// it under the terms of the GNU General Public License as
|
|
|
|
|
|
// published by the Free Software Foundation, either version 3 of the
|
|
|
|
|
|
// License, or (at your option) any later version.
|
|
|
|
|
|
//
|
|
|
|
|
|
// This program 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 General Public License for more details.
|
|
|
|
|
|
//
|
|
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
//
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2017-12-19 03:50:57 +00:00
|
|
|
|
// Copyright © 2011-2018 Natalia Portillo
|
2017-08-08 13:40:32 +01:00
|
|
|
|
// ****************************************************************************/
|
|
|
|
|
|
|
2017-12-21 14:30:38 +00:00
|
|
|
|
using System;
|
2017-12-19 03:50:57 +00:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.IO;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
using DiscImageChef.CommonTypes;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
using DiscImageChef.Decoders.CD;
|
|
|
|
|
|
using DiscImageChef.Decoders.DVD;
|
2017-12-20 17:15:26 +00:00
|
|
|
|
using DiscImageChef.DiscImages;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
using DiscImageChef.Filesystems;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
using Schemas;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
using DMI = DiscImageChef.Decoders.Xbox.DMI;
|
|
|
|
|
|
using Session = DiscImageChef.DiscImages.Session;
|
|
|
|
|
|
using TrackType = Schemas.TrackType;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
|
|
|
|
|
|
namespace DiscImageChef.Core
|
|
|
|
|
|
{
|
|
|
|
|
|
public static partial class Sidecar
|
|
|
|
|
|
{
|
2017-12-21 14:30:38 +00:00
|
|
|
|
static void OpticalDisc(ImagePlugin image, Guid filterId, string imagePath, FileInfo fi,
|
2017-12-19 20:33:03 +00:00
|
|
|
|
PluginBase plugins, List<ChecksumType> imgChecksums, ref CICMMetadataType sidecar)
|
2017-08-08 13:40:32 +01:00
|
|
|
|
{
|
2017-08-08 14:18:31 +01:00
|
|
|
|
sidecar.OpticalDisc = new[]
|
|
|
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
|
new OpticalDiscType
|
|
|
|
|
|
{
|
|
|
|
|
|
Checksums = imgChecksums.ToArray(),
|
|
|
|
|
|
Image = new ImageType
|
|
|
|
|
|
{
|
|
|
|
|
|
format = image.GetImageFormat(),
|
|
|
|
|
|
offset = 0,
|
|
|
|
|
|
offsetSpecified = true,
|
|
|
|
|
|
Value = Path.GetFileName(imagePath)
|
|
|
|
|
|
},
|
|
|
|
|
|
Size = fi.Length,
|
|
|
|
|
|
Sequence = new SequenceType {MediaTitle = image.GetImageName()}
|
2017-08-08 14:18:31 +01:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2017-08-08 13:40:32 +01:00
|
|
|
|
if(image.GetMediaSequence() != 0 && image.GetLastDiskSequence() != 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
sidecar.OpticalDisc[0].Sequence.MediaSequence = image.GetMediaSequence();
|
|
|
|
|
|
sidecar.OpticalDisc[0].Sequence.TotalMedia = image.GetMediaSequence();
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
sidecar.OpticalDisc[0].Sequence.MediaSequence = 1;
|
|
|
|
|
|
sidecar.OpticalDisc[0].Sequence.TotalMedia = 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-12-20 17:15:26 +00:00
|
|
|
|
MediaType dskType = image.ImageInfo.MediaType;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
|
2017-12-20 17:15:26 +00:00
|
|
|
|
foreach(MediaTagType tagType in image.ImageInfo.ReadableMediaTags)
|
2017-08-08 13:40:32 +01:00
|
|
|
|
switch(tagType)
|
|
|
|
|
|
{
|
|
|
|
|
|
case MediaTagType.CD_ATIP:
|
2017-08-08 14:18:31 +01:00
|
|
|
|
sidecar.OpticalDisc[0].ATIP = new DumpType
|
|
|
|
|
|
{
|
|
|
|
|
|
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.CD_ATIP)).ToArray(),
|
|
|
|
|
|
Size = image.ReadDiskTag(MediaTagType.CD_ATIP).Length
|
|
|
|
|
|
};
|
2017-12-21 14:30:38 +00:00
|
|
|
|
ATIP.CDATIP?
|
|
|
|
|
|
atip = ATIP.Decode(image.ReadDiskTag(MediaTagType.CD_ATIP));
|
2017-08-08 13:40:32 +01:00
|
|
|
|
if(atip.HasValue)
|
2017-12-19 20:33:03 +00:00
|
|
|
|
if(atip.Value.DDCD) dskType = atip.Value.DiscType ? MediaType.DDCDRW : MediaType.DDCDR;
|
|
|
|
|
|
else dskType = atip.Value.DiscType ? MediaType.CDRW : MediaType.CDR;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
break;
|
|
|
|
|
|
case MediaTagType.DVD_BCA:
|
2017-08-08 14:18:31 +01:00
|
|
|
|
sidecar.OpticalDisc[0].BCA = new DumpType
|
|
|
|
|
|
{
|
|
|
|
|
|
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.DVD_BCA)).ToArray(),
|
|
|
|
|
|
Size = image.ReadDiskTag(MediaTagType.DVD_BCA).Length
|
|
|
|
|
|
};
|
2017-08-08 13:40:32 +01:00
|
|
|
|
break;
|
|
|
|
|
|
case MediaTagType.BD_BCA:
|
2017-08-08 14:18:31 +01:00
|
|
|
|
sidecar.OpticalDisc[0].BCA = new DumpType
|
|
|
|
|
|
{
|
|
|
|
|
|
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.BD_BCA)).ToArray(),
|
|
|
|
|
|
Size = image.ReadDiskTag(MediaTagType.BD_BCA).Length
|
|
|
|
|
|
};
|
2017-08-08 13:40:32 +01:00
|
|
|
|
break;
|
|
|
|
|
|
case MediaTagType.DVD_CMI:
|
2017-08-08 14:18:31 +01:00
|
|
|
|
sidecar.OpticalDisc[0].CMI = new DumpType
|
|
|
|
|
|
{
|
|
|
|
|
|
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.DVD_CMI)).ToArray(),
|
|
|
|
|
|
Size = image.ReadDiskTag(MediaTagType.DVD_CMI).Length
|
|
|
|
|
|
};
|
2017-12-21 14:30:38 +00:00
|
|
|
|
CSS_CPRM.LeadInCopyright? cmi =
|
|
|
|
|
|
CSS_CPRM.DecodeLeadInCopyright(image.ReadDiskTag(MediaTagType.DVD_CMI));
|
2017-08-08 13:40:32 +01:00
|
|
|
|
if(cmi.HasValue)
|
|
|
|
|
|
switch(cmi.Value.CopyrightType)
|
|
|
|
|
|
{
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case CopyrightType.AACS:
|
2017-08-08 13:40:32 +01:00
|
|
|
|
sidecar.OpticalDisc[0].CopyProtection = "AACS";
|
|
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case CopyrightType.CSS:
|
2017-08-08 13:40:32 +01:00
|
|
|
|
sidecar.OpticalDisc[0].CopyProtection = "CSS";
|
|
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case CopyrightType.CPRM:
|
2017-08-08 13:40:32 +01:00
|
|
|
|
sidecar.OpticalDisc[0].CopyProtection = "CPRM";
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2017-12-19 20:33:03 +00:00
|
|
|
|
|
2017-08-08 13:40:32 +01:00
|
|
|
|
break;
|
|
|
|
|
|
case MediaTagType.DVD_DMI:
|
2017-08-08 14:18:31 +01:00
|
|
|
|
sidecar.OpticalDisc[0].DMI = new DumpType
|
|
|
|
|
|
{
|
|
|
|
|
|
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.DVD_DMI)).ToArray(),
|
|
|
|
|
|
Size = image.ReadDiskTag(MediaTagType.DVD_DMI).Length
|
|
|
|
|
|
};
|
2017-12-21 14:30:38 +00:00
|
|
|
|
if(DMI.IsXbox(image.ReadDiskTag(MediaTagType.DVD_DMI)))
|
2017-08-08 13:40:32 +01:00
|
|
|
|
{
|
|
|
|
|
|
dskType = MediaType.XGD;
|
2017-12-19 20:33:03 +00:00
|
|
|
|
sidecar.OpticalDisc[0].Dimensions = new DimensionsType {Diameter = 120};
|
2017-08-08 13:40:32 +01:00
|
|
|
|
}
|
2017-12-21 14:30:38 +00:00
|
|
|
|
else if(DMI.IsXbox360(image.ReadDiskTag(MediaTagType.DVD_DMI)))
|
2017-08-08 13:40:32 +01:00
|
|
|
|
{
|
|
|
|
|
|
dskType = MediaType.XGD2;
|
2017-12-19 20:33:03 +00:00
|
|
|
|
sidecar.OpticalDisc[0].Dimensions = new DimensionsType {Diameter = 120};
|
2017-08-08 13:40:32 +01:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case MediaTagType.DVD_PFI:
|
2017-08-08 14:18:31 +01:00
|
|
|
|
sidecar.OpticalDisc[0].PFI = new DumpType
|
|
|
|
|
|
{
|
|
|
|
|
|
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.DVD_PFI)).ToArray(),
|
|
|
|
|
|
Size = image.ReadDiskTag(MediaTagType.DVD_PFI).Length
|
|
|
|
|
|
};
|
2017-12-21 14:30:38 +00:00
|
|
|
|
PFI.PhysicalFormatInformation? pfi =
|
|
|
|
|
|
PFI.Decode(image.ReadDiskTag(MediaTagType.DVD_PFI));
|
2017-08-08 13:40:32 +01:00
|
|
|
|
if(pfi.HasValue)
|
2017-12-19 20:33:03 +00:00
|
|
|
|
if(dskType != MediaType.XGD && dskType != MediaType.XGD2 && dskType != MediaType.XGD3)
|
2017-08-08 13:40:32 +01:00
|
|
|
|
{
|
|
|
|
|
|
switch(pfi.Value.DiskCategory)
|
|
|
|
|
|
{
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case DiskCategory.DVDPR:
|
2017-08-08 13:40:32 +01:00
|
|
|
|
dskType = MediaType.DVDPR;
|
|
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case DiskCategory.DVDPRDL:
|
2017-08-08 13:40:32 +01:00
|
|
|
|
dskType = MediaType.DVDPRDL;
|
|
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case DiskCategory.DVDPRW:
|
2017-08-08 13:40:32 +01:00
|
|
|
|
dskType = MediaType.DVDPRW;
|
|
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case DiskCategory.DVDPRWDL:
|
2017-08-08 13:40:32 +01:00
|
|
|
|
dskType = MediaType.DVDPRWDL;
|
|
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case DiskCategory.DVDR:
|
2017-08-08 13:40:32 +01:00
|
|
|
|
dskType = MediaType.DVDR;
|
|
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case DiskCategory.DVDRAM:
|
2017-08-08 13:40:32 +01:00
|
|
|
|
dskType = MediaType.DVDRAM;
|
|
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case DiskCategory.DVDROM:
|
2017-08-08 13:40:32 +01:00
|
|
|
|
dskType = MediaType.DVDROM;
|
|
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case DiskCategory.DVDRW:
|
2017-08-08 13:40:32 +01:00
|
|
|
|
dskType = MediaType.DVDRW;
|
|
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case DiskCategory.HDDVDR:
|
2017-08-08 13:40:32 +01:00
|
|
|
|
dskType = MediaType.HDDVDR;
|
|
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case DiskCategory.HDDVDRAM:
|
2017-08-08 13:40:32 +01:00
|
|
|
|
dskType = MediaType.HDDVDRAM;
|
|
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case DiskCategory.HDDVDROM:
|
2017-08-08 13:40:32 +01:00
|
|
|
|
dskType = MediaType.HDDVDROM;
|
|
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case DiskCategory.HDDVDRW:
|
2017-08-08 13:40:32 +01:00
|
|
|
|
dskType = MediaType.HDDVDRW;
|
|
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case DiskCategory.Nintendo:
|
2017-08-08 13:40:32 +01:00
|
|
|
|
dskType = MediaType.GOD;
|
|
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case DiskCategory.UMD:
|
2017-08-08 13:40:32 +01:00
|
|
|
|
dskType = MediaType.UMD;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
|
if(dskType == MediaType.DVDR && pfi.Value.PartVersion == 6) dskType = MediaType.DVDRDL;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
if(dskType == MediaType.DVDRW && pfi.Value.PartVersion == 3)
|
|
|
|
|
|
dskType = MediaType.DVDRWDL;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
if(dskType == MediaType.GOD && pfi.Value.DiscSize == DVDSize.OneTwenty)
|
2017-08-08 13:40:32 +01:00
|
|
|
|
dskType = MediaType.WOD;
|
|
|
|
|
|
|
|
|
|
|
|
sidecar.OpticalDisc[0].Dimensions = new DimensionsType();
|
2017-12-19 20:33:03 +00:00
|
|
|
|
if(dskType == MediaType.UMD) sidecar.OpticalDisc[0].Dimensions.Diameter = 60;
|
2017-12-21 04:43:29 +00:00
|
|
|
|
else switch(pfi.Value.DiscSize) {
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case DVDSize.Eighty: sidecar.OpticalDisc[0].Dimensions.Diameter = 80;
|
2017-12-21 04:43:29 +00:00
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case DVDSize.OneTwenty: sidecar.OpticalDisc[0].Dimensions.Diameter = 120;
|
2017-12-21 04:43:29 +00:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
2017-08-08 13:40:32 +01:00
|
|
|
|
}
|
2017-12-19 20:33:03 +00:00
|
|
|
|
|
2017-08-08 13:40:32 +01:00
|
|
|
|
break;
|
|
|
|
|
|
case MediaTagType.CD_PMA:
|
2017-08-08 14:18:31 +01:00
|
|
|
|
sidecar.OpticalDisc[0].PMA = new DumpType
|
|
|
|
|
|
{
|
|
|
|
|
|
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.CD_PMA)).ToArray(),
|
|
|
|
|
|
Size = image.ReadDiskTag(MediaTagType.CD_PMA).Length
|
|
|
|
|
|
};
|
2017-08-08 13:40:32 +01:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
List<Session> sessions = image.GetSessions();
|
|
|
|
|
|
sidecar.OpticalDisc[0].Sessions = sessions != null ? sessions.Count : 1;
|
|
|
|
|
|
}
|
2017-12-19 20:33:03 +00:00
|
|
|
|
catch { sidecar.OpticalDisc[0].Sessions = 1; }
|
2017-08-08 13:40:32 +01:00
|
|
|
|
|
|
|
|
|
|
List<Track> tracks = image.GetTracks();
|
2017-12-21 14:30:38 +00:00
|
|
|
|
List<TrackType> trksLst = null;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
if(tracks != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
sidecar.OpticalDisc[0].Tracks = new int[1];
|
|
|
|
|
|
sidecar.OpticalDisc[0].Tracks[0] = tracks.Count;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
trksLst = new List<TrackType>();
|
2017-08-08 13:40:32 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
InitProgress();
|
|
|
|
|
|
foreach(Track trk in tracks)
|
|
|
|
|
|
{
|
2017-12-21 14:30:38 +00:00
|
|
|
|
TrackType xmlTrk = new TrackType();
|
2017-08-08 13:40:32 +01:00
|
|
|
|
switch(trk.TrackType)
|
|
|
|
|
|
{
|
2017-12-20 17:15:26 +00:00
|
|
|
|
case DiscImages.TrackType.Audio:
|
2017-08-08 13:40:32 +01:00
|
|
|
|
xmlTrk.TrackType1 = TrackTypeTrackType.audio;
|
|
|
|
|
|
break;
|
2017-12-20 17:15:26 +00:00
|
|
|
|
case DiscImages.TrackType.CdMode2Form2:
|
2017-08-08 13:40:32 +01:00
|
|
|
|
xmlTrk.TrackType1 = TrackTypeTrackType.m2f2;
|
|
|
|
|
|
break;
|
2017-12-20 17:15:26 +00:00
|
|
|
|
case DiscImages.TrackType.CdMode2Formless:
|
2017-08-08 13:40:32 +01:00
|
|
|
|
xmlTrk.TrackType1 = TrackTypeTrackType.mode2;
|
|
|
|
|
|
break;
|
2017-12-20 17:15:26 +00:00
|
|
|
|
case DiscImages.TrackType.CdMode2Form1:
|
2017-08-08 13:40:32 +01:00
|
|
|
|
xmlTrk.TrackType1 = TrackTypeTrackType.m2f1;
|
|
|
|
|
|
break;
|
2017-12-20 17:15:26 +00:00
|
|
|
|
case DiscImages.TrackType.CdMode1:
|
2017-08-08 13:40:32 +01:00
|
|
|
|
xmlTrk.TrackType1 = TrackTypeTrackType.mode1;
|
|
|
|
|
|
break;
|
2017-12-20 17:15:26 +00:00
|
|
|
|
case DiscImages.TrackType.Data:
|
2017-08-08 13:40:32 +01:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2017-12-19 20:33:03 +00:00
|
|
|
|
|
2017-08-08 13:40:32 +01:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
2017-12-19 20:33:03 +00:00
|
|
|
|
|
|
|
|
|
|
xmlTrk.Sequence =
|
|
|
|
|
|
new TrackSequenceType {Session = trk.TrackSession, TrackNumber = (int)trk.TrackSequence};
|
2017-08-08 13:40:32 +01:00
|
|
|
|
xmlTrk.StartSector = (long)trk.TrackStartSector;
|
|
|
|
|
|
xmlTrk.EndSector = (long)trk.TrackEndSector;
|
|
|
|
|
|
|
2017-12-20 23:07:46 +00:00
|
|
|
|
if(trk.Indexes != null && trk.Indexes.ContainsKey(0)) if(trk.Indexes.TryGetValue(0, out ulong idx0)) xmlTrk.StartSector = (long)idx0;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
|
switch(sidecar.OpticalDisc[0].DiscType) {
|
|
|
|
|
|
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-08-08 13:40:32 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
|
xmlTrk.Image = new ImageType {Value = Path.GetFileName(trk.TrackFile), format = trk.TrackFileType};
|
2017-08-08 14:18:31 +01:00
|
|
|
|
|
2017-08-08 13:40:32 +01:00
|
|
|
|
if(trk.TrackFileOffset > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
xmlTrk.Image.offset = (long)trk.TrackFileOffset;
|
|
|
|
|
|
xmlTrk.Image.offsetSpecified = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
xmlTrk.Size = (xmlTrk.EndSector - xmlTrk.StartSector + 1) * trk.TrackRawBytesPerSector;
|
|
|
|
|
|
xmlTrk.BytesPerSector = trk.TrackBytesPerSector;
|
|
|
|
|
|
|
|
|
|
|
|
uint sectorsToRead = 512;
|
|
|
|
|
|
ulong sectors = (ulong)(xmlTrk.EndSector - xmlTrk.StartSector + 1);
|
|
|
|
|
|
ulong doneSectors = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// If there is only one track, and it's the same as the image file (e.g. ".iso" files), don't re-checksum.
|
2017-12-21 14:30:38 +00:00
|
|
|
|
if(image.PluginUuid == new Guid("12345678-AAAA-BBBB-CCCC-123456789000") &&
|
2017-08-08 13:40:32 +01:00
|
|
|
|
// Only if filter is none...
|
2017-12-21 14:30:38 +00:00
|
|
|
|
(filterId == new Guid("12345678-AAAA-BBBB-CCCC-123456789000") ||
|
2017-08-08 13:40:32 +01:00
|
|
|
|
// ...or AppleDouble
|
2017-12-21 14:30:38 +00:00
|
|
|
|
filterId == new Guid("1b2165ee-c9df-4b21-bbbb-9e5892b2df4d"))) xmlTrk.Checksums = sidecar.OpticalDisc[0].Checksums;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
UpdateProgress("Track {0} of {1}", trk.TrackSequence, tracks.Count);
|
|
|
|
|
|
|
|
|
|
|
|
// For fast debugging, skip checksum
|
|
|
|
|
|
//goto skipChecksum;
|
|
|
|
|
|
|
|
|
|
|
|
Checksum trkChkWorker = new Checksum();
|
|
|
|
|
|
|
|
|
|
|
|
InitProgress2();
|
|
|
|
|
|
while(doneSectors < sectors)
|
|
|
|
|
|
{
|
|
|
|
|
|
byte[] sector;
|
|
|
|
|
|
|
2017-12-20 17:26:28 +00:00
|
|
|
|
if(sectors - doneSectors >= sectorsToRead)
|
2017-08-08 13:40:32 +01:00
|
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
|
sector = image.ReadSectorsLong(doneSectors, sectorsToRead,
|
|
|
|
|
|
(uint)xmlTrk.Sequence.TrackNumber);
|
|
|
|
|
|
UpdateProgress2("Hashings sector {0} of {1}", (long)doneSectors,
|
|
|
|
|
|
(long)(trk.TrackEndSector - trk.TrackStartSector + 1));
|
2017-08-08 13:40:32 +01:00
|
|
|
|
doneSectors += sectorsToRead;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
|
sector = image.ReadSectorsLong(doneSectors, (uint)(sectors - doneSectors),
|
|
|
|
|
|
(uint)xmlTrk.Sequence.TrackNumber);
|
|
|
|
|
|
UpdateProgress2("Hashings sector {0} of {1}", (long)doneSectors,
|
|
|
|
|
|
(long)(trk.TrackEndSector - trk.TrackStartSector + 1));
|
2017-12-20 17:26:28 +00:00
|
|
|
|
doneSectors += sectors - doneSectors;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
trkChkWorker.Update(sector);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
List<ChecksumType> trkChecksums = trkChkWorker.End();
|
|
|
|
|
|
|
|
|
|
|
|
xmlTrk.Checksums = trkChecksums.ToArray();
|
|
|
|
|
|
|
|
|
|
|
|
EndProgress2();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(trk.TrackSubchannelType != TrackSubchannelType.None)
|
|
|
|
|
|
{
|
2017-08-08 14:18:31 +01:00
|
|
|
|
xmlTrk.SubChannel = new SubChannelType
|
|
|
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
|
Image = new ImageType {Value = trk.TrackSubchannelFile},
|
2017-08-08 14:18:31 +01:00
|
|
|
|
// TODO: Packed subchannel has different size?
|
|
|
|
|
|
Size = (xmlTrk.EndSector - xmlTrk.StartSector + 1) * 96
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2017-08-08 13:40:32 +01:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(trk.TrackFileOffset > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
xmlTrk.SubChannel.Image.offset = (long)trk.TrackSubchannelOffset;
|
|
|
|
|
|
xmlTrk.SubChannel.Image.offsetSpecified = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Checksum subChkWorker = new Checksum();
|
|
|
|
|
|
|
|
|
|
|
|
sectors = (ulong)(xmlTrk.EndSector - xmlTrk.StartSector + 1);
|
|
|
|
|
|
doneSectors = 0;
|
|
|
|
|
|
|
|
|
|
|
|
InitProgress2();
|
|
|
|
|
|
while(doneSectors < sectors)
|
|
|
|
|
|
{
|
|
|
|
|
|
byte[] sector;
|
|
|
|
|
|
|
2017-12-20 17:26:28 +00:00
|
|
|
|
if(sectors - doneSectors >= sectorsToRead)
|
2017-08-08 13:40:32 +01:00
|
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
|
sector = image.ReadSectorsTag(doneSectors, sectorsToRead, (uint)xmlTrk.Sequence.TrackNumber,
|
2017-12-20 17:15:26 +00:00
|
|
|
|
SectorTagType.CdSectorSubchannel);
|
2017-12-19 20:33:03 +00:00
|
|
|
|
UpdateProgress2("Hashings subchannel sector {0} of {1}", (long)doneSectors,
|
|
|
|
|
|
(long)(trk.TrackEndSector - trk.TrackStartSector + 1));
|
2017-08-08 13:40:32 +01:00
|
|
|
|
doneSectors += sectorsToRead;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
|
sector = image.ReadSectorsTag(doneSectors, (uint)(sectors - doneSectors),
|
|
|
|
|
|
(uint)xmlTrk.Sequence.TrackNumber,
|
2017-12-20 17:15:26 +00:00
|
|
|
|
SectorTagType.CdSectorSubchannel);
|
2017-12-19 20:33:03 +00:00
|
|
|
|
UpdateProgress2("Hashings subchannel sector {0} of {1}", (long)doneSectors,
|
|
|
|
|
|
(long)(trk.TrackEndSector - trk.TrackStartSector + 1));
|
2017-12-20 17:26:28 +00:00
|
|
|
|
doneSectors += sectors - doneSectors;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
subChkWorker.Update(sector);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
List<ChecksumType> subChecksums = subChkWorker.End();
|
|
|
|
|
|
|
|
|
|
|
|
xmlTrk.SubChannel.Checksums = subChecksums.ToArray();
|
|
|
|
|
|
|
|
|
|
|
|
EndProgress2();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// For fast debugging, skip checksum
|
|
|
|
|
|
//skipChecksum:
|
|
|
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
|
UpdateStatus("Checking filesystems on track {0} from sector {1} to {2}", xmlTrk.Sequence.TrackNumber,
|
|
|
|
|
|
xmlTrk.StartSector, xmlTrk.EndSector);
|
2017-08-08 13:40:32 +01:00
|
|
|
|
|
|
|
|
|
|
List<Partition> partitions = Partitions.GetAll(image);
|
|
|
|
|
|
Partitions.AddSchemesToStats(partitions);
|
|
|
|
|
|
|
|
|
|
|
|
xmlTrk.FileSystemInformation = new PartitionType[1];
|
|
|
|
|
|
if(partitions.Count > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
xmlTrk.FileSystemInformation = new PartitionType[partitions.Count];
|
|
|
|
|
|
for(int i = 0; i < partitions.Count; i++)
|
|
|
|
|
|
{
|
2017-08-08 14:18:31 +01:00
|
|
|
|
xmlTrk.FileSystemInformation[i] = new PartitionType
|
|
|
|
|
|
{
|
|
|
|
|
|
Description = partitions[i].Description,
|
2017-12-20 17:26:28 +00:00
|
|
|
|
EndSector = (int)partitions[i].End,
|
2017-08-08 14:18:31 +01:00
|
|
|
|
Name = partitions[i].Name,
|
|
|
|
|
|
Sequence = (int)partitions[i].Sequence,
|
|
|
|
|
|
StartSector = (int)partitions[i].Start,
|
|
|
|
|
|
Type = partitions[i].Type
|
|
|
|
|
|
};
|
2017-08-08 13:40:32 +01:00
|
|
|
|
List<FileSystemType> lstFs = new List<FileSystemType>();
|
|
|
|
|
|
|
2017-12-20 17:15:26 +00:00
|
|
|
|
foreach(Filesystem plugin in plugins.PluginsList.Values)
|
2017-08-08 13:40:32 +01:00
|
|
|
|
try
|
|
|
|
|
|
{
|
2017-12-21 06:06:19 +00:00
|
|
|
|
if(!plugin.Identify(image, partitions[i])) continue;
|
|
|
|
|
|
|
|
|
|
|
|
plugin.GetInformation(image, partitions[i], out string foo);
|
|
|
|
|
|
lstFs.Add(plugin.XmlFSType);
|
|
|
|
|
|
Statistics.AddFilesystem(plugin.XmlFSType.Type);
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#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);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
|
if(lstFs.Count > 0) xmlTrk.FileSystemInformation[i].FileSystems = lstFs.ToArray();
|
2017-08-08 13:40:32 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2017-08-08 14:18:31 +01:00
|
|
|
|
xmlTrk.FileSystemInformation[0] = new PartitionType
|
|
|
|
|
|
{
|
|
|
|
|
|
EndSector = (int)xmlTrk.EndSector,
|
|
|
|
|
|
StartSector = (int)xmlTrk.StartSector
|
|
|
|
|
|
};
|
2017-08-08 13:40:32 +01:00
|
|
|
|
List<FileSystemType> lstFs = new List<FileSystemType>();
|
|
|
|
|
|
|
|
|
|
|
|
Partition xmlPart = new Partition
|
|
|
|
|
|
{
|
|
|
|
|
|
Start = (ulong)xmlTrk.StartSector,
|
2017-12-20 17:26:28 +00:00
|
|
|
|
Length = (ulong)(xmlTrk.EndSector - xmlTrk.StartSector + 1),
|
2017-08-08 13:40:32 +01:00
|
|
|
|
Type = xmlTrk.TrackType1.ToString(),
|
|
|
|
|
|
Size = (ulong)xmlTrk.Size,
|
|
|
|
|
|
Sequence = (ulong)xmlTrk.Sequence.TrackNumber
|
|
|
|
|
|
};
|
2017-12-20 17:15:26 +00:00
|
|
|
|
foreach(Filesystem plugin in plugins.PluginsList.Values)
|
2017-08-08 13:40:32 +01:00
|
|
|
|
try
|
|
|
|
|
|
{
|
2017-12-21 06:06:19 +00:00
|
|
|
|
if(!plugin.Identify(image, xmlPart)) continue;
|
2017-12-20 17:15:26 +00:00
|
|
|
|
|
2017-12-21 06:06:19 +00:00
|
|
|
|
plugin.GetInformation(image, xmlPart, out string foo);
|
|
|
|
|
|
lstFs.Add(plugin.XmlFSType);
|
|
|
|
|
|
Statistics.AddFilesystem(plugin.XmlFSType.Type);
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#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);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
|
if(lstFs.Count > 0) xmlTrk.FileSystemInformation[0].FileSystems = lstFs.ToArray();
|
2017-08-08 13:40:32 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
trksLst.Add(xmlTrk);
|
|
|
|
|
|
}
|
2017-12-19 20:33:03 +00:00
|
|
|
|
|
2017-08-08 13:40:32 +01:00
|
|
|
|
EndProgress();
|
|
|
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
|
if(trksLst != null) sidecar.OpticalDisc[0].Track = trksLst.ToArray();
|
2017-08-08 13:40:32 +01:00
|
|
|
|
|
|
|
|
|
|
// All XGD3 all have the same number of blocks
|
|
|
|
|
|
if(dskType == MediaType.XGD2 && sidecar.OpticalDisc[0].Track.Length == 1)
|
|
|
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
|
ulong blocks = (ulong)(sidecar.OpticalDisc[0].Track[0].EndSector -
|
|
|
|
|
|
sidecar.OpticalDisc[0].Track[0].StartSector + 1);
|
2017-08-08 13:40:32 +01:00
|
|
|
|
if(blocks == 25063 || // Locked (or non compatible drive)
|
|
|
|
|
|
blocks == 4229664 || // Xtreme unlock
|
|
|
|
|
|
blocks == 4246304) // Wxripper unlock
|
|
|
|
|
|
dskType = MediaType.XGD3;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-08-08 14:18:31 +01:00
|
|
|
|
Metadata.MediaType.MediaTypeToString(dskType, out string dscType, out string dscSubType);
|
2017-08-08 13:40:32 +01:00
|
|
|
|
sidecar.OpticalDisc[0].DiscType = dscType;
|
|
|
|
|
|
sidecar.OpticalDisc[0].DiscSubType = dscSubType;
|
|
|
|
|
|
Statistics.AddMedia(dskType, false);
|
|
|
|
|
|
|
2017-12-20 17:15:26 +00:00
|
|
|
|
if(!string.IsNullOrEmpty(image.ImageInfo.DriveManufacturer) ||
|
|
|
|
|
|
!string.IsNullOrEmpty(image.ImageInfo.DriveModel) ||
|
|
|
|
|
|
!string.IsNullOrEmpty(image.ImageInfo.DriveFirmwareRevision) ||
|
|
|
|
|
|
!string.IsNullOrEmpty(image.ImageInfo.DriveSerialNumber))
|
2017-08-08 14:18:31 +01:00
|
|
|
|
sidecar.OpticalDisc[0].DumpHardwareArray = new[]
|
|
|
|
|
|
{
|
|
|
|
|
|
new DumpHardwareType
|
|
|
|
|
|
{
|
2017-12-20 17:15:26 +00:00
|
|
|
|
Extents = new[] {new ExtentType {Start = 0, End = image.ImageInfo.Sectors}},
|
|
|
|
|
|
Manufacturer = image.ImageInfo.DriveManufacturer,
|
|
|
|
|
|
Model = image.ImageInfo.DriveModel,
|
|
|
|
|
|
Firmware = image.ImageInfo.DriveFirmwareRevision,
|
|
|
|
|
|
Serial = image.ImageInfo.DriveSerialNumber,
|
2017-08-08 14:18:31 +01:00
|
|
|
|
Software = new SoftwareType
|
|
|
|
|
|
{
|
|
|
|
|
|
Name = image.GetImageApplication(),
|
|
|
|
|
|
Version = image.GetImageApplicationVersion()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
2017-08-08 13:40:32 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2017-12-19 20:33:03 +00:00
|
|
|
|
}
|