Added creation of Alcohol 120% media descriptor files when

dumping optical media.
This commit is contained in:
2017-11-26 18:23:50 +00:00
parent 42e957f7a9
commit e01a060af9
5 changed files with 624 additions and 6 deletions

View File

@@ -36,12 +36,541 @@
// ****************************************************************************/ // ****************************************************************************/
// //$Id$ // //$Id$
using System; using System;
using System.Runtime.InteropServices;
using System.IO;
using System.Collections.Generic;
using System.Text;
using DiscImageChef.CommonTypes;
using DiscImageChef.ImagePlugins;
namespace DiscImageChef.Core.Devices.Dumping namespace DiscImageChef.Core.Devices.Dumping
{ {
// TODO: For >4.0, this class must disappear
public class Alcohol120 public class Alcohol120
{ {
public Alcohol120() #region Internal Structures
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AlcoholHeader
{ {
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string signature;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public byte[] version;
public AlcoholMediumType type;
public ushort sessions;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public ushort[] unknown1;
public ushort bcaLength;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public uint[] unknown2;
public uint bcaOffset;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public uint[] unknown3;
public uint structuresOffset;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public uint[] unknown4;
public uint sessionOffset;
public uint dpmOffset;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AlcoholSession
{
public int sessionStart;
public int sessionEnd;
public ushort sessionSequence;
public byte allBlocks;
public byte nonTrackBlocks;
public ushort firstTrack;
public ushort lastTrack;
public uint unknown;
public uint trackOffset;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AlcoholTrack
{
public AlcoholTrackMode mode;
public AlcoholSubchannelMode subMode;
public byte adrCtl;
public byte tno;
public byte point;
public byte min;
public byte sec;
public byte frame;
public byte zero;
public byte pmin;
public byte psec;
public byte pframe;
public uint extraOffset;
public ushort sectorSize;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 18)]
public byte[] unknown;
public uint startLba;
public ulong startOffset;
public uint files;
public uint footerOffset;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 24)]
public byte[] unknown2;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AlcoholTrackExtra
{
public uint pregap;
public uint sectors;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AlcoholFooter
{
public uint filenameOffset;
public uint widechar;
public uint unknown1;
public uint unknown2;
}
#endregion Internal Structures
#region Internal enumerations
enum AlcoholMediumType : ushort
{
CD = 0x00,
CDR = 0x01,
CDRW = 0x02,
DVD = 0x10,
DVDR = 0x12
}
enum AlcoholTrackMode : byte
{
NoData = 0x00,
DVD = 0x02,
Audio = 0xA9,
Mode1 = 0xAA,
Mode2 = 0xAB,
Mode2F1 = 0xAC,
Mode2F2 = 0xAD,
}
enum AlcoholSubchannelMode : byte
{
None = 0x00,
Interleaved = 0x08
}
#endregion Internal enumerations
string outputPrefix;
string extension;
byte[] bca;
byte[] pfi;
byte[] dmi;
AlcoholHeader header;
List<AlcoholTrack> tracks;
List<AlcoholSession> sessions;
Dictionary<byte, uint> trackLengths;
AlcoholFooter footer;
public Alcohol120(string outputPrefix)
{
this.outputPrefix = outputPrefix;
header = new AlcoholHeader
{
signature = "MEDIA DESCRIPTOR",
unknown1 = new ushort[] { 0x0002, 0x0000 },
unknown2 = new uint[2],
unknown3 = new uint[6],
unknown4 = new uint[3],
version = new byte[] { 1, 5 }
};
header.version[0] = 1;
header.version[1] = 5;
tracks = new List<AlcoholTrack>();
sessions = new List<AlcoholSession>();
trackLengths = new Dictionary<byte, uint>();
footer = new AlcoholFooter { widechar = 1 };
}
public void Close()
{
if(sessions.Count == 0 || tracks.Count == 0)
return;
// Calculate first offsets
header.sessions = (ushort)sessions.Count;
header.sessionOffset = 88;
long nextOffset = 88 + sessions.Count * 24;
// Calculate session blocks
AlcoholSession[] sessionsArray = sessions.ToArray();
for(int i = 0; i < sessionsArray.Length; i++)
{
sessionsArray[i].allBlocks = (byte)(((sessionsArray[i].lastTrack - sessionsArray[i].firstTrack) + 1) +
sessionsArray[i].nonTrackBlocks);
sessionsArray[i].trackOffset = (uint)nextOffset;
nextOffset += sessionsArray[i].allBlocks * 80;
}
// Calculate track blocks
AlcoholTrack[] tracksArray = tracks.ToArray();
AlcoholTrackExtra[] extrasArray = new AlcoholTrackExtra[trackLengths.Count];
for(int i = 0; i < tracksArray.Length; i++)
{
if(tracksArray[i].point >= 0xA0) continue;
if(!trackLengths.TryGetValue(tracksArray[i].point, out uint trkLen)) continue;
if(tracksArray[i].mode == AlcoholTrackMode.DVD)
{
tracksArray[i].extraOffset = trkLen;
}
else
{
AlcoholTrackExtra extra = new AlcoholTrackExtra();
if(tracksArray[i].point == 1)
{
extra.pregap = 150;
sessionsArray[0].sessionStart = -150;
}
extra.sectors = trkLen;
extrasArray[tracksArray[i].point - 1] = extra;
tracksArray[i].extraOffset = (uint)nextOffset;
nextOffset += 8;
}
}
// DVD things
if(bca != null && bca.Length > 0)
{
header.bcaOffset = (uint)nextOffset;
header.bcaLength = (ushort)bca.Length;
nextOffset += bca.Length;
}
if(pfi != null && pfi.Length > 0 && dmi != null && dmi.Length > 0)
{
header.structuresOffset = (uint)nextOffset;
nextOffset += 4100;
}
for(int i = 0; i < tracksArray.Length; i++)
tracksArray[i].footerOffset = (uint)nextOffset;
footer.filenameOffset = (uint)(nextOffset + 16);
byte[] filename = Encoding.Unicode.GetBytes(outputPrefix + extension);
// Open descriptor file here
FileStream descriptorFile = new FileStream(outputPrefix + ".mds", FileMode.Create, FileAccess.ReadWrite, FileShare.None);
byte[] tmp = new byte[88];
IntPtr hdrPtr = Marshal.AllocHGlobal(88);
Marshal.StructureToPtr(header, hdrPtr, false);
Marshal.Copy(hdrPtr, tmp, 0, 88);
descriptorFile.Write(tmp, 0, tmp.Length);
foreach(AlcoholSession session in sessionsArray)
{
tmp = new byte[24];
IntPtr sesPtr = Marshal.AllocHGlobal(24);
Marshal.StructureToPtr(session, sesPtr, false);
Marshal.Copy(sesPtr, tmp, 0, 24);
descriptorFile.Write(tmp, 0, tmp.Length);
Marshal.FreeHGlobal(sesPtr);
}
foreach(AlcoholTrack track in tracksArray)
{
tmp = new byte[80];
IntPtr trkPtr = Marshal.AllocHGlobal(80);
Marshal.StructureToPtr(track, trkPtr, false);
Marshal.Copy(trkPtr, tmp, 0, 80);
descriptorFile.Write(tmp, 0, tmp.Length);
Marshal.FreeHGlobal(trkPtr);
}
if(header.type == AlcoholMediumType.CD || header.type == AlcoholMediumType.CDR || header.type == AlcoholMediumType.CDRW)
{
foreach(AlcoholTrackExtra extra in extrasArray)
{
tmp = new byte[8];
IntPtr trkxPtr = Marshal.AllocHGlobal(8);
Marshal.StructureToPtr(extra, trkxPtr, false);
Marshal.Copy(trkxPtr, tmp, 0, 8);
descriptorFile.Write(tmp, 0, tmp.Length);
Marshal.FreeHGlobal(trkxPtr);
}
}
if(bca != null && bca.Length > 0)
{
header.bcaOffset = (uint)descriptorFile.Position;
header.bcaLength = (ushort)bca.Length;
descriptorFile.Write(bca, 0, bca.Length);
}
if(pfi != null && pfi.Length > 0 && dmi != null && dmi.Length > 0)
{
descriptorFile.Write(new byte[4], 0, 4);
descriptorFile.Write(dmi, 0, 2048);
descriptorFile.Write(pfi, 0, 2048);
}
tmp = new byte[16];
IntPtr ftrPtr = Marshal.AllocHGlobal(16);
Marshal.StructureToPtr(footer, ftrPtr, false);
Marshal.Copy(ftrPtr, tmp, 0, 16);
Marshal.FreeHGlobal(ftrPtr);
descriptorFile.Write(tmp, 0, tmp.Length);
descriptorFile.Write(filename, 0, filename.Length);
// This is because of marshalling strings
descriptorFile.Position = 15;
descriptorFile.WriteByte(0x52);
descriptorFile.Dispose();
}
public void SetMediaType(MediaType type)
{
switch(type)
{
case MediaType.DVDDownload:
case MediaType.DVDPR:
case MediaType.DVDPRDL:
case MediaType.DVDPRW:
case MediaType.DVDPRWDL:
case MediaType.DVDR:
case MediaType.DVDRAM:
case MediaType.DVDRDL:
case MediaType.DVDRW:
case MediaType.DVDRWDL:
header.type = AlcoholMediumType.DVDR;
break;
case MediaType.CD:
case MediaType.CDDA:
case MediaType.CDEG:
case MediaType.CDG:
case MediaType.CDI:
case MediaType.CDMIDI:
case MediaType.CDPLUS:
case MediaType.CDROM:
case MediaType.CDROMXA:
case MediaType.CDV:
case MediaType.DDCD:
case MediaType.DTSCD:
case MediaType.JaguarCD:
case MediaType.MEGACD:
case MediaType.PCD:
case MediaType.PS1CD:
case MediaType.PS2CD:
case MediaType.SATURNCD:
case MediaType.SuperCDROM2:
case MediaType.SVCD:
case MediaType.VCD:
case MediaType.VCDHD:
case MediaType.GDROM:
case MediaType.ThreeDO:
header.type = AlcoholMediumType.CD;
break;
case MediaType.CDR:
case MediaType.DDCDR:
case MediaType.GDR:
header.type = AlcoholMediumType.CDR;
break;
case MediaType.CDRW:
case MediaType.DDCDRW:
case MediaType.CDMO:
case MediaType.CDMRW:
header.type = AlcoholMediumType.CDRW;
break;
default:
header.type = AlcoholMediumType.DVD;
break;
}
}
public void AddSessions(Session[] cdSessions)
{
foreach(Session cdSession in cdSessions)
{
System.Console.WriteLine("AddSession(start: {0}, end: {1}, sequence: {2}", cdSession.StartTrack, cdSession.EndTrack, cdSession.SessionSequence);
AlcoholSession session = new AlcoholSession
{
firstTrack = (ushort)cdSession.StartTrack,
lastTrack = (ushort)cdSession.EndTrack,
sessionSequence = cdSession.SessionSequence
};
sessions.Add(session);
}
}
public void SetTrackTypes(byte point, TrackType mode, TrackSubchannelType subMode)
{
System.Console.WriteLine("SetTrackTypes(point: {0}, mode: {1}, subMode: {2}", point, mode, subMode);
AlcoholTrack[] trkArray = tracks.ToArray();
for(int i = 0; i < trkArray.Length; i++)
{
if(trkArray[i].point != point) continue;
switch(mode)
{
case TrackType.Audio:
trkArray[i].mode = AlcoholTrackMode.Audio;
break;
case TrackType.Data:
trkArray[i].mode = AlcoholTrackMode.DVD;
break;
case TrackType.CDMode1:
trkArray[i].mode = AlcoholTrackMode.Mode1;
break;
case TrackType.CDMode2Formless:
trkArray[i].mode = AlcoholTrackMode.Mode2;
break;
case TrackType.CDMode2Form1:
trkArray[i].mode = AlcoholTrackMode.Mode2F1;
break;
case TrackType.CDMode2Form2:
trkArray[i].mode = AlcoholTrackMode.Mode2F2;
break;
default:
throw new ArgumentOutOfRangeException(nameof(mode), mode, null);
}
switch(subMode)
{
case TrackSubchannelType.None:
trkArray[i].subMode = AlcoholSubchannelMode.None;
break;
case TrackSubchannelType.RawInterleaved:
trkArray[i].subMode = AlcoholSubchannelMode.Interleaved;
break;
case TrackSubchannelType.Packed:
case TrackSubchannelType.Raw:
case TrackSubchannelType.PackedInterleaved:
case TrackSubchannelType.Q16:
case TrackSubchannelType.Q16Interleaved:
throw new FeatureUnsupportedImageException("Specified subchannel type is not supported.");
default:
throw new ArgumentOutOfRangeException(nameof(subMode), subMode, null);
}
tracks = new List<AlcoholTrack>(trkArray);
break;
}
}
public void SetTrackSizes(byte point, int sectorSize, long startLba, long startOffset, long length)
{
System.Console.WriteLine("SetTrackSizes(point: {0}, sectorSize: {1}, startOffset: {2}, length: {3}", point, sectorSize, startOffset, length);
AlcoholTrack[] trkArray = tracks.ToArray();
for(int i = 0; i < trkArray.Length; i++)
{
if(trkArray[i].point != point) continue;
trkArray[i].sectorSize = (ushort)sectorSize;
trkArray[i].startLba = (uint)startLba;
trkArray[i].startOffset = (ulong)startOffset;
tracks = new List<AlcoholTrack>(trkArray);
break;
}
if(trackLengths.ContainsKey(point))
trackLengths.Remove(point);
trackLengths.Add(point, (uint)length);
AlcoholSession[] sess = sessions.ToArray();
for(int i = 0; i < sess.Length; i++)
{
if(sess[i].firstTrack == point)
sess[i].sessionStart = (int)startLba;
if(sess[i].lastTrack == point)
sess[i].sessionEnd = (int)(startLba + length);
}
sessions = new List<AlcoholSession>(sess);
}
public void AddTrack(byte adrCtl, byte tno, byte point, byte min, byte sec, byte frame, byte zero, byte pmin,
byte psec, byte pframe, byte session)
{
System.Console.WriteLine("AddTrack(adrCtl: {0}, tno: {1}, point: {2}, min: {3}, sec: {4}, frame: {5}, zero: {6}, pmin: {7}, psec: {8}, pframe: {9}, session: {10}",
adrCtl, tno, point, min, sec, frame, zero, pmin, psec, pframe, session);
AlcoholTrack trk = new AlcoholTrack
{
mode = AlcoholTrackMode.NoData,
subMode = AlcoholSubchannelMode.None,
adrCtl = adrCtl,
tno = tno,
point = point,
min = min,
sec = sec,
frame = frame,
zero = zero,
pmin = pmin,
psec = psec,
pframe = pframe,
unknown = new byte[18],
files = 1,
unknown2 = new byte[24]
};
tracks.Add(trk);
if(point < 0xA0) return;
AlcoholSession[] sess = sessions.ToArray();
for(int i = 0; i < sess.Length; i++)
{
if(sess[i].sessionSequence == session)
sess[i].nonTrackBlocks++;
}
sessions = new List<AlcoholSession>(sess);
}
public void AddBCA(byte[] bca)
{
this.bca = bca;
}
public void AddPFI(byte[] pfi)
{
if(pfi.Length == 2052)
{
this.pfi = new byte[2048];
Array.Copy(pfi, 4, this.pfi, 0, 2048);
}
else
this.pfi = pfi;
}
public void AddDMI(byte[] dmi)
{
if(dmi.Length == 2052)
{
this.dmi = new byte[2048];
Array.Copy(dmi, 4, this.dmi, 0, 2048);
}
else
this.dmi = dmi;
}
public void SetExtension(string extension)
{
this.extension = extension;
} }
} }
} }

View File

@@ -38,7 +38,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using DiscImageChef.CommonTypes;
using DiscImageChef.Console; using DiscImageChef.Console;
using DiscImageChef.Core.Logging; using DiscImageChef.Core.Logging;
using DiscImageChef.Devices; using DiscImageChef.Devices;
@@ -49,10 +48,16 @@ using Extents;
namespace DiscImageChef.Core.Devices.Dumping namespace DiscImageChef.Core.Devices.Dumping
{ {
using ImagePlugins;
using Metadata;
using MediaType = CommonTypes.MediaType;
using Session = Decoders.CD.Session;
using TrackType = Schemas.TrackType;
internal class CompactDisc internal class CompactDisc
{ {
// TODO: Add support for resume file // TODO: Add support for resume file
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar, ref MediaType dskType, bool separateSubchannel, ref Metadata.Resume resume, ref DumpLog dumpLog) internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar, ref MediaType dskType, bool separateSubchannel, ref Resume resume, ref DumpLog dumpLog, Alcohol120 alcohol)
{ {
MHDDLog mhddLog; MHDDLog mhddLog;
IBGLog ibgLog; IBGLog ibgLog;
@@ -262,6 +267,30 @@ namespace DiscImageChef.Core.Devices.Dumping
return; return;
} }
ImagePlugins.Session[] sessionsForAlcohol = new ImagePlugins.Session[toc.Value.LastCompleteSession];
for(int i = 0; i < sessionsForAlcohol.Length; i++)
{
sessionsForAlcohol[i].SessionSequence = (ushort)(i + 1);
sessionsForAlcohol[i].StartTrack = ushort.MaxValue;
}
foreach(FullTOC.TrackDataDescriptor trk in toc.Value.TrackDescriptors)
{
if(trk.POINT > 0 && trk.POINT < 0xA0 && trk.SessionNumber <= sessionsForAlcohol.Length)
{
if(trk.POINT < sessionsForAlcohol[trk.SessionNumber - 1].StartTrack)
sessionsForAlcohol[trk.SessionNumber - 1].StartTrack = trk.POINT;
if(trk.POINT > sessionsForAlcohol[trk.SessionNumber - 1].EndTrack)
sessionsForAlcohol[trk.SessionNumber - 1].EndTrack = trk.POINT;
}
}
alcohol.AddSessions(sessionsForAlcohol);
foreach(FullTOC.TrackDataDescriptor trk in toc.Value.TrackDescriptors)
{
alcohol.AddTrack((byte)((trk.ADR << 4) & trk.CONTROL), trk.TNO, trk.POINT, trk.Min, trk.Sec, trk.Frame,
trk.Zero, trk.PMIN, trk.PSEC, trk.PFRAME, trk.SessionNumber);
}
FullTOC.TrackDataDescriptor[] sortedTracks = toc.Value.TrackDescriptors.OrderBy(track => track.POINT).ToArray(); FullTOC.TrackDataDescriptor[] sortedTracks = toc.Value.TrackDescriptors.OrderBy(track => track.POINT).ToArray();
List<TrackType> trackList = new List<TrackType>(); List<TrackType> trackList = new List<TrackType>();
long lastSector = 0; long lastSector = 0;
@@ -494,8 +523,10 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpLog.WriteLine("Device reports {0} bytes per logical block.", blockSize); dumpLog.WriteLine("Device reports {0} bytes per logical block.", blockSize);
dumpLog.WriteLine("SCSI device type: {0}.", dev.SCSIType); dumpLog.WriteLine("SCSI device type: {0}.", dev.SCSIType);
dumpLog.WriteLine("Media identified as {0}.", dskType); dumpLog.WriteLine("Media identified as {0}.", dskType);
alcohol.SetMediaType(dskType);
dumpFile = new DataFile(outputPrefix + ".bin"); dumpFile = new DataFile(outputPrefix + ".bin");
alcohol.SetExtension(".bin");
DataFile subFile = null; DataFile subFile = null;
if(separateSubchannel) if(separateSubchannel)
subFile = new DataFile(outputPrefix + ".sub"); subFile = new DataFile(outputPrefix + ".sub");
@@ -543,6 +574,8 @@ namespace DiscImageChef.Core.Devices.Dumping
tracks[t].SubChannel.Image.Value = tracks[t].Image.Value; tracks[t].SubChannel.Image.Value = tracks[t].Image.Value;
} }
alcohol.SetTrackSizes((byte)(t + 1), sectorSize, tracks[t].StartSector, dumpFile.Position, (tracks[t].EndSector - tracks[t].StartSector + 1));
bool checkedDataFormat = false; bool checkedDataFormat = false;
for(ulong i = resume.NextBlock; i <= (ulong)tracks[t].EndSector; i += blocksToRead) for(ulong i = resume.NextBlock; i <= (ulong)tracks[t].EndSector; i += blocksToRead)
@@ -648,6 +681,38 @@ namespace DiscImageChef.Core.Devices.Dumping
#pragma warning restore IDE0004 // Remove Unnecessary Cast #pragma warning restore IDE0004 // Remove Unnecessary Cast
resume.NextBlock = i + blocksToRead; resume.NextBlock = i + blocksToRead;
} }
ImagePlugins.TrackType trkType;
switch(tracks[t].TrackType1)
{
case TrackTypeTrackType.audio:
trkType = ImagePlugins.TrackType.Audio;
break;
case TrackTypeTrackType.mode1:
trkType = ImagePlugins.TrackType.CDMode1;
break;
case TrackTypeTrackType.mode2:
trkType = ImagePlugins.TrackType.CDMode2Formless;
break;
case TrackTypeTrackType.m2f1:
trkType = ImagePlugins.TrackType.CDMode2Form1;
break;
case TrackTypeTrackType.m2f2:
trkType = ImagePlugins.TrackType.CDMode2Form2;
break;
case TrackTypeTrackType.dvd:
case TrackTypeTrackType.hddvd:
case TrackTypeTrackType.bluray:
case TrackTypeTrackType.ddcd:
case TrackTypeTrackType.mode0:
trkType = ImagePlugins.TrackType.Data;
break;
default:
throw new ArgumentOutOfRangeException();
}
alcohol.SetTrackTypes((byte)(t + 1), trkType,
separateSubchannel ? TrackSubchannelType.None : TrackSubchannelType.RawInterleaved);
} }
DicConsole.WriteLine(); DicConsole.WriteLine();
end = DateTime.UtcNow; end = DateTime.UtcNow;
@@ -892,6 +957,7 @@ namespace DiscImageChef.Core.Devices.Dumping
System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType)); System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType));
xmlSer.Serialize(xmlFs, sidecar); xmlSer.Serialize(xmlFs, sidecar);
xmlFs.Close(); xmlFs.Close();
alcohol.Close();
} }
Statistics.AddMedia(dskType, true); Statistics.AddMedia(dskType, true);

View File

@@ -57,6 +57,7 @@ namespace DiscImageChef.Core.Devices.Dumping
bool compactDisc = true; bool compactDisc = true;
ushort currentProfile = 0x0001; ushort currentProfile = 0x0001;
bool isXbox = false; bool isXbox = false;
Alcohol120 alcohol = new Alcohol120(outputPrefix);
sidecar.OpticalDisc = new OpticalDiscType[1]; sidecar.OpticalDisc = new OpticalDiscType[1];
sidecar.OpticalDisc[0] = new OpticalDiscType(); sidecar.OpticalDisc[0] = new OpticalDiscType();
@@ -167,7 +168,7 @@ namespace DiscImageChef.Core.Devices.Dumping
if(compactDisc) if(compactDisc)
{ {
CompactDisc.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, separateSubchannel, ref resume, ref dumpLog); CompactDisc.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, separateSubchannel, ref resume, ref dumpLog, alcohol);
return; return;
} }
@@ -211,6 +212,7 @@ namespace DiscImageChef.Core.Devices.Dumping
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out duration); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out duration);
if(!sense) if(!sense)
{ {
alcohol.AddPFI(cmdBuf);
if(Decoders.DVD.PFI.Decode(cmdBuf).HasValue) if(Decoders.DVD.PFI.Decode(cmdBuf).HasValue)
{ {
tmpBuf = new byte[cmdBuf.Length - 4]; tmpBuf = new byte[cmdBuf.Length - 4];
@@ -325,6 +327,8 @@ namespace DiscImageChef.Core.Devices.Dumping
isXbox = true; isXbox = true;
} }
alcohol.AddDMI(cmdBuf);
if(cmdBuf.Length == 2052) if(cmdBuf.Length == 2052)
{ {
tmpBuf = new byte[cmdBuf.Length - 4]; tmpBuf = new byte[cmdBuf.Length - 4];
@@ -378,6 +382,7 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
tmpBuf = new byte[cmdBuf.Length - 4]; tmpBuf = new byte[cmdBuf.Length - 4];
Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
alcohol.AddBCA(tmpBuf);
sidecar.OpticalDisc[0].BCA = new DumpType sidecar.OpticalDisc[0].BCA = new DumpType
{ {
Image = outputPrefix + ".bca.bin", Image = outputPrefix + ".bca.bin",
@@ -590,6 +595,7 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
tmpBuf = new byte[cmdBuf.Length - 4]; tmpBuf = new byte[cmdBuf.Length - 4];
Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4); Array.Copy(cmdBuf, 4, tmpBuf, 0, cmdBuf.Length - 4);
alcohol.AddBCA(tmpBuf);
sidecar.OpticalDisc[0].BCA = new DumpType sidecar.OpticalDisc[0].BCA = new DumpType
{ {
Image = outputPrefix + ".bca.bin", Image = outputPrefix + ".bca.bin",
@@ -643,7 +649,7 @@ namespace DiscImageChef.Core.Devices.Dumping
return; return;
} }
SBC.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, true, ref resume, ref dumpLog); SBC.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, true, ref resume, ref dumpLog, alcohol);
} }
} }
} }

View File

@@ -51,9 +51,11 @@ using Extents;
namespace DiscImageChef.Core.Devices.Dumping namespace DiscImageChef.Core.Devices.Dumping
{ {
using TrackType = ImagePlugins.TrackType;
internal static class SBC internal static class SBC
{ {
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar, ref MediaType dskType, bool opticalDisc, ref Metadata.Resume resume, ref DumpLog dumpLog) internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar, ref MediaType dskType, bool opticalDisc, ref Metadata.Resume resume, ref DumpLog dumpLog, Alcohol120 alcohol = null)
{ {
MHDDLog mhddLog; MHDDLog mhddLog;
IBGLog ibgLog; IBGLog ibgLog;
@@ -342,6 +344,15 @@ namespace DiscImageChef.Core.Devices.Dumping
readBuffer = null; readBuffer = null;
if(alcohol != null && !dumpRaw)
{
alcohol.AddSessions(new [] { new Session() { StartTrack = 1, EndTrack = 1, SessionSequence = 1}});
alcohol.AddTrack(20, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1);
alcohol.SetExtension(outputExtension);
alcohol.SetTrackSizes(1, (int)blockSize, 0, 0, (long)blocks);
alcohol.SetTrackTypes(1, TrackType.Data, TrackSubchannelType.None);
}
DumpHardwareType currentTry = null; DumpHardwareType currentTry = null;
ExtentsULong extents = null; ExtentsULong extents = null;
ResumeSupport.Process(true, dev.IsRemovable, blocks, dev.Manufacturer, dev.Model, dev.Serial, dev.PlatformID, ref resume, ref currentTry, ref extents); ResumeSupport.Process(true, dev.IsRemovable, blocks, dev.Manufacturer, dev.Model, dev.Serial, dev.PlatformID, ref resume, ref currentTry, ref extents);
@@ -749,6 +760,9 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
} }
if(alcohol != null && !dumpRaw)
alcohol.SetMediaType(dskType);
if(opticalDisc) if(opticalDisc)
{ {
sidecar.OpticalDisc[0].Checksums = dataChk.End().ToArray(); sidecar.OpticalDisc[0].Checksums = dataChk.End().ToArray();
@@ -885,6 +899,8 @@ namespace DiscImageChef.Core.Devices.Dumping
System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType)); System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType));
xmlSer.Serialize(xmlFs, sidecar); xmlSer.Serialize(xmlFs, sidecar);
xmlFs.Close(); xmlFs.Close();
if(alcohol != null && !dumpRaw)
alcohol.Close();
} }
Statistics.AddMedia(dskType, true); Statistics.AddMedia(dskType, true);

View File

@@ -88,6 +88,7 @@
<Compile Include="Sidecar\AudioMedia.cs" /> <Compile Include="Sidecar\AudioMedia.cs" />
<Compile Include="Sidecar\BlockTape.cs" /> <Compile Include="Sidecar\BlockTape.cs" />
<Compile Include="Logging\DumpLog.cs" /> <Compile Include="Logging\DumpLog.cs" />
<Compile Include="Devices\Dumping\Alcohol120.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\DiscImageChef.Console\DiscImageChef.Console.csproj"> <ProjectReference Include="..\DiscImageChef.Console\DiscImageChef.Console.csproj">