Files
Aaru/DiscImageChef.Core/Sidecar/OpticalDisc.cs

641 lines
32 KiB
C#
Raw Normal View History

2017-08-08 13:40:32 +01:00
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : OpticalDisc.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
2017-08-08 13:40:32 +01:00
//
// Component : Core algorithms.
2017-08-08 13:40:32 +01:00
//
// --[ Description ] ----------------------------------------------------------
//
// 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/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2018 Natalia Portillo
2017-08-08 13:40:32 +01:00
// ****************************************************************************/
2017-12-21 14:30:38 +00:00
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
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;
using DiscImageChef.DiscImages;
2017-12-21 14:30:38 +00:00
using DiscImageChef.Filesystems;
using DiscImageChef.Metadata;
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 MediaType = DiscImageChef.CommonTypes.MediaType;
2017-12-21 14:30:38 +00:00
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
{
/// <summary>
/// Creates a metadata sidecar for an optical disc (e.g. CD, DVD, GD, BD, XGD, GOD)
/// </summary>
/// <param name="image">Image</param>
/// <param name="filterId">Filter uuid</param>
/// <param name="imagePath">Image path</param>
/// <param name="fi">Image file information</param>
/// <param name="plugins">Image plugins</param>
/// <param name="imgChecksums">List of image checksums</param>
/// <param name="sidecar">Metadata sidecar</param>
static void OpticalDisc(IMediaImage image, Guid filterId, string imagePath,
FileInfo fi, PluginBase plugins,
List<ChecksumType> imgChecksums, ref CICMMetadataType sidecar, Encoding encoding)
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
2017-12-19 20:33:03 +00:00
{
format = image.Format,
offset = 0,
2017-12-19 20:33:03 +00:00
offsetSpecified = true,
Value = Path.GetFileName(imagePath)
2017-12-19 20:33:03 +00:00
},
Size = fi.Length,
Sequence = new SequenceType {MediaTitle = image.Info.MediaTitle}
2017-08-08 14:18:31 +01:00
}
};
if(image.Info.MediaSequence != 0 && image.Info.LastMediaSequence != 0)
2017-08-08 13:40:32 +01:00
{
sidecar.OpticalDisc[0].Sequence.MediaSequence = image.Info.MediaSequence;
sidecar.OpticalDisc[0].Sequence.TotalMedia = image.Info.LastMediaSequence;
2017-08-08 13:40:32 +01:00
}
else
{
sidecar.OpticalDisc[0].Sequence.MediaSequence = 1;
sidecar.OpticalDisc[0].Sequence.TotalMedia = 1;
2017-08-08 13:40:32 +01:00
}
MediaType dskType = image.Info.MediaType;
2017-08-08 13:40:32 +01:00
foreach(MediaTagType tagType in image.Info.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-08-08 14:18:31 +01:00
};
ATIP.CDATIP? atip = ATIP.Decode(image.ReadDiskTag(MediaTagType.CD_ATIP));
2017-08-08 13:40:32 +01:00
if(atip.HasValue)
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 14:18:31 +01:00
};
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 14:18:31 +01:00
};
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-08-08 14:18:31 +01:00
};
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-08-08 14:18:31 +01:00
};
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;
sidecar.OpticalDisc[0].Dimensions = new DimensionsType {Diameter = 120, Thickness = 1.2};
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;
sidecar.OpticalDisc[0].Dimensions = new DimensionsType {Diameter = 120, Thickness = 1.2};
2017-08-08 13:40:32 +01:00
}
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-08-08 14:18:31 +01: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;
}
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();
if(dskType == MediaType.UMD)
{
sidecar.OpticalDisc[0].Dimensions.Height = 64;
sidecar.OpticalDisc[0].Dimensions.HeightSpecified = true;
sidecar.OpticalDisc[0].Dimensions.Width = 63;
sidecar.OpticalDisc[0].Dimensions.WidthSpecified = true;
sidecar.OpticalDisc[0].Dimensions.Thickness = 4;
}
else
switch(pfi.Value.DiscSize)
{
case DVDSize.Eighty:
sidecar.OpticalDisc[0].Dimensions.Diameter = 80;
sidecar.OpticalDisc[0].Dimensions.Thickness = 1.2;
break;
case DVDSize.OneTwenty:
sidecar.OpticalDisc[0].Dimensions.Diameter = 120;
sidecar.OpticalDisc[0].Dimensions.Thickness = 1.2;
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 14:18:31 +01:00
};
2017-08-08 13:40:32 +01:00
break;
}
try
{
List<Session> sessions = image.Sessions;
sidecar.OpticalDisc[0].Sessions = sessions?.Count ?? 1;
2017-08-08 13:40:32 +01:00
}
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.Tracks;
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];
2017-08-08 13:40:32 +01:00
sidecar.OpticalDisc[0].Tracks[0] = tracks.Count;
trksLst = new List<TrackType>();
2017-08-08 13:40:32 +01:00
}
if(sidecar.OpticalDisc[0].Dimensions == null && image.Info.MediaType != MediaType.Unknown)
sidecar.OpticalDisc[0].Dimensions = Dimensions.DimensionsFromMediaType(image.Info.MediaType);
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)
{
case DiscImages.TrackType.Audio:
2017-08-08 13:40:32 +01:00
xmlTrk.TrackType1 = TrackTypeTrackType.audio;
break;
case DiscImages.TrackType.CdMode2Form2:
2017-08-08 13:40:32 +01:00
xmlTrk.TrackType1 = TrackTypeTrackType.m2f2;
break;
case DiscImages.TrackType.CdMode2Formless:
2017-08-08 13:40:32 +01:00
xmlTrk.TrackType1 = TrackTypeTrackType.mode2;
break;
case DiscImages.TrackType.CdMode2Form1:
2017-08-08 13:40:32 +01:00
xmlTrk.TrackType1 = TrackTypeTrackType.m2f1;
break;
case DiscImages.TrackType.CdMode1:
2017-08-08 13:40:32 +01:00
xmlTrk.TrackType1 = TrackTypeTrackType.mode1;
break;
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 =
2017-12-19 20:33:03 +00:00
new TrackSequenceType {Session = trk.TrackSession, TrackNumber = (int)trk.TrackSequence};
xmlTrk.StartSector = (long)trk.TrackStartSector;
xmlTrk.EndSector = (long)trk.TrackEndSector;
2017-08-08 13:40:32 +01: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
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;
2017-08-08 13:40:32 +01:00
xmlTrk.Image.offsetSpecified = true;
}
xmlTrk.Size = (xmlTrk.EndSector - xmlTrk.StartSector + 1) * trk.TrackRawBytesPerSector;
2017-08-08 13:40:32 +01:00
xmlTrk.BytesPerSector = trk.TrackBytesPerSector;
uint sectorsToRead = 512;
ulong sectors = (ulong)(xmlTrk.EndSector - xmlTrk.StartSector + 1);
ulong doneSectors = 0;
2017-08-08 13:40:32 +01: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(image.Id == 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
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;
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));
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;
2017-08-08 13:40:32 +01:00
xmlTrk.SubChannel.Image.offsetSpecified = true;
}
Checksum subChkWorker = new Checksum();
sectors = (ulong)(xmlTrk.EndSector - xmlTrk.StartSector + 1);
2017-08-08 13:40:32 +01:00
doneSectors = 0;
InitProgress2();
while(doneSectors < sectors)
{
byte[] sector;
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,
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,
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));
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,
EndSector = (int)partitions[i].End,
Name = partitions[i].Name,
Sequence = (int)partitions[i].Sequence,
2017-08-08 14:18:31 +01:00
StartSector = (int)partitions[i].Start,
Type = partitions[i].Type
2017-08-08 14:18:31 +01:00
};
2017-08-08 13:40:32 +01:00
List<FileSystemType> lstFs = new List<FileSystemType>();
foreach(IFilesystem plugin in plugins.PluginsList.Values)
2017-08-08 13:40:32 +01:00
try
{
if(!plugin.Identify(image, partitions[i])) continue;
plugin.GetInformation(image, partitions[i], out _, encoding);
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
2017-08-08 13:40:32 +01:00
catch
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
2017-08-08 13:40:32 +01:00
{
//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,
2017-08-08 14:18:31 +01:00
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,
Length = (ulong)(xmlTrk.EndSector - xmlTrk.StartSector + 1),
Type = xmlTrk.TrackType1.ToString(),
Size = (ulong)xmlTrk.Size,
2017-08-08 13:40:32 +01:00
Sequence = (ulong)xmlTrk.Sequence.TrackNumber
};
foreach(IFilesystem plugin in plugins.PluginsList.Values)
2017-08-08 13:40:32 +01:00
try
{
if(!plugin.Identify(image, xmlPart)) continue;
plugin.GetInformation(image, xmlPart, out _, encoding);
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
2017-08-08 13:40:32 +01:00
catch
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
2017-08-08 13:40:32 +01:00
{
//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)
{
ulong blocks = (ulong)(sidecar.OpticalDisc[0].Track[0].EndSector -
2017-12-19 20:33:03 +00:00
sidecar.OpticalDisc[0].Track[0].StartSector + 1);
if(blocks == 25063 || // Locked (or non compatible drive)
2017-08-08 13:40:32 +01:00
blocks == 4229664 || // Xtreme unlock
blocks == 4246304) // Wxripper unlock
2017-08-08 13:40:32 +01:00
dskType = MediaType.XGD3;
}
2017-08-08 14:18:31 +01:00
Metadata.MediaType.MediaTypeToString(dskType, out string dscType, out string dscSubType);
sidecar.OpticalDisc[0].DiscType = dscType;
2017-08-08 13:40:32 +01:00
sidecar.OpticalDisc[0].DiscSubType = dscSubType;
Statistics.AddMedia(dskType, false);
if(image.DumpHardware != null) sidecar.OpticalDisc[0].DumpHardwareArray = image.DumpHardware.ToArray();
else if(!string.IsNullOrEmpty(image.Info.DriveManufacturer) ||
!string.IsNullOrEmpty(image.Info.DriveModel) ||
!string.IsNullOrEmpty(image.Info.DriveFirmwareRevision) ||
!string.IsNullOrEmpty(image.Info.DriveSerialNumber))
2017-08-08 14:18:31 +01:00
sidecar.OpticalDisc[0].DumpHardwareArray = new[]
{
new DumpHardwareType
{
Extents = new[] {new ExtentType {Start = 0, End = image.Info.Sectors}},
Manufacturer = image.Info.DriveManufacturer,
Model = image.Info.DriveModel,
Firmware = image.Info.DriveFirmwareRevision,
Serial = image.Info.DriveSerialNumber,
Software = new SoftwareType
2017-08-08 14:18:31 +01:00
{
Name = image.Info.Application,
Version = image.Info.ApplicationVersion
2017-08-08 14:18:31 +01:00
}
}
};
2017-08-08 13:40:32 +01:00
}
}
2017-12-19 20:33:03 +00:00
}