Files
apprepodbmgr/apprepodbmgr.Core/Workers/DiscImageChef.cs

1343 lines
66 KiB
C#
Raw Normal View History

//
// 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
using System;
using System.Collections.Generic;
2017-05-03 01:54:02 +01:00
using System.IO;
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;
namespace apprepodbmgr.Core
{
public static partial class Workers
{
public static void AddMedia()
{
2017-12-30 00:32:21 +00:00
if(string.IsNullOrWhiteSpace(Context.SelectedFile))
{
2017-12-30 00:32:21 +00:00
Failed?.Invoke("There is no file set");
2020-08-22 21:37:02 +01:00
return;
}
string filesPath;
2020-08-22 21:37:02 +01:00
if(!string.IsNullOrEmpty(Context.TmpFolder) &&
Directory.Exists(Context.TmpFolder))
filesPath = Context.TmpFolder;
else
filesPath = Context.Path;
2017-12-30 00:32:21 +00:00
string selectedFile = Path.Combine(filesPath, Context.SelectedFile);
if(!File.Exists(selectedFile))
{
2017-12-30 00:32:21 +00:00
Failed?.Invoke("Selected file does not exist");
2020-08-22 21:37:02 +01:00
return;
}
2020-08-22 21:37:02 +01:00
var sidecar = new CICMMetadataType();
var plugins = new PluginBase();
long maxProgress = 4;
2020-08-22 21:37:02 +01:00
var filtersList = new FiltersList();
2017-12-30 00:32:21 +00:00
UpdateProgress?.Invoke(null, "Detecting image filter", 1, maxProgress);
2017-12-29 19:31:26 +00:00
IFilter inputFilter = filtersList.GetFilter(selectedFile);
if(inputFilter == null)
{
2017-12-30 00:32:21 +00:00
Failed?.Invoke("Cannot open specified file.");
2020-08-22 21:37:02 +01:00
return;
}
try
{
2020-08-22 21:37:02 +01:00
#if DEBUG
2017-05-19 03:24:34 +01:00
stopwatch.Restart();
2020-08-22 21:37:02 +01:00
#endif
2017-12-30 00:32:21 +00:00
UpdateProgress?.Invoke(null, "Detecting image format", 2, maxProgress);
IMediaImage imageFormat = ImageFormat.Detect(inputFilter);
2020-08-22 21:37:02 +01:00
#if DEBUG
2017-05-19 03:24:34 +01:00
stopwatch.Stop();
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
Console.WriteLine("Core.AddMedia(): Took {0} seconds to detect image format",
stopwatch.Elapsed.TotalSeconds);
2020-08-22 21:37:02 +01:00
#endif
2017-12-30 00:32:21 +00:00
if(imageFormat == null)
{
2017-12-30 00:32:21 +00:00
Failed?.Invoke("Image format not identified, not proceeding with analysis.");
2020-08-22 21:37:02 +01:00
return;
}
try
{
2017-12-30 00:32:21 +00:00
if(!imageFormat.Open(inputFilter))
{
2017-12-30 00:32:21 +00:00
Failed?.Invoke("Unable to open image format\n" + "No error given");
2020-08-22 21:37:02 +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}");
2020-08-22 21:37:02 +01:00
#if DEBUG
2017-06-13 18:21:12 +01:00
Console.WriteLine("Exception {0}\n{1}", ex.Message, ex.InnerException);
2020-08-22 21:37:02 +01:00
#endif
return;
}
2020-08-22 21:37:02 +01:00
var fi = new FileInfo(selectedFile);
var fs = new FileStream(selectedFile, FileMode.Open, FileAccess.Read);
2020-08-22 21:37:02 +01:00
var imgChkWorker = new Checksum();
2017-12-30 00:32:21 +00:00
UpdateProgress?.Invoke(null, "Hashing image file", 3, maxProgress);
2020-08-22 21:37:02 +01:00
#if DEBUG
2017-05-19 03:24:34 +01:00
stopwatch.Restart();
2020-08-22 21:37:02 +01:00
#endif
byte[] data;
2017-12-30 00:32:21 +00:00
long position = 0;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
while(position < fi.Length - 524288)
{
data = new byte[524288];
fs.Read(data, 0, 524288);
2017-12-30 00:32:21 +00:00
UpdateProgress2?.Invoke(null, $"{position} of {fi.Length} bytes", position, fi.Length);
imgChkWorker.Update(data);
position += 524288;
}
2020-08-22 21:37:02 +01:00
data = new byte[fi.Length - position];
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);
imgChkWorker.Update(data);
fs.Close();
2020-08-22 21:37:02 +01:00
#if DEBUG
2017-05-19 03:24:34 +01:00
stopwatch.Stop();
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
Console.WriteLine("Core.AddMedia(): Took {0} seconds to hash image file",
stopwatch.Elapsed.TotalSeconds);
2020-08-22 21:37:02 +01:00
#endif
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;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
switch(imageFormat.Info.XmlMediaType)
{
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);
2020-08-22 21:37:02 +01:00
sidecar.OpticalDisc = new OpticalDiscType[1];
2017-12-30 00:32:21 +00:00
sidecar.OpticalDisc[0] = new OpticalDiscType
{
2017-12-30 00:32:21 +00:00
Checksums = imgChecksums.ToArray(),
2020-08-22 21:37:02 +01:00
Image = new ImageType
{
2017-12-30 00:32:21 +00:00
format = imageFormat.Format,
offset = 0,
offsetSpecified = true,
Value = Path.GetFileName(selectedFile)
},
2020-08-22 21:37:02 +01:00
Size = fi.Length,
Sequence = new SequenceType
{
MediaTitle = imageFormat.Info.MediaTitle
}
2017-12-30 00:32:21 +00:00
};
2020-08-22 21:37:02 +01:00
if(imageFormat.Info.MediaSequence != 0 &&
imageFormat.Info.LastMediaSequence != 0)
2017-12-30 00:32:21 +00:00
{
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-12-30 00:32:21 +00:00
MediaType dskType = imageFormat.Info.MediaType;
2017-12-30 00:32:21 +00:00
currentProgress = 3;
2020-08-22 21:37:02 +01:00
#if DEBUG
2017-12-30 00:32:21 +00:00
stopwatch.Restart();
2020-08-22 21:37:02 +01:00
#endif
2017-12-30 00:32:21 +00:00
foreach(MediaTagType tagType in imageFormat.Info.ReadableMediaTags)
{
currentProgress++;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
UpdateProgress?.Invoke(null, $"Hashing file containing {tagType}", currentProgress,
maxProgress);
2017-12-30 00:32:21 +00:00
switch(tagType)
{
case MediaTagType.CD_ATIP:
2020-08-22 21:37:02 +01:00
sidecar.OpticalDisc[0].ATIP = new DumpType();
sidecar.OpticalDisc[0].ATIP.Checksums = Checksum.
GetChecksums(imageFormat.
ReadDiskTag(MediaTagType.
CD_ATIP)).
ToArray();
2017-12-30 00:32:21 +00:00
sidecar.OpticalDisc[0].ATIP.Size =
imageFormat.ReadDiskTag(MediaTagType.CD_ATIP).Length;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
ATIP.CDATIP? atip = ATIP.Decode(imageFormat.ReadDiskTag(MediaTagType.CD_ATIP));
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00: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;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case MediaTagType.DVD_BCA:
2020-08-22 21:37:02 +01:00
sidecar.OpticalDisc[0].BCA = new DumpType();
sidecar.OpticalDisc[0].BCA.Checksums = Checksum.
GetChecksums(imageFormat.
ReadDiskTag(MediaTagType.
DVD_BCA)).
ToArray();
2017-12-30 00:32:21 +00:00
sidecar.OpticalDisc[0].BCA.Size =
imageFormat.ReadDiskTag(MediaTagType.DVD_BCA).Length;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case MediaTagType.BD_BCA:
2020-08-22 21:37:02 +01:00
sidecar.OpticalDisc[0].BCA = new DumpType();
sidecar.OpticalDisc[0].BCA.Checksums = Checksum.
GetChecksums(imageFormat.
ReadDiskTag(MediaTagType.
BD_BCA)).ToArray();
2017-12-30 00:32:21 +00:00
sidecar.OpticalDisc[0].BCA.Size =
imageFormat.ReadDiskTag(MediaTagType.BD_BCA).Length;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case MediaTagType.DVD_CMI:
2020-08-22 21:37:02 +01:00
sidecar.OpticalDisc[0].CMI = new DumpType();
2017-12-30 00:32:21 +00:00
CSS_CPRM.LeadInCopyright? cmi =
CSS_CPRM.DecodeLeadInCopyright(imageFormat.ReadDiskTag(MediaTagType.DVD_CMI));
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
if(cmi.HasValue)
switch(cmi.Value.CopyrightType)
{
2017-12-30 00:32:21 +00:00
case CopyrightType.AACS:
sidecar.OpticalDisc[0].CopyProtection = "AACS";
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case CopyrightType.CSS:
sidecar.OpticalDisc[0].CopyProtection = "CSS";
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case CopyrightType.CPRM:
sidecar.OpticalDisc[0].CopyProtection = "CPRM";
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
}
2020-08-22 21:37:02 +01:00
sidecar.OpticalDisc[0].CMI.Checksums = Checksum.
GetChecksums(imageFormat.
ReadDiskTag(MediaTagType.
DVD_CMI)).
ToArray();
2017-12-30 00:32:21 +00:00
sidecar.OpticalDisc[0].CMI.Size =
imageFormat.ReadDiskTag(MediaTagType.DVD_CMI).Length;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case MediaTagType.DVD_DMI:
2020-08-22 21:37:02 +01:00
sidecar.OpticalDisc[0].DMI = new DumpType();
sidecar.OpticalDisc[0].DMI.Checksums = Checksum.
GetChecksums(imageFormat.
ReadDiskTag(MediaTagType.
DVD_DMI)).
ToArray();
2017-12-30 00:32:21 +00:00
sidecar.OpticalDisc[0].DMI.Size =
imageFormat.ReadDiskTag(MediaTagType.DVD_DMI).Length;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
if(DMI.IsXbox(imageFormat.ReadDiskTag(MediaTagType.DVD_DMI)))
{
2020-08-22 21:37:02 +01:00
dskType = MediaType.XGD;
sidecar.OpticalDisc[0].Dimensions = new DimensionsType
{
Diameter = 120
};
2017-12-30 00:32:21 +00:00
}
else if(DMI.IsXbox360(imageFormat.ReadDiskTag(MediaTagType.DVD_DMI)))
{
2020-08-22 21:37:02 +01:00
dskType = MediaType.XGD2;
sidecar.OpticalDisc[0].Dimensions = new DimensionsType
{
Diameter = 120
};
2017-12-30 00:32:21 +00:00
}
break;
case MediaTagType.DVD_PFI:
2020-08-22 21:37:02 +01:00
sidecar.OpticalDisc[0].PFI = new DumpType();
sidecar.OpticalDisc[0].PFI.Checksums = Checksum.
GetChecksums(imageFormat.
ReadDiskTag(MediaTagType.
DVD_PFI)).
ToArray();
2017-12-30 00:32:21 +00:00
sidecar.OpticalDisc[0].PFI.Size =
imageFormat.ReadDiskTag(MediaTagType.DVD_PFI).Length;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
PFI.PhysicalFormatInformation? pfi =
PFI.Decode(imageFormat.ReadDiskTag(MediaTagType.DVD_PFI));
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
if(pfi.HasValue)
2020-08-22 21:37:02 +01:00
if(dskType != MediaType.XGD &&
dskType != MediaType.XGD2 &&
2017-12-30 00:32:21 +00:00
dskType != MediaType.XGD3)
{
2017-12-30 00:32:21 +00:00
switch(pfi.Value.DiskCategory)
{
2017-12-30 00:32:21 +00:00
case DiskCategory.DVDPR:
dskType = MediaType.DVDPR;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case DiskCategory.DVDPRDL:
dskType = MediaType.DVDPRDL;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case DiskCategory.DVDPRW:
dskType = MediaType.DVDPRW;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case DiskCategory.DVDPRWDL:
dskType = MediaType.DVDPRWDL;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case DiskCategory.DVDR:
dskType = MediaType.DVDR;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case DiskCategory.DVDRAM:
dskType = MediaType.DVDRAM;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case DiskCategory.DVDROM:
dskType = MediaType.DVDROM;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case DiskCategory.DVDRW:
dskType = MediaType.DVDRW;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case DiskCategory.HDDVDR:
dskType = MediaType.HDDVDR;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case DiskCategory.HDDVDRAM:
dskType = MediaType.HDDVDRAM;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case DiskCategory.HDDVDROM:
dskType = MediaType.HDDVDROM;
2020-08-22 21:37:02 +01:00
break;
2017-12-30 00:32:21 +00:00
case DiskCategory.HDDVDRW:
dskType = MediaType.HDDVDRW;
2020-08-22 21:37:02 +01:00
break;
2017-12-30 00:32:21 +00:00
case DiskCategory.Nintendo:
dskType = MediaType.GOD;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case DiskCategory.UMD:
dskType = MediaType.UMD;
2020-08-22 21:37:02 +01:00
break;
}
2020-08-22 21:37:02 +01:00
if(dskType == MediaType.DVDR &&
pfi.Value.PartVersion == 6)
2017-12-30 00:32:21 +00:00
dskType = MediaType.DVDRDL;
2020-08-22 21:37:02 +01:00
if(dskType == MediaType.DVDRW &&
pfi.Value.PartVersion == 3)
2017-12-30 00:32:21 +00:00
dskType = MediaType.DVDRWDL;
2020-08-22 21:37:02 +01:00
if(dskType == MediaType.GOD &&
pfi.Value.DiscSize == DVDSize.OneTwenty)
2017-12-30 00:32:21 +00:00
dskType = MediaType.WOD;
2017-12-30 00:32:21 +00:00
sidecar.OpticalDisc[0].Dimensions = new DimensionsType();
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
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-12-30 00:32:21 +00:00
break;
case MediaTagType.CD_PMA:
2020-08-22 21:37:02 +01:00
sidecar.OpticalDisc[0].PMA = new DumpType();
sidecar.OpticalDisc[0].PMA.Checksums = Checksum.
GetChecksums(imageFormat.
ReadDiskTag(MediaTagType.
CD_PMA)).ToArray();
2017-12-30 00:32:21 +00:00
sidecar.OpticalDisc[0].PMA.Size =
imageFormat.ReadDiskTag(MediaTagType.CD_PMA).Length;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
}
2017-12-30 00:32:21 +00:00
}
2020-08-22 21:37:02 +01:00
#if DEBUG
2017-12-30 00:32:21 +00:00
stopwatch.Stop();
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
Console.WriteLine("Core.AddMedia(): Took {0} seconds to hash media tags",
stopwatch.Elapsed.TotalSeconds);
2020-08-22 21:37:02 +01:00
#endif
2017-12-30 00:32:21 +00:00
try
{
2020-08-22 21:37:02 +01:00
List<Session> sessions = imageFormat.Sessions;
2017-12-30 00:32:21 +00:00
sidecar.OpticalDisc[0].Sessions = sessions?.Count ?? 1;
}
2020-08-22 21:37:02 +01:00
catch
{
sidecar.OpticalDisc[0].Sessions = 1;
}
2017-12-30 00:32:21 +00:00
List<Track> tracks = imageFormat.Tracks;
List<TrackType> trksLst = null;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
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++;
2020-08-22 21:37:02 +01:00
var xmlTrk = new TrackType();
2017-12-30 00:32:21 +00:00
switch(trk.TrackType)
{
2017-12-30 00:32:21 +00:00
case DiscImageChef.DiscImages.TrackType.Audio:
xmlTrk.TrackType1 = TrackTypeTrackType.audio;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case DiscImageChef.DiscImages.TrackType.CdMode2Form2:
xmlTrk.TrackType1 = TrackTypeTrackType.m2f2;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case DiscImageChef.DiscImages.TrackType.CdMode2Formless:
xmlTrk.TrackType1 = TrackTypeTrackType.mode2;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case DiscImageChef.DiscImages.TrackType.CdMode2Form1:
xmlTrk.TrackType1 = TrackTypeTrackType.m2f1;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case DiscImageChef.DiscImages.TrackType.CdMode1:
xmlTrk.TrackType1 = TrackTypeTrackType.mode1;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case DiscImageChef.DiscImages.TrackType.Data:
switch(sidecar.OpticalDisc[0].DiscType)
{
case "BD":
xmlTrk.TrackType1 = TrackTypeTrackType.bluray;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case "DDCD":
xmlTrk.TrackType1 = TrackTypeTrackType.ddcd;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case "DVD":
xmlTrk.TrackType1 = TrackTypeTrackType.dvd;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case "HD DVD":
xmlTrk.TrackType1 = TrackTypeTrackType.hddvd;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
default:
xmlTrk.TrackType1 = TrackTypeTrackType.mode1;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
}
break;
}
2017-12-30 00:32:21 +00:00
xmlTrk.Sequence = new TrackSequenceType
{
2017-12-30 00:32:21 +00:00
Session = trk.TrackSession,
TrackNumber = (int)trk.TrackSequence
};
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
xmlTrk.StartSector = (long)trk.TrackStartSector;
xmlTrk.EndSector = (long)trk.TrackEndSector;
2020-08-22 21:37:02 +01:00
if(trk.Indexes != null &&
trk.Indexes.ContainsKey(0))
2017-12-30 00:32:21 +00:00
if(trk.Indexes.TryGetValue(0, out ulong idx0))
xmlTrk.StartSector = (long)idx0;
2017-12-30 00:32:21 +00:00
switch(sidecar.OpticalDisc[0].DiscType)
{
2017-12-30 00:32:21 +00:00
case "CD":
case "GD":
xmlTrk.StartMSF = LbaToMsf(xmlTrk.StartSector);
xmlTrk.EndMSF = LbaToMsf(xmlTrk.EndSector);
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case "DDCD":
xmlTrk.StartMSF = DdcdLbaToMsf(xmlTrk.StartSector);
xmlTrk.EndMSF = DdcdLbaToMsf(xmlTrk.EndSector);
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
}
2020-08-22 21:37:02 +01:00
xmlTrk.Image = new ImageType
{
Value = Path.GetFileName(trk.TrackFile)
};
2017-12-30 00:32:21 +00:00
if(trk.TrackFileOffset > 0)
{
2017-12-30 00:32:21 +00:00
xmlTrk.Image.offset = (long)trk.TrackFileOffset;
xmlTrk.Image.offsetSpecified = true;
}
2017-12-30 00:32:21 +00:00
xmlTrk.Image.format = trk.TrackFileType;
2020-08-22 21:37:02 +01:00
xmlTrk.Size = ((xmlTrk.EndSector - xmlTrk.StartSector) + 1) * trk.TrackRawBytesPerSector;
2017-12-30 00:32:21 +00:00
xmlTrk.BytesPerSector = trk.TrackBytesPerSector;
2017-12-30 00:32:21 +00:00
const uint SECTORS_TO_READ = 512;
2020-08-22 21:37:02 +01:00
ulong sectors = (ulong)((xmlTrk.EndSector - xmlTrk.StartSector) + 1);
2017-12-30 00:32:21 +00:00
ulong doneSectors = 0;
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);
2020-08-22 21:37:02 +01:00
var trkChkWorker = new Checksum();
2020-08-22 21:37:02 +01:00
#if DEBUG
2017-12-30 00:32:21 +00:00
stopwatch.Restart();
2020-08-22 21:37:02 +01:00
#endif
2017-12-30 00:32:21 +00:00
while(doneSectors < sectors)
{
byte[] sector;
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);
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
UpdateProgress2?.Invoke(null, $"Sector {doneSectors} of {sectors}",
(long)doneSectors, (long)sectors);
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
doneSectors += SECTORS_TO_READ;
}
else
{
sector = imageFormat.ReadSectorsLong(doneSectors, (uint)(sectors - doneSectors),
(uint)xmlTrk.Sequence.TrackNumber);
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
UpdateProgress2?.Invoke(null, $"Sector {doneSectors} of {sectors}",
(long)doneSectors, (long)sectors);
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
doneSectors += sectors - doneSectors;
}
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();
2020-08-22 21:37:02 +01:00
#if DEBUG
2017-12-30 00:32:21 +00:00
stopwatch.Stop();
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
Console.WriteLine("Core.AddMedia(): Took {0} seconds to hash track {1}",
stopwatch.Elapsed.TotalSeconds, trk.TrackSequence);
2020-08-22 21:37:02 +01:00
#endif
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-12-30 00:32:21 +00:00
if(trk.TrackSubchannelType != TrackSubchannelType.None)
{
UpdateProgress?.Invoke(null, $"Hashing subchannel of track {trk.TrackSequence}",
currentProgress, maxProgress);
2020-08-22 21:37:02 +01:00
xmlTrk.SubChannel = new SubChannelType
{
Image = new ImageType()
};
2017-12-30 00:32:21 +00:00
switch(trk.TrackSubchannelType)
{
case TrackSubchannelType.Packed:
case TrackSubchannelType.PackedInterleaved:
xmlTrk.SubChannel.Image.format = "rw";
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case TrackSubchannelType.Raw:
case TrackSubchannelType.RawInterleaved:
xmlTrk.SubChannel.Image.format = "rw_raw";
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case TrackSubchannelType.Q16:
case TrackSubchannelType.Q16Interleaved:
xmlTrk.SubChannel.Image.format = "q16";
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
2017-06-20 07:20:39 +01:00
}
2017-12-30 00:32:21 +00:00
if(trk.TrackFileOffset > 0)
{
2017-12-30 00:32:21 +00:00
xmlTrk.SubChannel.Image.offset = (long)trk.TrackSubchannelOffset;
xmlTrk.SubChannel.Image.offsetSpecified = true;
}
2017-12-30 00:32:21 +00:00
xmlTrk.SubChannel.Image.Value = trk.TrackSubchannelFile;
2017-12-30 00:32:21 +00:00
// TODO: Packed subchannel has different size?
2020-08-22 21:37:02 +01:00
xmlTrk.SubChannel.Size = ((xmlTrk.EndSector - xmlTrk.StartSector) + 1) * 96;
2020-08-22 21:37:02 +01:00
var subChkWorker = new Checksum();
2020-08-22 21:37:02 +01:00
sectors = (ulong)((xmlTrk.EndSector - xmlTrk.StartSector) + 1);
2017-12-30 00:32:21 +00:00
doneSectors = 0;
2020-08-22 21:37:02 +01:00
#if DEBUG
2017-12-30 00:32:21 +00:00
stopwatch.Restart();
2020-08-22 21:37:02 +01:00
#endif
2017-12-30 00:32:21 +00:00
while(doneSectors < sectors)
{
byte[] sector;
2017-12-30 00:32:21 +00:00
if(sectors - doneSectors >= SECTORS_TO_READ)
{
2017-12-30 00:32:21 +00:00
sector = imageFormat.ReadSectorsTag(doneSectors, SECTORS_TO_READ,
(uint)xmlTrk.Sequence.TrackNumber,
SectorTagType.CdSectorSubchannel);
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
UpdateProgress2?.Invoke(null, $"Sector {doneSectors} of {sectors}", position,
fi.Length);
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
doneSectors += SECTORS_TO_READ;
}
else
{
sector = imageFormat.ReadSectorsTag(doneSectors, (uint)(sectors - doneSectors),
(uint)xmlTrk.Sequence.TrackNumber,
SectorTagType.CdSectorSubchannel);
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
UpdateProgress2?.Invoke(null, $"Sector {doneSectors} of {sectors}", position,
fi.Length);
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
doneSectors += sectors - doneSectors;
}
2017-12-30 00:32:21 +00:00
subChkWorker.Update(sector);
}
2017-12-30 00:32:21 +00:00
List<ChecksumType> subChecksums = subChkWorker.End();
2017-12-30 00:32:21 +00:00
xmlTrk.SubChannel.Checksums = subChecksums.ToArray();
2020-08-22 21:37:02 +01:00
#if DEBUG
2017-12-30 00:32:21 +00:00
stopwatch.Stop();
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
Console.WriteLine("Core.AddMedia(): Took {0} seconds to hash subchannel of track {1}",
stopwatch.Elapsed.TotalSeconds, trk.TrackSequence);
2020-08-22 21:37:02 +01:00
#endif
2017-12-30 00:32:21 +00:00
UpdateProgress2?.Invoke(null, null, 0, 0);
}
2017-12-30 00:32:21 +00:00
UpdateProgress?.Invoke(null, "Checking filesystems", maxProgress - 1, maxProgress);
2020-08-22 21:37:02 +01:00
#if DEBUG
2017-12-30 00:32:21 +00:00
stopwatch.Restart();
2020-08-22 21:37:02 +01:00
#endif
2017-12-30 00:32:21 +00:00
List<Partition> partitions = new List<Partition>();
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-12-30 00:32:21 +00:00
xmlTrk.FileSystemInformation = new PartitionType[1];
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
if(partitions.Count > 0)
{
xmlTrk.FileSystemInformation = new PartitionType[partitions.Count];
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
for(int i = 0; i < partitions.Count; i++)
{
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
};
List<FileSystemType> lstFs = new List<FileSystemType>();
2017-12-30 00:32:21 +00:00
foreach(IFilesystem plugin in plugins.PluginsList.Values)
try
{
2020-08-22 21:37:02 +01:00
if(!plugin.Identify(imageFormat, partitions[i]))
continue;
2017-12-30 00:32:21 +00:00
plugin.GetInformation(imageFormat, partitions[i], out _, null);
lstFs.Add(plugin.XmlFsType);
2017-12-30 00:32:21 +00:00
switch(plugin.XmlFsType.Type)
{
case "Opera":
dskType = MediaType.ThreeDO;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case "PC Engine filesystem":
dskType = MediaType.SuperCDROM2;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case "Nintendo Wii filesystem":
dskType = MediaType.WOD;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case "Nintendo Gamecube filesystem":
dskType = MediaType.GOD;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
}
}
2017-12-30 00:32:21 +00:00
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
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
{
//DicConsole.DebugWriteLine("Create-sidecar command", "Plugin {0} crashed", _plugin.Name);
}
2020-08-22 21:37:02 +01:00
if(lstFs.Count > 0)
xmlTrk.FileSystemInformation[i].FileSystems = lstFs.ToArray();
}
}
2017-12-30 00:32:21 +00:00
else
{
xmlTrk.FileSystemInformation[0] = new PartitionType
{
EndSector = (int)xmlTrk.EndSector,
StartSector = (int)xmlTrk.StartSector
};
2020-08-22 21:37:02 +01:00
var xmlPart = new Partition
2017-12-30 00:32:21 +00:00
{
Start = (ulong)xmlTrk.StartSector,
2020-08-22 21:37:02 +01:00
Length = (ulong)((xmlTrk.EndSector - xmlTrk.StartSector) + 1)
2017-12-30 00:32:21 +00:00
};
2017-12-30 00:32:21 +00:00
List<FileSystemType> lstFs = new List<FileSystemType>();
2017-12-30 00:32:21 +00:00
foreach(IFilesystem _plugin in plugins.PluginsList.Values)
try
{
2020-08-22 21:37:02 +01:00
if(!_plugin.Identify(imageFormat, xmlPart))
continue;
2017-12-30 00:32:21 +00:00
_plugin.GetInformation(imageFormat, xmlPart, out _, null);
lstFs.Add(_plugin.XmlFsType);
2017-12-30 00:32:21 +00:00
switch(_plugin.XmlFsType.Type)
{
case "Opera":
dskType = MediaType.ThreeDO;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case "PC Engine filesystem":
dskType = MediaType.SuperCDROM2;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case "Nintendo Wii filesystem":
dskType = MediaType.WOD;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case "Nintendo Gamecube filesystem":
dskType = MediaType.GOD;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
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);
}
2020-08-22 21:37:02 +01:00
if(lstFs.Count > 0)
xmlTrk.FileSystemInformation[0].FileSystems = lstFs.ToArray();
}
2020-08-22 21:37:02 +01:00
#if DEBUG
2017-12-30 00:32:21 +00:00
stopwatch.Stop();
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
Console.WriteLine("Core.AddMedia(): Took {0} seconds to check all filesystems on track {1}",
stopwatch.Elapsed.TotalSeconds, trk.TrackSequence);
2020-08-22 21:37:02 +01:00
#endif
2017-12-30 00:32:21 +00:00
trksLst.Add(xmlTrk);
}
2017-12-30 00:32:21 +00:00
UpdateProgress?.Invoke(null, "Finishing", maxProgress, maxProgress);
2020-08-22 21:37:02 +01:00
if(trksLst != null)
sidecar.OpticalDisc[0].Track = trksLst.ToArray();
2017-12-30 00:32:21 +00:00
DiscImageChef.Metadata.MediaType.MediaTypeToString(dskType, out string dscType,
out string dscSubType);
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
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-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;
2020-08-22 21:37:02 +01:00
sidecar.OpticalDisc[0].DumpHardwareArray[0].Manufacturer =
2017-12-30 00:32:21 +00:00
imageFormat.Info.DriveManufacturer;
2020-08-22 21:37:02 +01:00
sidecar.OpticalDisc[0].DumpHardwareArray[0].Model = imageFormat.Info.DriveModel;
2017-12-30 00:32:21 +00:00
sidecar.OpticalDisc[0].DumpHardwareArray[0].Firmware =
imageFormat.Info.DriveFirmwareRevision;
2020-08-22 21:37:02 +01:00
sidecar.OpticalDisc[0].DumpHardwareArray[0].Serial = imageFormat.Info.DriveSerialNumber;
2017-12-30 00:32:21 +00:00
sidecar.OpticalDisc[0].DumpHardwareArray[0].Software = new SoftwareType
{
2017-12-30 00:32:21 +00:00
Name = imageFormat.Info.Application,
Version = imageFormat.Info.ApplicationVersion
};
}
2017-12-30 00:32:21 +00:00
Context.WorkingDisc = sidecar.OpticalDisc[0];
Finished?.Invoke();
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
return;
}
case XmlMediaType.BlockMedia:
{
maxProgress = 3 + imageFormat.Info.ReadableMediaTags.Count;
UpdateProgress?.Invoke(null, "Hashing image file", 3, maxProgress);
2020-08-22 21:37:02 +01:00
sidecar.BlockMedia = new BlockMediaType[1];
2017-12-30 00:32:21 +00:00
sidecar.BlockMedia[0] = new BlockMediaType
{
Checksums = imgChecksums.ToArray(),
2020-08-22 21:37:02 +01:00
Image = new ImageType
{
2017-12-30 00:32:21 +00:00
format = imageFormat.Format,
offset = 0,
offsetSpecified = true,
Value = Path.GetFileName(selectedFile)
},
2020-08-22 21:37:02 +01:00
Size = fi.Length,
Sequence = new SequenceType
{
MediaTitle = imageFormat.Info.MediaTitle
}
2017-12-30 00:32:21 +00:00
};
2020-08-22 21:37:02 +01:00
if(imageFormat.Info.MediaSequence != 0 &&
imageFormat.Info.LastMediaSequence != 0)
2017-12-30 00:32:21 +00:00
{
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;
2020-08-22 21:37:02 +01:00
#if DEBUG
2017-12-30 00:32:21 +00:00
stopwatch.Restart();
2020-08-22 21:37:02 +01:00
#endif
2017-12-30 00:32:21 +00:00
foreach(MediaTagType tagType in imageFormat.Info.ReadableMediaTags)
{
currentProgress++;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
UpdateProgress?.Invoke(null, $"Hashing file containing {tagType}", currentProgress,
maxProgress);
switch(tagType)
{
case MediaTagType.ATAPI_IDENTIFY:
2020-08-22 21:37:02 +01:00
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();
2017-12-30 00:32:21 +00:00
sidecar.BlockMedia[0].ATA.Identify.Size =
imageFormat.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY).Length;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case MediaTagType.ATA_IDENTIFY:
2020-08-22 21:37:02 +01:00
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();
2017-12-30 00:32:21 +00:00
sidecar.BlockMedia[0].ATA.Identify.Size =
imageFormat.ReadDiskTag(MediaTagType.ATA_IDENTIFY).Length;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case MediaTagType.PCMCIA_CIS:
2020-08-22 21:37:02 +01:00
byte[] cis = imageFormat.ReadDiskTag(MediaTagType.PCMCIA_CIS);
2017-12-30 00:32:21 +00:00
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;
2020-08-22 21:37:02 +01:00
Tuple[] tuples = CIS.GetTuples(cis);
2017-12-30 00:32:21 +00:00
if(tuples != null)
foreach(Tuple tuple in tuples)
if(tuple.Code == TupleCodes.CISTPL_MANFID)
{
2017-12-30 00:32:21 +00:00
ManufacturerIdentificationTuple manfid =
CIS.DecodeManufacturerIdentificationTuple(tuple);
if(manfid != null)
{
2017-12-30 00:32:21 +00:00
sidecar.BlockMedia[0].PCMCIA.ManufacturerCode =
manfid.ManufacturerID;
2020-08-22 21:37:02 +01:00
sidecar.BlockMedia[0].PCMCIA.CardCode = manfid.CardID;
2017-12-30 00:32:21 +00:00
sidecar.BlockMedia[0].PCMCIA.ManufacturerCodeSpecified = true;
2020-08-22 21:37:02 +01:00
sidecar.BlockMedia[0].PCMCIA.CardCodeSpecified = true;
}
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-12-30 00:32:21 +00:00
sidecar.BlockMedia[0].PCMCIA.Manufacturer = vers.Manufacturer;
sidecar.BlockMedia[0].PCMCIA.ProductName = vers.Product;
2020-08-22 21:37:02 +01:00
sidecar.BlockMedia[0].PCMCIA.Compliance =
2017-12-30 00:32:21 +00:00
$"{vers.MajorVersion}.{vers.MinorVersion}";
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
sidecar.BlockMedia[0].PCMCIA.AdditionalInformation =
vers.AdditionalInformation;
}
}
2017-12-30 00:32:21 +00:00
break;
case MediaTagType.SCSI_INQUIRY:
2020-08-22 21:37:02 +01:00
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();
2017-12-30 00:32:21 +00:00
sidecar.BlockMedia[0].SCSI.Inquiry.Size =
imageFormat.ReadDiskTag(MediaTagType.SCSI_INQUIRY).Length;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case MediaTagType.SD_CID:
if(sidecar.BlockMedia[0].SecureDigital == null)
2020-08-22 21:37:02 +01:00
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();
2017-12-30 00:32:21 +00:00
sidecar.BlockMedia[0].SecureDigital.CID.Size =
imageFormat.ReadDiskTag(MediaTagType.SD_CID).Length;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case MediaTagType.SD_CSD:
if(sidecar.BlockMedia[0].SecureDigital == null)
2020-08-22 21:37:02 +01:00
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();
2017-12-30 00:32:21 +00:00
sidecar.BlockMedia[0].SecureDigital.CSD.Size =
imageFormat.ReadDiskTag(MediaTagType.SD_CSD).Length;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
case MediaTagType.MMC_ExtendedCSD:
if(sidecar.BlockMedia[0].SecureDigital == null)
2020-08-22 21:37:02 +01:00
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();
2017-12-30 00:32:21 +00:00
sidecar.BlockMedia[0].MultiMediaCard.ExtendedCSD.Size =
imageFormat.ReadDiskTag(MediaTagType.MMC_ExtendedCSD).Length;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
break;
2017-06-20 07:20:39 +01:00
}
2017-12-30 00:32:21 +00:00
}
2020-08-22 21:37:02 +01:00
#if DEBUG
2017-12-30 00:32:21 +00:00
stopwatch.Stop();
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
Console.WriteLine("Core.AddMedia(): Took {0} seconds to hash media tags",
stopwatch.Elapsed.TotalSeconds);
2020-08-22 21:37:02 +01:00
#endif
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"))
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
2020-08-22 21:37:02 +01:00
var cntChkWorker = new Checksum();
2017-06-20 07:20:39 +01:00
2020-08-22 21:37:02 +01:00
#if DEBUG
2017-12-30 00:32:21 +00:00
stopwatch.Restart();
2020-08-22 21:37:02 +01:00
#endif
2017-12-30 00:32:21 +00:00
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);
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
UpdateProgress2?.Invoke(null, $"Sector {doneSectors} of {sectors}",
(long)doneSectors, (long)sectors);
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
doneSectors += SECTORS_TO_READ;
}
else
{
sector = imageFormat.ReadSectors(doneSectors, (uint)(sectors - doneSectors));
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
UpdateProgress2?.Invoke(null, $"Sector {doneSectors} of {sectors}",
(long)doneSectors, (long)sectors);
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
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();
2020-08-22 21:37:02 +01:00
#if DEBUG
2017-12-30 00:32:21 +00:00
stopwatch.Stop();
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
Console.WriteLine("Core.AddMedia(): Took {0} seconds to hash media contents",
stopwatch.Elapsed.TotalSeconds);
2020-08-22 21:37:02 +01:00
#endif
2017-12-30 00:32:21 +00:00
sidecar.BlockMedia[0].ContentChecksums = cntChecksums.ToArray();
}
2017-12-30 00:32:21 +00:00
DiscImageChef.Metadata.MediaType.MediaTypeToString(imageFormat.Info.MediaType,
out string dskType, out string dskSubType);
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
sidecar.BlockMedia[0].DiskType = dskType;
sidecar.BlockMedia[0].DiskSubType = dskSubType;
2017-12-30 00:32:21 +00:00
sidecar.BlockMedia[0].Dimensions =
Dimensions.DimensionsFromMediaType(imageFormat.Info.MediaType);
2017-12-30 00:32:21 +00:00
sidecar.BlockMedia[0].LogicalBlocks = (long)imageFormat.Info.Sectors;
sidecar.BlockMedia[0].LogicalBlockSize = (int)imageFormat.Info.SectorSize;
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
// TODO: Detect it
sidecar.BlockMedia[0].PhysicalBlockSize = (int)imageFormat.Info.SectorSize;
2017-12-30 00:32:21 +00:00
UpdateProgress?.Invoke(null, "Checking filesystems", maxProgress - 1, maxProgress);
2020-08-22 21:37:02 +01:00
#if DEBUG
2017-12-30 00:32:21 +00:00
stopwatch.Restart();
2020-08-22 21:37:02 +01:00
#endif
2017-12-30 00:32:21 +00:00
List<Partition> partitions = new List<Partition>();
2017-12-30 00:32:21 +00:00
foreach(IPartition partplugin in plugins.PartPluginsList.Values)
{
2020-08-22 21:37:02 +01:00
if(!partplugin.GetInformation(imageFormat, out partitions, 0))
continue;
2017-12-30 00:32:21 +00:00
break;
}
2017-12-30 00:32:21 +00:00
sidecar.BlockMedia[0].FileSystemInformation = new PartitionType[1];
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
if(partitions.Count > 0)
{
sidecar.BlockMedia[0].FileSystemInformation = new PartitionType[partitions.Count];
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
for(int i = 0; i < partitions.Count; i++)
{
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
};
List<FileSystemType> lstFs = new List<FileSystemType>();
2017-12-30 00:32:21 +00:00
foreach(IFilesystem plugin in plugins.PluginsList.Values)
try
{
2020-08-22 21:37:02 +01:00
if(!plugin.Identify(imageFormat, partitions[i]))
continue;
2017-12-30 00:32:21 +00:00
plugin.GetInformation(imageFormat, partitions[i], out _, null);
lstFs.Add(plugin.XmlFsType);
}
2017-12-30 00:32:21 +00:00
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
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
{
//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-12-30 00:32:21 +00:00
else
{
2017-12-30 00:32:21 +00:00
sidecar.BlockMedia[0].FileSystemInformation[0] = new PartitionType
{
StartSector = 0,
EndSector = (int)(imageFormat.Info.Sectors - 1)
};
2020-08-22 21:37:02 +01:00
var wholePart = new Partition
{
Start = 0,
Length = imageFormat.Info.Sectors
};
2017-12-30 00:32:21 +00:00
List<FileSystemType> lstFs = new List<FileSystemType>();
foreach(IFilesystem _plugin in plugins.PluginsList.Values)
try
{
2020-08-22 21:37:02 +01:00
if(!_plugin.Identify(imageFormat, wholePart))
continue;
2017-12-30 00:32:21 +00:00
_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();
}
2020-08-22 21:37:02 +01:00
#if DEBUG
2017-12-30 00:32:21 +00:00
stopwatch.Stop();
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
Console.WriteLine("Core.AddMedia(): Took {0} seconds to check all filesystems",
stopwatch.Elapsed.TotalSeconds);
2020-08-22 21:37:02 +01:00
#endif
2017-12-30 00:32:21 +00:00
// TODO: Implement support for getting CHS
UpdateProgress?.Invoke(null, "Finishing", maxProgress, maxProgress);
Context.WorkingDisk = sidecar.BlockMedia[0];
Finished?.Invoke();
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
return;
}
case XmlMediaType.LinearMedia:
{
Failed?.Invoke("Linear media not yet supported.");
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
return;
}
case XmlMediaType.AudioMedia:
2017-12-30 00:32:21 +00:00
{
Failed?.Invoke("Audio media not yet supported.");
2020-08-22 21:37:02 +01:00
2017-12-30 00:32:21 +00:00
return;
}
}
2017-12-30 00:32:21 +00:00
Failed?.Invoke("Should've not arrived here.");
}
catch(Exception ex)
{
2017-12-30 00:32:21 +00:00
Failed?.Invoke($"Error reading file: {ex.Message}\n{ex.StackTrace}");
2020-08-22 21:37:02 +01:00
#if DEBUG
2017-06-13 18:21:12 +01:00
Console.WriteLine("Exception {0}\n{1}", ex.Message, ex.InnerException);
2020-08-22 21:37:02 +01:00
#endif
}
}
static string LbaToMsf(long lba)
{
long m, s, f;
2020-08-22 21:37:02 +01:00
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;
}
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-12-30 00:32:21 +00:00
return $"{m}:{s:D2}:{f:D2}";
}
static string DdcdLbaToMsf(long lba)
{
long h, m, s, f;
2020-08-22 21:37:02 +01:00
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;
}
else
{
2020-08-22 21:37:02 +01: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);
}
return string.Format("{3}:{0:D2}:{1:D2}:{2:D2}", m, s, f, h);
}
}
2017-12-30 00:32:21 +00:00
}