From 8ed384f47f659ba6c9c094bf1a747a0ca1974c89 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Fri, 25 Dec 2015 20:47:40 +0000 Subject: [PATCH] * README.md: * DiscImageChef.DiscImages/GDI.cs: * DiscImageChef.DiscImages/DiscImageChef.DiscImages.csproj: Added support for Dreamcast GDI images. * DiscImageChef.DiscImages/ImagePlugin.cs: Add XML documentation to exceptions. * DiscImageChef.Filesystems/ISO9660.cs: Corrected Dreamcast IP.BIN interpretation. * DiscImageChef/Commands/CreateSidecar.cs: Formatting. --- DiscImageChef.DiscImages/ChangeLog | 9 + .../DiscImageChef.DiscImages.csproj | 1 + DiscImageChef.DiscImages/GDI.cs | 1249 +++++++++++++++++ DiscImageChef.DiscImages/ImagePlugin.cs | 70 + DiscImageChef.Filesystems/ChangeLog | 5 + DiscImageChef.Filesystems/ISO9660.cs | 51 +- DiscImageChef/ChangeLog | 5 + DiscImageChef/Commands/CreateSidecar.cs | 44 +- README.md | 1 + 9 files changed, 1392 insertions(+), 43 deletions(-) create mode 100644 DiscImageChef.DiscImages/GDI.cs diff --git a/DiscImageChef.DiscImages/ChangeLog b/DiscImageChef.DiscImages/ChangeLog index 362bdbdff..60edbe009 100644 --- a/DiscImageChef.DiscImages/ChangeLog +++ b/DiscImageChef.DiscImages/ChangeLog @@ -1,3 +1,12 @@ +2015-12-25 Natalia Portillo + + * GDI.cs: + * DiscImageChef.DiscImages.csproj: + Added support for Dreamcast GDI images. + + * ImagePlugin.cs: + Add XML documentation to exceptions. + 2015-12-23 Natalia Portillo * CDRDAO.cs: diff --git a/DiscImageChef.DiscImages/DiscImageChef.DiscImages.csproj b/DiscImageChef.DiscImages/DiscImageChef.DiscImages.csproj index b25428ef9..34f6f11b1 100644 --- a/DiscImageChef.DiscImages/DiscImageChef.DiscImages.csproj +++ b/DiscImageChef.DiscImages/DiscImageChef.DiscImages.csproj @@ -44,6 +44,7 @@ + diff --git a/DiscImageChef.DiscImages/GDI.cs b/DiscImageChef.DiscImages/GDI.cs new file mode 100644 index 000000000..3cf7a3ae5 --- /dev/null +++ b/DiscImageChef.DiscImages/GDI.cs @@ -0,0 +1,1249 @@ +// /*************************************************************************** +// The Disc Image Chef +// ---------------------------------------------------------------------------- +// +// Filename : GDI.cs +// Version : 1.0 +// Author(s) : Natalia Portillo +// +// Component : Component +// +// Revision : $Revision$ +// Last change by : $Author$ +// Date : $Date$ +// +// --[ Description ] ---------------------------------------------------------- +// +// Description +// +// --[ 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 . +// +// ---------------------------------------------------------------------------- +// Copyright (C) 2011-2015 Claunia.com +// ****************************************************************************/ +// //$Id$ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; +using DiscImageChef.Console; +using DiscImageChef.CommonTypes; + +namespace DiscImageChef.ImagePlugins +{ + // TODO: There seems no be no clear definition on how to treat pregaps that are not included in the file, so this is just appending it to start of track + // TODO: This format doesn't support to specify pregaps that are included in the file (like Redump ones) + class GDI : ImagePlugin + { + #region Internal structures + + struct GDITrack + { + /// Track # + public UInt32 sequence; + /// Track file + public string trackfile; + /// Track byte offset in file + public long offset; + /// Track flags + public byte flags; + /// Track starting sector + public ulong startSector; + /// Bytes per sector + public UInt16 bps; + /// Sectors in track + public UInt64 sectors; + /// Track type + public TrackType tracktype; + /// Track session + public bool highDensity; + /// Pregap sectors not stored in track file + public ulong pregap; + } + + struct GDIDisc + { + /// Sessions + public List sessions; + /// Tracks + public List tracks; + /// Disk type + public DiskType disktype; + } + + #endregion Internal structures + + #region Internal variables + + string imagePath; + StreamReader gdiStream; + FileStream imageStream; + /// Dictionary, index is track #, value is track number, or 0 if a TOC + Dictionary offsetmap; + GDIDisc discimage; + List partitions; + ulong densitySeparationSectors; + + #endregion Internal variables + + #region Parsing regexs + + const string TrackRegEx = "\\s?(?\\d+)\\s+(?\\d+)\\s(?\\d)\\s(?2352|2048)\\s(?.+)\\s(?\\d+)$"; + + #endregion Parsing regexs + + #region Public methods + + public GDI() + { + Name = "Dreamcast GDI image"; + PluginUUID = new Guid("281ECBF2-D2A7-414C-8497-1A33F6DCB2DD"); + imagePath = ""; + ImageInfo = new ImageInfo(); + ImageInfo.readableSectorTags = new List(); + ImageInfo.readableDiskTags = new List(); + ImageInfo.imageHasPartitions = true; + ImageInfo.imageHasSessions = true; + ImageInfo.imageVersion = null; + ImageInfo.imageApplicationVersion = null; + ImageInfo.imageName = null; + ImageInfo.imageCreator = null; + ImageInfo.diskManufacturer = null; + ImageInfo.diskModel = null; + ImageInfo.diskPartNumber = null; + ImageInfo.diskSequence = 0; + ImageInfo.lastDiskSequence = 0; + ImageInfo.driveManufacturer = null; + ImageInfo.driveModel = null; + ImageInfo.driveSerialNumber = null; + } + + // Due to .gdi format, this method must parse whole file, ignoring errors (those will be thrown by OpenImage()). + public override bool IdentifyImage(string imagePath) + { + this.imagePath = imagePath; + + try + { + gdiStream = new StreamReader(this.imagePath); + int line = 0; + int tracksFound = 0; + int tracks = 0; + + while (gdiStream.Peek() >= 0) + { + line++; + string _line = gdiStream.ReadLine(); + + if(line == 1) + { + if(!int.TryParse(_line, out tracks)) + return false; + } + else + { + Regex RegexTrack = new Regex(TrackRegEx); + + Match TrackMatch = RegexTrack.Match(_line); + + if(!TrackMatch.Success) + return false; + + tracksFound++; + } + } + + if(tracks == 0) + return false; + + return tracks == tracksFound; + } + catch (Exception ex) + { + DicConsole.ErrorWriteLine("Exception trying to identify image file {0}", this.imagePath); + DicConsole.ErrorWriteLine("Exception: {0}", ex.Message); + DicConsole.ErrorWriteLine("Stack trace: {0}", ex.StackTrace); + return false; + } + } + + public override bool OpenImage(string imagePath) + { + if (imagePath == null) + return false; + if (imagePath == "") + return false; + + this.imagePath = imagePath; + + try + { + gdiStream = new StreamReader(imagePath); + int line = 0; + int tracksFound = 0; + int tracks = 0; + bool highDensity = false; + FileInfo trackFileInfo; + + // Initialize all RegExs + Regex RegexTrack = new Regex(TrackRegEx); + + // Initialize all RegEx matches + Match TrackMatch; + + // Initialize disc + discimage = new GDIDisc(); + discimage.sessions = new List(); + discimage.tracks = new List(); + + ulong currentStart = 0; + offsetmap = new Dictionary(); + GDITrack currentTrack; + densitySeparationSectors = 0; + + while (gdiStream.Peek() >= 0) + { + line++; + string _line = gdiStream.ReadLine(); + + if(line == 1) + { + if(!int.TryParse(_line, out tracks)) + throw new ImageNotSupportedException("Not a correct Dreamcast GDI image"); + } + else + { + TrackMatch = RegexTrack.Match(_line); + + if(!TrackMatch.Success) + throw new ImageNotSupportedException(String.Format("Unknown line \"{0}\" at line {1}", _line, line)); + + tracksFound++; + + DicConsole.DebugWriteLine("GDI plugin", "Found track {0} starts at {1} flags {2} type {3} file {4} offset {5} at line {6}", + TrackMatch.Groups["track"].Value, TrackMatch.Groups["start"].Value, TrackMatch.Groups["flags"].Value, + TrackMatch.Groups["type"].Value, TrackMatch.Groups["filename"].Value, TrackMatch.Groups["offset"].Value, line); + + currentTrack = new GDITrack(); + currentTrack.bps = ushort.Parse(TrackMatch.Groups["type"].Value); + currentTrack.flags = (byte)(byte.Parse(TrackMatch.Groups["flags"].Value) * 0x10); + currentTrack.offset = long.Parse(TrackMatch.Groups["offset"].Value); + currentTrack.sequence = uint.Parse(TrackMatch.Groups["track"].Value); + currentTrack.startSector = ulong.Parse(TrackMatch.Groups["start"].Value); + currentTrack.trackfile = TrackMatch.Groups["filename"].Value.Replace("\\\"", "\"").Trim(new []{'"'}); + + if((currentTrack.startSector - currentStart) > 0) + { + if(currentTrack.startSector == 45000) + { + highDensity = true; + offsetmap.Add(0, currentStart); + densitySeparationSectors = (currentTrack.startSector - currentStart); + currentStart = currentTrack.startSector; + } + else + { + currentTrack.pregap = (currentTrack.startSector - currentStart); + currentTrack.startSector -= (currentTrack.startSector - currentStart); + } + } + + trackFileInfo = new FileInfo(currentTrack.trackfile); + if(((trackFileInfo.Length - currentTrack.offset) % currentTrack.bps) != 0) + throw new ImageNotSupportedException("Track size not a multiple of sector size"); + + currentTrack.sectors = (ulong)((trackFileInfo.Length - currentTrack.offset) / currentTrack.bps); + currentTrack.sectors += currentTrack.pregap; + currentStart += currentTrack.sectors; + currentTrack.highDensity = highDensity; + + if((currentTrack.flags & 0x40) == 0x40) + currentTrack.tracktype = TrackType.CDMode1; + else + currentTrack.tracktype = TrackType.Audio; + + discimage.tracks.Add(currentTrack); + } + } + + Session[] _sessions = new Session[2]; + for (int s = 0; s < _sessions.Length; s++) + { + if(s == 0) + { + _sessions[s].SessionSequence = 1; + + foreach(GDITrack trk in discimage.tracks) + { + if(!trk.highDensity) + { + if(_sessions[s].StartTrack == 0) + _sessions[s].StartTrack = trk.sequence; + else if(_sessions[s].StartTrack > trk.sequence) + _sessions[s].StartTrack = trk.sequence; + + if(_sessions[s].EndTrack < trk.sequence) + _sessions[s].EndTrack = trk.sequence; + + if(_sessions[s].StartSector > trk.startSector) + _sessions[s].StartSector = trk.startSector; + + if(_sessions[s].EndSector < (trk.sectors + trk.startSector - 1)) + _sessions[s].EndSector = trk.sectors + trk.startSector - 1; + } + } + } + else + { + _sessions[s].SessionSequence = 2; + + foreach(GDITrack trk in discimage.tracks) + { + if(trk.highDensity) + { + if(_sessions[s].StartTrack == 0) + _sessions[s].StartTrack = trk.sequence; + else if(_sessions[s].StartTrack > trk.sequence) + _sessions[s].StartTrack = trk.sequence; + + if(_sessions[s].EndTrack < trk.sequence) + _sessions[s].EndTrack = trk.sequence; + + if(_sessions[s].StartSector > trk.startSector) + _sessions[s].StartSector = trk.startSector; + + if(_sessions[s].EndSector < (trk.sectors + trk.startSector - 1)) + _sessions[s].EndSector = trk.sectors + trk.startSector - 1; + } + } + } + } + + discimage.sessions.Add(_sessions[0]); + discimage.sessions.Add(_sessions[1]); + + discimage.disktype = DiskType.GDROM; + + // DEBUG information + DicConsole.DebugWriteLine("GDI plugin", "Disc image parsing results"); + + DicConsole.DebugWriteLine("GDI plugin", "Session information:"); + DicConsole.DebugWriteLine("GDI plugin", "\tDisc contains {0} sessions", discimage.sessions.Count); + for (int i = 0; i < discimage.sessions.Count; i++) + { + DicConsole.DebugWriteLine("GDI plugin", "\tSession {0} information:", i + 1); + DicConsole.DebugWriteLine("GDI plugin", "\t\tStarting track: {0}", discimage.sessions[i].StartTrack); + DicConsole.DebugWriteLine("GDI plugin", "\t\tStarting sector: {0}", discimage.sessions[i].StartSector); + DicConsole.DebugWriteLine("GDI plugin", "\t\tEnding track: {0}", discimage.sessions[i].EndTrack); + DicConsole.DebugWriteLine("GDI plugin", "\t\tEnding sector: {0}", discimage.sessions[i].EndSector); + } + DicConsole.DebugWriteLine("GDI plugin", "Track information:"); + DicConsole.DebugWriteLine("GDI plugin", "\tDisc contains {0} tracks", discimage.tracks.Count); + for (int i = 0; i < discimage.tracks.Count; i++) + { + DicConsole.DebugWriteLine("GDI plugin", "\tTrack {0} information:", discimage.tracks[i].sequence); + DicConsole.DebugWriteLine("GDI plugin", "\t\t{0} bytes per sector", discimage.tracks[i].bps); + DicConsole.DebugWriteLine("GDI plugin", "\t\tPregap: {0} sectors", discimage.tracks[i].pregap); + + if ((discimage.tracks[i].flags & 0x80) == 0x80) + DicConsole.DebugWriteLine("GDI plugin", "\t\tTrack is flagged as quadraphonic"); + if ((discimage.tracks[i].flags & 0x40) == 0x40) + DicConsole.DebugWriteLine("GDI plugin", "\t\tTrack is data"); + if ((discimage.tracks[i].flags & 0x20) == 0x20) + DicConsole.DebugWriteLine("GDI plugin", "\t\tTrack allows digital copy"); + if ((discimage.tracks[i].flags & 0x10) == 0x10) + DicConsole.DebugWriteLine("GDI plugin", "\t\tTrack has pre-emphasis applied"); + + DicConsole.DebugWriteLine("GDI plugin", "\t\tTrack resides in file {0}, type defined as {1}, starting at byte {2}", + discimage.tracks[i].trackfile, discimage.tracks[i].tracktype, discimage.tracks[i].offset); + } + + DicConsole.DebugWriteLine("GDI plugin", "Building offset map"); + + partitions = new List(); + ulong byte_offset = 0; + + for (int i = 0; i < discimage.tracks.Count; i++) + { + if (discimage.tracks[i].sequence == 1 && i != 0) + throw new ImageNotSupportedException("Unordered tracks"); + + Partition partition = new Partition(); + + // Index 01 + partition.PartitionDescription = String.Format("Track {0}.", discimage.tracks[i].sequence); + partition.PartitionName = null; + partition.PartitionStartSector = discimage.tracks[i].startSector; + partition.PartitionLength = discimage.tracks[i].sectors * discimage.tracks[i].bps; + partition.PartitionSectors = discimage.tracks[i].sectors; + partition.PartitionSequence = discimage.tracks[i].sequence; + partition.PartitionStart = byte_offset; + partition.PartitionType = discimage.tracks[i].tracktype.ToString(); + + byte_offset += partition.PartitionLength; + offsetmap.Add(discimage.tracks[i].sequence, partition.PartitionStartSector); + partitions.Add(partition); + } + + foreach (GDITrack track in discimage.tracks) + ImageInfo.imageSize += track.bps * track.sectors; + foreach (GDITrack track in discimage.tracks) + ImageInfo.sectors += track.sectors; + + ImageInfo.sectors += densitySeparationSectors; + + ImageInfo.sectorSize = 2352; // All others + + foreach (GDITrack track in discimage.tracks) + { + if((track.flags & 0x40) == 0x40 && track.bps == 2352) + { + ImageInfo.readableSectorTags.Add(SectorTagType.CDSectorSync); + ImageInfo.readableSectorTags.Add(SectorTagType.CDSectorHeader); + ImageInfo.readableSectorTags.Add(SectorTagType.CDSectorSubHeader); + ImageInfo.readableSectorTags.Add(SectorTagType.CDSectorECC); + ImageInfo.readableSectorTags.Add(SectorTagType.CDSectorECC_P); + ImageInfo.readableSectorTags.Add(SectorTagType.CDSectorECC_Q); + ImageInfo.readableSectorTags.Add(SectorTagType.CDSectorEDC); + } + } + + FileInfo fi = new FileInfo(discimage.tracks[0].trackfile); + + ImageInfo.imageCreationTime = fi.CreationTimeUtc; + ImageInfo.imageLastModificationTime = fi.LastWriteTimeUtc; + + ImageInfo.diskType = discimage.disktype; + + ImageInfo.readableSectorTags.Add(SectorTagType.CDTrackFlags); + + ImageInfo.xmlMediaType = XmlMediaType.OpticalDisc; + + return true; + } + catch (Exception ex) + { + DicConsole.ErrorWriteLine("Exception trying to identify image file {0}", imagePath); + DicConsole.ErrorWriteLine("Exception: {0}", ex.Message); + DicConsole.ErrorWriteLine("Stack trace: {0}", ex.StackTrace); + return false; + } + } + + public override bool ImageHasPartitions() + { + return ImageInfo.imageHasPartitions; + } + + public override UInt64 GetImageSize() + { + return ImageInfo.imageSize; + } + + public override UInt64 GetSectors() + { + return ImageInfo.sectors; + } + + public override UInt32 GetSectorSize() + { + return ImageInfo.sectorSize; + } + + public override byte[] ReadDiskTag(DiskTagType tag) + { + throw new FeatureSupportedButNotImplementedImageException("Feature not supported by image format"); + } + + public override byte[] ReadSector(UInt64 sectorAddress) + { + return ReadSectors(sectorAddress, 1); + } + + public override byte[] ReadSectorTag(UInt64 sectorAddress, SectorTagType tag) + { + return ReadSectorsTag(sectorAddress, 1, tag); + } + + public override byte[] ReadSector(UInt64 sectorAddress, UInt32 track) + { + return ReadSectors(sectorAddress, 1, track); + } + + public override byte[] ReadSectorTag(UInt64 sectorAddress, UInt32 track, SectorTagType tag) + { + return ReadSectorsTag(sectorAddress, 1, track, tag); + } + + public override byte[] ReadSectors(UInt64 sectorAddress, UInt32 length) + { + foreach (KeyValuePair kvp in offsetmap) + { + if (sectorAddress >= kvp.Value) + { + foreach (GDITrack gdi_track in discimage.tracks) + { + if (gdi_track.sequence == kvp.Key) + { + if ((sectorAddress - kvp.Value) < gdi_track.sectors) + return ReadSectors((sectorAddress - kvp.Value), length, kvp.Key); + } + } + } + } + + ulong transitionStart; + offsetmap.TryGetValue(0, out transitionStart); + if (sectorAddress >= transitionStart && sectorAddress < (densitySeparationSectors + transitionStart)) + return ReadSectors((sectorAddress - transitionStart), length, 0); + + throw new ArgumentOutOfRangeException("sectorAddress", "Sector address not found"); + } + + public override byte[] ReadSectorsTag(UInt64 sectorAddress, UInt32 length, SectorTagType tag) + { + foreach (KeyValuePair kvp in offsetmap) + { + if (sectorAddress >= kvp.Value) + { + foreach (GDITrack gdi_track in discimage.tracks) + { + if (gdi_track.sequence == kvp.Key) + { + if ((sectorAddress - kvp.Value) < gdi_track.sectors) + return ReadSectorsTag((sectorAddress - kvp.Value), length, kvp.Key, tag); + } + } + } + } + + ulong transitionStart; + offsetmap.TryGetValue(0, out transitionStart); + if (sectorAddress >= transitionStart && sectorAddress < (densitySeparationSectors + transitionStart)) + return ReadSectorsTag((sectorAddress - transitionStart), length, 0, tag); + + throw new ArgumentOutOfRangeException("sectorAddress", "Sector address not found"); + } + + public override byte[] ReadSectors(UInt64 sectorAddress, UInt32 length, UInt32 track) + { + if (track == 0) + { + if((sectorAddress + length) > densitySeparationSectors) + throw new ArgumentOutOfRangeException("length", "Requested more sectors than present in track, won't cross tracks"); + + return new byte[length * 2352]; + } + + GDITrack _track = new GDITrack(); + + _track.sequence = 0; + + foreach (GDITrack gdi_track in discimage.tracks) + { + if (gdi_track.sequence == track) + { + _track = gdi_track; + break; + } + } + + if (_track.sequence == 0) + throw new ArgumentOutOfRangeException("track", "Track does not exist in disc image"); + + if ((sectorAddress + length) > _track.sectors) + throw new ArgumentOutOfRangeException("length", "Requested more sectors than present in track, won't cross tracks"); + + uint sector_offset; + uint sector_size; + uint sector_skip; + + switch (_track.tracktype) + { + case TrackType.Audio: + { + sector_offset = 0; + sector_size = 2352; + sector_skip = 0; + break; + } + case TrackType.CDMode1: + { + if (_track.bps == 2352) + { + sector_offset = 16; + sector_size = 2048; + sector_skip = 288; + } + else + { + sector_offset = 0; + sector_size = 2048; + sector_skip = 0; + } + break; + } + default: + throw new FeatureSupportedButNotImplementedImageException("Unsupported track type"); + } + + byte[] buffer = new byte[sector_size * length]; + + ulong remainingSectors = length; + + if (_track.pregap > 0 && sectorAddress < _track.pregap) + { + ulong remainingPregap = _track.pregap - sectorAddress; + byte[] zero; + if (length > remainingPregap) + { + zero = new byte[remainingPregap * sector_size]; + remainingSectors -= remainingPregap; + } + else + { + zero = new byte[length * sector_size]; + remainingSectors -= length; + } + + Array.Copy(zero, 0, buffer, 0, zero.Length); + } + + if(remainingSectors == 0) + return buffer; + + imageStream = new FileStream(_track.trackfile, FileMode.Open, FileAccess.Read); + using (BinaryReader br = new BinaryReader(imageStream)) + { + br.BaseStream.Seek(_track.offset + (long)(sectorAddress * (sector_offset + sector_size + sector_skip) + _track.pregap * _track.bps), SeekOrigin.Begin); + if (sector_offset == 0 && sector_skip == 0) + buffer = br.ReadBytes((int)(sector_size * remainingSectors)); + else + { + for (ulong i = 0; i < remainingSectors; i++) + { + byte[] sector; + br.BaseStream.Seek(sector_offset, SeekOrigin.Current); + sector = br.ReadBytes((int)sector_size); + br.BaseStream.Seek(sector_skip, SeekOrigin.Current); + Array.Copy(sector, 0, buffer, (int)(i * sector_size), sector_size); + } + } + } + + return buffer; + } + + public override byte[] ReadSectorsTag(UInt64 sectorAddress, UInt32 length, UInt32 track, SectorTagType tag) + { + if (track == 0) + { + if((sectorAddress + length) > densitySeparationSectors) + throw new ArgumentOutOfRangeException("length", "Requested more sectors than present in track, won't cross tracks"); + + if (tag == SectorTagType.CDTrackFlags) + return new byte[] { 0x00 }; + + throw new ArgumentException("Unsupported tag requested for this track", "tag"); + } + + GDITrack _track = new GDITrack(); + + _track.sequence = 0; + + foreach (GDITrack gdi_track in discimage.tracks) + { + if (gdi_track.sequence == track) + { + _track = gdi_track; + break; + } + } + + if (_track.sequence == 0) + throw new ArgumentOutOfRangeException("track", "Track does not exist in disc image"); + + if (length > _track.sectors) + throw new ArgumentOutOfRangeException("length", "Requested more sectors than present in track, won't cross tracks"); + + uint sector_offset; + uint sector_size; + uint sector_skip; + + switch (tag) + { + case SectorTagType.CDSectorECC: + case SectorTagType.CDSectorECC_P: + case SectorTagType.CDSectorECC_Q: + case SectorTagType.CDSectorEDC: + case SectorTagType.CDSectorHeader: + case SectorTagType.CDSectorSync: + break; + case SectorTagType.CDTrackFlags: + { + byte[] flags = new byte[1]; + + flags[0] += _track.flags; + + return flags; + } + default: + throw new ArgumentException("Unsupported tag requested", "tag"); + } + + switch (_track.tracktype) + { + case TrackType.Audio: + throw new ArgumentException("There are no tags on audio tracks", "tag"); + case TrackType.CDMode1: + { + if (_track.bps != 2352) + throw new FeatureNotPresentImageException("Image does not include tags for mode 1 sectors"); + + switch (tag) + { + case SectorTagType.CDSectorSync: + { + sector_offset = 0; + sector_size = 12; + sector_skip = 2340; + break; + } + case SectorTagType.CDSectorHeader: + { + sector_offset = 12; + sector_size = 4; + sector_skip = 2336; + break; + } + case SectorTagType.CDSectorSubchannel: + case SectorTagType.CDSectorSubHeader: + throw new ArgumentException("Unsupported tag requested for this track", "tag"); + case SectorTagType.CDSectorECC: + { + sector_offset = 2076; + sector_size = 276; + sector_skip = 0; + break; + } + case SectorTagType.CDSectorECC_P: + { + sector_offset = 2076; + sector_size = 172; + sector_skip = 104; + break; + } + case SectorTagType.CDSectorECC_Q: + { + sector_offset = 2248; + sector_size = 104; + sector_skip = 0; + break; + } + case SectorTagType.CDSectorEDC: + { + sector_offset = 2064; + sector_size = 4; + sector_skip = 284; + break; + } + default: + throw new ArgumentException("Unsupported tag requested", "tag"); + } + break; + } + default: + throw new FeatureSupportedButNotImplementedImageException("Unsupported track type"); + } + + byte[] buffer = new byte[sector_size * length]; + + ulong remainingSectors = length; + + if (_track.pregap > 0 && sectorAddress < _track.pregap) + { + ulong remainingPregap = _track.pregap - sectorAddress; + byte[] zero; + if (length > remainingPregap) + { + zero = new byte[remainingPregap * sector_size]; + remainingSectors -= remainingPregap; + } + else + { + zero = new byte[length * sector_size]; + remainingSectors -= length; + } + + Array.Copy(zero, 0, buffer, 0, zero.Length); + } + + if(remainingSectors == 0) + return buffer; + + imageStream = new FileStream(_track.trackfile, FileMode.Open, FileAccess.Read); + using (BinaryReader br = new BinaryReader(imageStream)) + { + br.BaseStream.Seek(_track.offset + (long)(sectorAddress * (sector_offset + sector_size + sector_skip) + _track.pregap * _track.bps), SeekOrigin.Begin); + if (sector_offset == 0 && sector_skip == 0) + buffer = br.ReadBytes((int)(sector_size * remainingSectors)); + else + { + for (ulong i = 0; i < remainingSectors; i++) + { + byte[] sector; + br.BaseStream.Seek(sector_offset, SeekOrigin.Current); + sector = br.ReadBytes((int)sector_size); + br.BaseStream.Seek(sector_skip, SeekOrigin.Current); + Array.Copy(sector, 0, buffer, (int)(i * sector_size), sector_size); + } + } + } + + return buffer; + } + + public override byte[] ReadSectorLong(UInt64 sectorAddress) + { + return ReadSectorsLong(sectorAddress, 1); + } + + public override byte[] ReadSectorLong(UInt64 sectorAddress, UInt32 track) + { + return ReadSectorsLong(sectorAddress, 1, track); + } + + public override byte[] ReadSectorsLong(UInt64 sectorAddress, UInt32 length) + { + foreach (KeyValuePair kvp in offsetmap) + { + if (sectorAddress >= kvp.Value) + { + foreach (GDITrack gdi_track in discimage.tracks) + { + if (gdi_track.sequence == kvp.Key) + { + if ((sectorAddress - kvp.Value) < gdi_track.sectors) + return ReadSectorsLong((sectorAddress - kvp.Value), length, kvp.Key); + } + } + } + } + + throw new ArgumentOutOfRangeException("sectorAddress", "Sector address not found"); + } + + public override byte[] ReadSectorsLong(UInt64 sectorAddress, UInt32 length, UInt32 track) + { + if (track == 0) + { + if((sectorAddress + length) > densitySeparationSectors) + throw new ArgumentOutOfRangeException("length", "Requested more sectors than present in track, won't cross tracks"); + + return new byte[length * 2352]; + } + + GDITrack _track = new GDITrack(); + + _track.sequence = 0; + + foreach (GDITrack gdi_track in discimage.tracks) + { + if (gdi_track.sequence == track) + { + _track = gdi_track; + break; + } + } + + if (_track.sequence == 0) + throw new ArgumentOutOfRangeException("track", "Track does not exist in disc image"); + + if ((sectorAddress + length) > _track.sectors) + throw new ArgumentOutOfRangeException("length", "Requested more sectors than present in track, won't cross tracks"); + + uint sector_offset; + uint sector_size; + uint sector_skip; + + switch (_track.tracktype) + { + case TrackType.Audio: + { + sector_offset = 0; + sector_size = 2352; + sector_skip = 0; + break; + } + case TrackType.CDMode1: + { + if (_track.bps == 2352) + { + sector_offset = 0; + sector_size = 2352; + sector_skip = 0; + } + else + { + sector_offset = 0; + sector_size = 2048; + sector_skip = 0; + } + break; + } + default: + throw new FeatureSupportedButNotImplementedImageException("Unsupported track type"); + } + + byte[] buffer = new byte[sector_size * length]; + + ulong remainingSectors = length; + + if (_track.pregap > 0 && sectorAddress < _track.pregap) + { + ulong remainingPregap = _track.pregap - sectorAddress; + byte[] zero; + if (length > remainingPregap) + { + zero = new byte[remainingPregap * sector_size]; + remainingSectors -= remainingPregap; + } + else + { + zero = new byte[length * sector_size]; + remainingSectors -= length; + } + + Array.Copy(zero, 0, buffer, 0, zero.Length); + } + + if(remainingSectors == 0) + return buffer; + + imageStream = new FileStream(_track.trackfile, FileMode.Open, FileAccess.Read); + using (BinaryReader br = new BinaryReader(imageStream)) + { + br.BaseStream.Seek(_track.offset + (long)(sectorAddress * (sector_offset + sector_size + sector_skip) + _track.pregap * _track.bps), SeekOrigin.Begin); + if (sector_offset == 0 && sector_skip == 0) + buffer = br.ReadBytes((int)(sector_size * remainingSectors)); + else + { + for (ulong i = 0; i < remainingSectors; i++) + { + byte[] sector; + br.BaseStream.Seek(sector_offset, SeekOrigin.Current); + sector = br.ReadBytes((int)sector_size); + br.BaseStream.Seek(sector_skip, SeekOrigin.Current); + Array.Copy(sector, 0, buffer, (int)(i * sector_size), sector_size); + } + } + } + + return buffer; + } + + public override string GetImageFormat() + { + return "Dreamcast GDI image"; + } + + public override string GetImageVersion() + { + return ImageInfo.imageVersion; + } + + public override string GetImageApplication() + { + return ImageInfo.imageApplication; + } + + public override string GetImageApplicationVersion() + { + return ImageInfo.imageApplicationVersion; + } + + public override DateTime GetImageCreationTime() + { + return ImageInfo.imageCreationTime; + } + + public override DateTime GetImageLastModificationTime() + { + return ImageInfo.imageLastModificationTime; + } + + public override string GetImageComments() + { + return ImageInfo.imageComments; + } + + public override string GetDiskSerialNumber() + { + return ImageInfo.diskSerialNumber; + } + + public override string GetDiskBarcode() + { + return ImageInfo.diskBarcode; + } + + public override DiskType GetDiskType() + { + return ImageInfo.diskType; + } + + public override List GetPartitions() + { + return partitions; + } + + public override List GetTracks() + { + List tracks = new List(); + + foreach (GDITrack gdi_track in discimage.tracks) + { + Track _track = new Track(); + + _track.Indexes = new Dictionary(); + _track.TrackDescription = null; + _track.TrackStartSector = gdi_track.startSector; + _track.TrackEndSector = _track.TrackStartSector + gdi_track.sectors - 1; + _track.TrackPregap = gdi_track.pregap; + if (gdi_track.highDensity) + _track.TrackSession = 2; + else + _track.TrackSession = 1; + _track.TrackSequence = gdi_track.sequence; + _track.TrackType = gdi_track.tracktype; + _track.TrackFile = gdi_track.trackfile; + _track.TrackFileOffset = (ulong)gdi_track.offset; + _track.TrackFileType = "BINARY"; + _track.TrackRawBytesPerSector = gdi_track.bps; + if(gdi_track.tracktype == TrackType.Data) + _track.TrackBytesPerSector = 2048; + else + _track.TrackBytesPerSector = 2352; + _track.TrackSubchannelType = TrackSubchannelType.None; + + tracks.Add(_track); + } + + return tracks; + } + + public override List GetSessionTracks(Session session) + { + if (discimage.sessions.Contains(session)) + { + return GetSessionTracks(session.SessionSequence); + } + throw new ImageNotSupportedException("Session does not exist in disc image"); + } + + public override List GetSessionTracks(UInt16 session) + { + List tracks = new List(); + bool expectedDensity; + + switch(session) + { + case 1: + expectedDensity = false; + break; + case 2: + expectedDensity = true; + break; + default: + throw new ImageNotSupportedException("Session does not exist in disc image"); + } + + foreach (GDITrack gdi_track in discimage.tracks) + { + if (gdi_track.highDensity == expectedDensity) + { + Track _track = new Track(); + + _track.Indexes = new Dictionary(); + _track.TrackDescription = null; + _track.TrackStartSector = gdi_track.startSector; + _track.TrackEndSector = _track.TrackStartSector + gdi_track.sectors - 1; + _track.TrackPregap = gdi_track.pregap; + if (gdi_track.highDensity) + _track.TrackSession = 2; + else + _track.TrackSession = 1; + _track.TrackSequence = gdi_track.sequence; + _track.TrackType = gdi_track.tracktype; + _track.TrackFile = gdi_track.trackfile; + _track.TrackFileOffset = (ulong)gdi_track.offset; + _track.TrackFileType = "BINARY"; + _track.TrackRawBytesPerSector = gdi_track.bps; + if(gdi_track.tracktype == TrackType.Data) + _track.TrackBytesPerSector = 2048; + else + _track.TrackBytesPerSector = 2352; + _track.TrackSubchannelType = TrackSubchannelType.None; + + tracks.Add(_track); + } + } + + return tracks; + } + + public override List GetSessions() + { + return discimage.sessions; + } + + public override bool? VerifySector(UInt64 sectorAddress) + { + byte[] buffer = ReadSectorLong(sectorAddress); + return Checksums.CDChecksums.CheckCDSector(buffer); + } + + public override bool? VerifySector(UInt64 sectorAddress, UInt32 track) + { + byte[] buffer = ReadSectorLong(sectorAddress, track); + return Checksums.CDChecksums.CheckCDSector(buffer); + } + + public override bool? VerifySectors(UInt64 sectorAddress, UInt32 length, out List FailingLBAs, out List UnknownLBAs) + { + byte[] buffer = ReadSectorsLong(sectorAddress, length); + int bps = (int)(buffer.Length / length); + byte[] sector = new byte[bps]; + FailingLBAs = new List(); + UnknownLBAs = new List(); + + for (int i = 0; i < length; i++) + { + Array.Copy(buffer, i * bps, sector, 0, bps); + bool? sectorStatus = Checksums.CDChecksums.CheckCDSector(sector); + + switch (sectorStatus) + { + case null: + UnknownLBAs.Add((ulong)i + sectorAddress); + break; + case false: + FailingLBAs.Add((ulong)i + sectorAddress); + break; + } + } + + if (UnknownLBAs.Count > 0) + return null; + if (FailingLBAs.Count > 0) + return false; + return true; + } + + public override bool? VerifySectors(UInt64 sectorAddress, UInt32 length, UInt32 track, out List FailingLBAs, out List UnknownLBAs) + { + byte[] buffer = ReadSectorsLong(sectorAddress, length, track); + int bps = (int)(buffer.Length / length); + byte[] sector = new byte[bps]; + FailingLBAs = new List(); + UnknownLBAs = new List(); + + for (int i = 0; i < length; i++) + { + Array.Copy(buffer, i * bps, sector, 0, bps); + bool? sectorStatus = Checksums.CDChecksums.CheckCDSector(sector); + + switch (sectorStatus) + { + case null: + UnknownLBAs.Add((ulong)i + sectorAddress); + break; + case false: + FailingLBAs.Add((ulong)i + sectorAddress); + break; + } + } + + if (UnknownLBAs.Count > 0) + return null; + if (FailingLBAs.Count > 0) + return false; + return true; + } + + public override bool? VerifyDiskImage() + { + return null; + } + + #endregion Public methods + + #region Unsupported features + + public override int GetDiskSequence() + { + return ImageInfo.diskSequence; + } + + public override int GetLastDiskSequence() + { + return ImageInfo.lastDiskSequence; + } + + public override string GetDriveManufacturer() + { + return ImageInfo.driveManufacturer; + } + + public override string GetDriveModel() + { + return ImageInfo.driveModel; + } + + public override string GetDriveSerialNumber() + { + return ImageInfo.driveSerialNumber; + } + + public override string GetDiskPartNumber() + { + return ImageInfo.diskPartNumber; + } + + public override string GetDiskManufacturer() + { + return ImageInfo.diskManufacturer; + } + + public override string GetDiskModel() + { + return ImageInfo.diskModel; + } + + public override string GetImageName() + { + return ImageInfo.imageName; + } + + public override string GetImageCreator() + { + return ImageInfo.imageCreator; + } + + #endregion Unsupported features + } +} + diff --git a/DiscImageChef.DiscImages/ImagePlugin.cs b/DiscImageChef.DiscImages/ImagePlugin.cs index 51bba52be..12bc092e1 100644 --- a/DiscImageChef.DiscImages/ImagePlugin.cs +++ b/DiscImageChef.DiscImages/ImagePlugin.cs @@ -694,14 +694,28 @@ namespace DiscImageChef.ImagePlugins [Serializable] public class FeatureSupportedButNotImplementedImageException : Exception { + /// + /// Feature is supported by image but not implemented yet. + /// + /// Message. + /// Inner. public FeatureSupportedButNotImplementedImageException(string message, Exception inner) : base(message, inner) { } + /// + /// Feature is supported by image but not implemented yet. + /// + /// Message. public FeatureSupportedButNotImplementedImageException(string message) : base(message) { } + /// + /// Feature is supported by image but not implemented yet. + /// + /// Info. + /// Context. protected FeatureSupportedButNotImplementedImageException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { @@ -716,14 +730,28 @@ namespace DiscImageChef.ImagePlugins [Serializable] public class FeatureUnsupportedImageException : Exception { + /// + /// Feature is not supported by image. + /// + /// Message. + /// Inner. public FeatureUnsupportedImageException(string message, Exception inner) : base(message, inner) { } + /// + /// Feature is not supported by image. + /// + /// Message. public FeatureUnsupportedImageException(string message) : base(message) { } + /// + /// Feature is not supported by image. + /// + /// Info. + /// Context. protected FeatureUnsupportedImageException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { @@ -738,14 +766,28 @@ namespace DiscImageChef.ImagePlugins [Serializable] public class FeatureNotPresentImageException : Exception { + /// + /// Feature is supported by image but not present on it. + /// + /// Message. + /// Inner. public FeatureNotPresentImageException(string message, Exception inner) : base(message, inner) { } + /// + /// Feature is supported by image but not present on it. + /// + /// Message. public FeatureNotPresentImageException(string message) : base(message) { } + /// + /// Feature is supported by image but not present on it. + /// + /// Info. + /// Context. protected FeatureNotPresentImageException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { @@ -760,14 +802,28 @@ namespace DiscImageChef.ImagePlugins [Serializable] public class FeaturedNotSupportedByDiscImageException : Exception { + /// + /// Feature is supported by image but not by the disc it represents. + /// + /// Message. + /// Inner. public FeaturedNotSupportedByDiscImageException(string message, Exception inner) : base(message, inner) { } + /// + /// Feature is supported by image but not by the disc it represents. + /// + /// Message. public FeaturedNotSupportedByDiscImageException(string message) : base(message) { } + /// + /// Feature is supported by image but not by the disc it represents. + /// + /// Info. + /// Context. protected FeaturedNotSupportedByDiscImageException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { @@ -782,14 +838,28 @@ namespace DiscImageChef.ImagePlugins [Serializable] public class ImageNotSupportedException : Exception { + /// + /// Corrupt, incorrect or unhandled feature found on image + /// + /// Message. + /// Inner. public ImageNotSupportedException(string message, Exception inner) : base(message, inner) { } + /// + /// Corrupt, incorrect or unhandled feature found on image + /// + /// Message. public ImageNotSupportedException(string message) : base(message) { } + /// + /// Corrupt, incorrect or unhandled feature found on image + /// + /// Info. + /// Context. protected ImageNotSupportedException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { diff --git a/DiscImageChef.Filesystems/ChangeLog b/DiscImageChef.Filesystems/ChangeLog index 48a921a05..ec2de4d70 100644 --- a/DiscImageChef.Filesystems/ChangeLog +++ b/DiscImageChef.Filesystems/ChangeLog @@ -1,3 +1,8 @@ +2015-12-25 Natalia Portillo + + * ISO9660.cs: + Corrected Dreamcast IP.BIN interpretation. + 2015-12-23 Natalia Portillo * ISO9660.cs: diff --git a/DiscImageChef.Filesystems/ISO9660.cs b/DiscImageChef.Filesystems/ISO9660.cs index 21d7d855f..d960236ea 100644 --- a/DiscImageChef.Filesystems/ISO9660.cs +++ b/DiscImageChef.Filesystems/ISO9660.cs @@ -80,9 +80,9 @@ namespace DiscImageChef.Plugins public override bool Identify(ImagePlugins.ImagePlugin imagePlugin, ulong partitionStart, ulong partitionEnd) { - if (alreadyLaunched) +/* if (alreadyLaunched) return false; - alreadyLaunched = true; + alreadyLaunched = true;*/ byte VDType; @@ -776,54 +776,57 @@ namespace DiscImageChef.Plugins int iPeripherals = int.Parse(Encoding.ASCII.GetString(peripherals), NumberStyles.HexNumber); - if((iPeripherals & 0x00000010) == 0x00000010) + if((iPeripherals & 0x00000001) == 0x00000001) IPBinInformation.AppendLine("Game uses Windows CE."); IPBinInformation.AppendFormat("Peripherals:").AppendLine(); - if ((iPeripherals & 0x00000100) == 0x00000100) + if ((iPeripherals & 0x00000010) == 0x00000010) IPBinInformation.AppendLine("Game supports the VGA Box."); - if ((iPeripherals & 0x00001000) == 0x00001000) + if ((iPeripherals & 0x00000100) == 0x00000100) IPBinInformation.AppendLine("Game supports other expansion."); - if ((iPeripherals & 0x00002000) == 0x00002000) + if ((iPeripherals & 0x00000200) == 0x00000200) IPBinInformation.AppendLine("Game supports Puru Puru pack."); - if ((iPeripherals & 0x00004000) == 0x00004000) + if ((iPeripherals & 0x00000400) == 0x00000400) IPBinInformation.AppendLine("Game supports Mike Device."); - if ((iPeripherals & 0x00008000) == 0x00008000) + if ((iPeripherals & 0x00000800) == 0x00000800) IPBinInformation.AppendLine("Game supports Memory Card."); - if ((iPeripherals & 0x00010000) == 0x00010000) + if ((iPeripherals & 0x00001000) == 0x00001000) IPBinInformation.AppendLine("Game requires A + B + Start buttons and D-Pad."); - if ((iPeripherals & 0x00020000) == 0x00020000) + if ((iPeripherals & 0x00002000) == 0x00002000) IPBinInformation.AppendLine("Game requires C button."); - if ((iPeripherals & 0x00040000) == 0x00040000) + if ((iPeripherals & 0x00004000) == 0x00004000) IPBinInformation.AppendLine("Game requires D button."); - if ((iPeripherals & 0x00080000) == 0x00080000) + if ((iPeripherals & 0x00008000) == 0x00008000) IPBinInformation.AppendLine("Game requires X button."); - if ((iPeripherals & 0x00100000) == 0x00100000) + if ((iPeripherals & 0x00010000) == 0x00010000) IPBinInformation.AppendLine("Game requires Y button."); - if ((iPeripherals & 0x00200000) == 0x00200000) + if ((iPeripherals & 0x00020000) == 0x00020000) IPBinInformation.AppendLine("Game requires Z button."); - if ((iPeripherals & 0x00400000) == 0x00400000) + if ((iPeripherals & 0x00040000) == 0x00040000) IPBinInformation.AppendLine("Game requires expanded direction buttons."); - if ((iPeripherals & 0x00800000) == 0x00800000) + if ((iPeripherals & 0x00080000) == 0x00080000) IPBinInformation.AppendLine("Game requires analog R trigger."); - if ((iPeripherals & 0x01000000) == 0x01000000) + if ((iPeripherals & 0x00100000) == 0x00100000) IPBinInformation.AppendLine("Game requires analog L trigger."); - if ((iPeripherals & 0x02000000) == 0x02000000) + if ((iPeripherals & 0x00200000) == 0x00200000) IPBinInformation.AppendLine("Game requires analog horizontal controller."); - if ((iPeripherals & 0x04000000) == 0x04000000) + if ((iPeripherals & 0x00400000) == 0x00400000) IPBinInformation.AppendLine("Game requires analog vertical controller."); - if ((iPeripherals & 0x08000000) == 0x08000000) + if ((iPeripherals & 0x00800000) == 0x00800000) IPBinInformation.AppendLine("Game requires expanded analog horizontal controller."); - if ((iPeripherals & 0x10000000) == 0x10000000) + if ((iPeripherals & 0x01000000) == 0x01000000) IPBinInformation.AppendLine("Game requires expanded analog vertical controller."); - if ((iPeripherals & 0x20000000) == 0x20000000) + if ((iPeripherals & 0x02000000) == 0x02000000) IPBinInformation.AppendLine("Game supports Gun."); - if ((iPeripherals & 0x40000000) == 0x40000000) + if ((iPeripherals & 0x04000000) == 0x04000000) IPBinInformation.AppendLine("Game supports Keyboard."); - if ((iPeripherals & 0x80000000) == 0x80000000) + if ((iPeripherals & 0x08000000) == 0x08000000) IPBinInformation.AppendLine("Game supports Mouse."); + if((iPeripherals & 0xEE) != 0) + IPBinInformation.AppendFormat("Game supports unknown peripherals mask {0:X2}", (iPeripherals & 0xEE)); + break; } } diff --git a/DiscImageChef/ChangeLog b/DiscImageChef/ChangeLog index 0a9a5de68..8c6f55792 100644 --- a/DiscImageChef/ChangeLog +++ b/DiscImageChef/ChangeLog @@ -1,3 +1,8 @@ +2015-12-25 Natalia Portillo + + * Commands/CreateSidecar.cs: + Formatting. + 2015-12-23 Natalia Portillo * Commands/CreateSidecar.cs: diff --git a/DiscImageChef/Commands/CreateSidecar.cs b/DiscImageChef/Commands/CreateSidecar.cs index fc9fac1f0..7792c3655 100644 --- a/DiscImageChef/Commands/CreateSidecar.cs +++ b/DiscImageChef/Commands/CreateSidecar.cs @@ -409,8 +409,8 @@ namespace DiscImageChef.Commands if (pfi.HasValue) { if (dskType != DiskType.XGD && - dskType != DiskType.XGD2 && - dskType != DiskType.XGD3) + dskType != DiskType.XGD2 && + dskType != DiskType.XGD3) { switch (pfi.Value.DiskCategory) { @@ -555,7 +555,7 @@ namespace DiscImageChef.Commands xmlTrk.EndSector = (long)trk.TrackEndSector; if (sidecar.OpticalDisc[0].DiscType == "CD" || - sidecar.OpticalDisc[0].DiscType == "GD") + sidecar.OpticalDisc[0].DiscType == "GD") { xmlTrk.StartMSF = LbaToMsf(xmlTrk.StartSector); xmlTrk.EndMSF = LbaToMsf(xmlTrk.EndSector); @@ -578,6 +578,9 @@ namespace DiscImageChef.Commands xmlTrk.Size = (xmlTrk.EndSector - xmlTrk.StartSector + 1) * trk.TrackRawBytesPerSector; xmlTrk.BytesPerSector = trk.TrackBytesPerSector; + // For fast debugging, skip checksum + //goto skipChecksum; + uint sectorsToRead = 512; adler32ctx = new Adler32Context(); @@ -683,11 +686,11 @@ namespace DiscImageChef.Commands spamsumThread.Start(spamsumPkt); while (adlerThread.IsAlive || crc16Thread.IsAlive || - crc32Thread.IsAlive || crc64Thread.IsAlive || - md5Thread.IsAlive || ripemd160Thread.IsAlive || - sha1Thread.IsAlive || sha256Thread.IsAlive || - sha384Thread.IsAlive || sha512Thread.IsAlive || - spamsumThread.IsAlive) + crc32Thread.IsAlive || crc64Thread.IsAlive || + md5Thread.IsAlive || ripemd160Thread.IsAlive || + sha1Thread.IsAlive || sha256Thread.IsAlive || + sha384Thread.IsAlive || sha512Thread.IsAlive || + spamsumThread.IsAlive) { } @@ -894,11 +897,11 @@ namespace DiscImageChef.Commands spamsumThread.Start(spamsumPkt); while (adlerThread.IsAlive || crc16Thread.IsAlive || - crc32Thread.IsAlive || crc64Thread.IsAlive || - md5Thread.IsAlive || ripemd160Thread.IsAlive || - sha1Thread.IsAlive || sha256Thread.IsAlive || - sha384Thread.IsAlive || sha512Thread.IsAlive || - spamsumThread.IsAlive) + crc32Thread.IsAlive || crc64Thread.IsAlive || + md5Thread.IsAlive || ripemd160Thread.IsAlive || + sha1Thread.IsAlive || sha256Thread.IsAlive || + sha384Thread.IsAlive || sha512Thread.IsAlive || + spamsumThread.IsAlive) { } @@ -977,6 +980,9 @@ namespace DiscImageChef.Commands DicConsole.WriteLine(); } + // For fast debugging, skip checksum + //skipChecksum: + DicConsole.WriteLine("Checking filesystems on track {0} from sector {1} to {2}", xmlTrk.Sequence.TrackNumber, xmlTrk.StartSector, xmlTrk.EndSector); List partitions = new List(); @@ -993,10 +999,10 @@ namespace DiscImageChef.Commands } xmlTrk.FileSystemInformation = new PartitionType[1]; - if(partitions.Count > 0) + if (partitions.Count > 0) { xmlTrk.FileSystemInformation = new PartitionType[partitions.Count]; - for(int i = 0; i < partitions.Count; i++) + for (int i = 0; i < partitions.Count; i++) { xmlTrk.FileSystemInformation[i] = new PartitionType(); xmlTrk.FileSystemInformation[i].Description = partitions[i].PartitionDescription; @@ -1012,10 +1018,10 @@ namespace DiscImageChef.Commands { try { - if (_plugin.Identify(_imageFormat, partitions[i].PartitionStartSector, partitions[i].PartitionStartSector+partitions[i].PartitionSectors-1)) + if (_plugin.Identify(_imageFormat, partitions[i].PartitionStartSector, partitions[i].PartitionStartSector + partitions[i].PartitionSectors - 1)) { string foo; - _plugin.GetInformation(_imageFormat, partitions[i].PartitionStartSector, partitions[i].PartitionStartSector+partitions[i].PartitionSectors-1, out foo); + _plugin.GetInformation(_imageFormat, partitions[i].PartitionStartSector, partitions[i].PartitionStartSector + partitions[i].PartitionSectors - 1, out foo); lstFs.Add(_plugin.XmlFSType); } } @@ -1025,7 +1031,7 @@ namespace DiscImageChef.Commands } } - if(lstFs.Count > 0) + if (lstFs.Count > 0) xmlTrk.FileSystemInformation[i].FileSystems = lstFs.ToArray(); } } @@ -1054,7 +1060,7 @@ namespace DiscImageChef.Commands } } - if(lstFs.Count > 0) + if (lstFs.Count > 0) xmlTrk.FileSystemInformation[0].FileSystems = lstFs.ToArray(); } diff --git a/README.md b/README.md index 759de7385..be659fdc1 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ Supported disk image formats * Apple 2IMG (used with Apple // emulators) * Virtual PC fixed size, dynamic size and differencing (undo) disk images * CDRDAO TOC sheets +* Dreamcast GDI Supported partitioning schemes ==============================