2015-12-25 20:47:40 +00:00
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : GDI.cs
2016-07-28 18:13:49 +01:00
// Author(s) : Natalia Portillo <claunia@claunia.com>
2015-12-25 20:47:40 +00:00
//
2016-07-28 18:13:49 +01:00
// Component : Disc image plugins.
2015-12-25 20:47:40 +00:00
//
// --[ Description ] ----------------------------------------------------------
//
2016-07-28 18:13:49 +01:00
// Manages Dreamcast GDI disc images.
2015-12-25 20:47:40 +00:00
//
// --[ License ] --------------------------------------------------------------
//
2016-07-28 18:13:49 +01:00
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
2015-12-25 20:47:40 +00:00
// License, or (at your option) any later version.
//
2016-07-28 18:13:49 +01:00
// This library 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
// Lesser General Public License for more details.
2015-12-25 20:47:40 +00:00
//
2016-07-28 18:13:49 +01:00
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
2015-12-25 20:47:40 +00:00
//
// ----------------------------------------------------------------------------
2016-07-28 18:13:49 +01:00
// Copyright © 2011-2016 Natalia Portillo
2015-12-25 20:47:40 +00:00
// ****************************************************************************/
2016-07-28 18:13:49 +01:00
2015-12-25 20:47:40 +00:00
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
{
/// <summary>Track #</summary>
2016-07-28 22:25:26 +01:00
public uint sequence ;
2015-12-25 20:47:40 +00:00
/// <summary>Track file</summary>
public string trackfile ;
/// <summary>Track byte offset in file</summary>
public long offset ;
/// <summary>Track flags</summary>
public byte flags ;
/// <summary>Track starting sector</summary>
public ulong startSector ;
/// <summary>Bytes per sector</summary>
2016-07-28 22:25:26 +01:00
public ushort bps ;
2015-12-25 20:47:40 +00:00
/// <summary>Sectors in track</summary>
2016-07-28 22:25:26 +01:00
public ulong sectors ;
2015-12-25 20:47:40 +00:00
/// <summary>Track type</summary>
public TrackType tracktype ;
/// <summary>Track session</summary>
public bool highDensity ;
/// <summary>Pregap sectors not stored in track file</summary>
public ulong pregap ;
}
struct GDIDisc
{
/// <summary>Sessions</summary>
public List < Session > sessions ;
/// <summary>Tracks</summary>
public List < GDITrack > tracks ;
/// <summary>Disk type</summary>
2016-01-16 03:54:55 +00:00
public MediaType disktype ;
2015-12-25 20:47:40 +00:00
}
#endregion Internal structures
#region Internal variables
string imagePath ;
StreamReader gdiStream ;
FileStream imageStream ;
/// <summary>Dictionary, index is track #, value is track number, or 0 if a TOC</summary>
2016-07-28 22:25:26 +01:00
Dictionary < uint , ulong > offsetmap ;
2015-12-25 20:47:40 +00:00
GDIDisc discimage ;
List < Partition > partitions ;
ulong densitySeparationSectors ;
#endregion Internal variables
#region Parsing regexs
const string TrackRegEx = "\\s?(?<track>\\d+)\\s+(?<start>\\d+)\\s(?<flags>\\d)\\s(?<type>2352|2048)\\s(?<filename>.+)\\s(?<offset>\\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 < SectorTagType > ( ) ;
2016-01-16 03:54:55 +00:00
ImageInfo . readableMediaTags = new List < MediaTagType > ( ) ;
2015-12-25 20:47:40 +00:00
ImageInfo . imageHasPartitions = true ;
ImageInfo . imageHasSessions = true ;
ImageInfo . imageVersion = null ;
ImageInfo . imageApplicationVersion = null ;
ImageInfo . imageName = null ;
ImageInfo . imageCreator = null ;
2016-01-16 03:54:55 +00:00
ImageInfo . mediaManufacturer = null ;
ImageInfo . mediaModel = null ;
ImageInfo . mediaPartNumber = null ;
ImageInfo . mediaSequence = 0 ;
ImageInfo . lastMediaSequence = 0 ;
2015-12-25 20:47:40 +00:00
ImageInfo . driveManufacturer = null ;
ImageInfo . driveModel = null ;
ImageInfo . driveSerialNumber = null ;
2016-08-18 00:05:24 +01:00
ImageInfo . driveFirmwareRevision = null ;
2015-12-25 20:47:40 +00:00
}
// 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 ;
2016-04-19 02:11:47 +01:00
while ( gdiStream . Peek ( ) > = 0 )
2015-12-25 20:47:40 +00:00
{
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 ;
}
2016-04-19 02:11:47 +01:00
catch ( Exception ex )
2015-12-25 20:47:40 +00:00
{
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 )
{
2016-04-19 02:11:47 +01:00
if ( imagePath = = null )
2015-12-25 20:47:40 +00:00
return false ;
2016-04-19 02:11:47 +01:00
if ( imagePath = = "" )
2015-12-25 20:47:40 +00:00
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 < Session > ( ) ;
discimage . tracks = new List < GDITrack > ( ) ;
ulong currentStart = 0 ;
offsetmap = new Dictionary < uint , ulong > ( ) ;
GDITrack currentTrack ;
densitySeparationSectors = 0 ;
2016-04-19 02:11:47 +01:00
while ( gdiStream . Peek ( ) > = 0 )
2015-12-25 20:47:40 +00:00
{
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 )
2016-07-28 22:25:26 +01:00
throw new ImageNotSupportedException ( string . Format ( "Unknown line \"{0}\" at line {1}" , _line , line ) ) ;
2015-12-25 20:47:40 +00:00
tracksFound + + ;
2016-04-19 02:11:47 +01:00
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 ,
2015-12-25 20:47:40 +00:00
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 ) ;
2016-04-19 02:11:47 +01:00
currentTrack . trackfile = TrackMatch . Groups [ "filename" ] . Value . Replace ( "\\\"" , "\"" ) . Trim ( new [ ] { '"' } ) ;
2015-12-25 20:47:40 +00:00
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 ] ;
2016-04-19 02:11:47 +01:00
for ( int s = 0 ; s < _sessions . Length ; s + + )
2015-12-25 20:47:40 +00:00
{
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 ] ) ;
2016-01-16 03:54:55 +00:00
discimage . disktype = MediaType . GDROM ;
2015-12-25 20:47:40 +00:00
// 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 ) ;
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < discimage . sessions . Count ; i + + )
2015-12-25 20:47:40 +00:00
{
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 ) ;
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < discimage . tracks . Count ; i + + )
2015-12-25 20:47:40 +00:00
{
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 ) ;
2016-04-19 02:11:47 +01:00
if ( ( discimage . tracks [ i ] . flags & 0x80 ) = = 0x80 )
2015-12-25 20:47:40 +00:00
DicConsole . DebugWriteLine ( "GDI plugin" , "\t\tTrack is flagged as quadraphonic" ) ;
2016-04-19 02:11:47 +01:00
if ( ( discimage . tracks [ i ] . flags & 0x40 ) = = 0x40 )
2015-12-25 20:47:40 +00:00
DicConsole . DebugWriteLine ( "GDI plugin" , "\t\tTrack is data" ) ;
2016-04-19 02:11:47 +01:00
if ( ( discimage . tracks [ i ] . flags & 0x20 ) = = 0x20 )
2015-12-25 20:47:40 +00:00
DicConsole . DebugWriteLine ( "GDI plugin" , "\t\tTrack allows digital copy" ) ;
2016-04-19 02:11:47 +01:00
if ( ( discimage . tracks [ i ] . flags & 0x10 ) = = 0x10 )
2015-12-25 20:47:40 +00:00
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 < Partition > ( ) ;
ulong byte_offset = 0 ;
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < discimage . tracks . Count ; i + + )
2015-12-25 20:47:40 +00:00
{
2016-04-19 02:11:47 +01:00
if ( discimage . tracks [ i ] . sequence = = 1 & & i ! = 0 )
2015-12-25 20:47:40 +00:00
throw new ImageNotSupportedException ( "Unordered tracks" ) ;
Partition partition = new Partition ( ) ;
// Index 01
2016-07-28 22:25:26 +01:00
partition . PartitionDescription = string . Format ( "Track {0}." , discimage . tracks [ i ] . sequence ) ;
2015-12-25 20:47:40 +00:00
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 ) ;
}
2016-04-19 02:11:47 +01:00
foreach ( GDITrack track in discimage . tracks )
2015-12-25 20:47:40 +00:00
ImageInfo . imageSize + = track . bps * track . sectors ;
2016-04-19 02:11:47 +01:00
foreach ( GDITrack track in discimage . tracks )
2015-12-25 20:47:40 +00:00
ImageInfo . sectors + = track . sectors ;
ImageInfo . sectors + = densitySeparationSectors ;
ImageInfo . sectorSize = 2352 ; // All others
2016-04-19 02:11:47 +01:00
foreach ( GDITrack track in discimage . tracks )
2015-12-25 20:47:40 +00:00
{
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 ;
2016-01-16 03:54:55 +00:00
ImageInfo . mediaType = discimage . disktype ;
2015-12-25 20:47:40 +00:00
ImageInfo . readableSectorTags . Add ( SectorTagType . CDTrackFlags ) ;
ImageInfo . xmlMediaType = XmlMediaType . OpticalDisc ;
return true ;
}
2016-04-19 02:11:47 +01:00
catch ( Exception ex )
2015-12-25 20:47:40 +00:00
{
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 ;
}
2016-07-28 22:25:26 +01:00
public override ulong GetImageSize ( )
2015-12-25 20:47:40 +00:00
{
return ImageInfo . imageSize ;
}
2016-07-28 22:25:26 +01:00
public override ulong GetSectors ( )
2015-12-25 20:47:40 +00:00
{
return ImageInfo . sectors ;
}
2016-07-28 22:25:26 +01:00
public override uint GetSectorSize ( )
2015-12-25 20:47:40 +00:00
{
return ImageInfo . sectorSize ;
}
2016-01-16 03:54:55 +00:00
public override byte [ ] ReadDiskTag ( MediaTagType tag )
2015-12-25 20:47:40 +00:00
{
throw new FeatureSupportedButNotImplementedImageException ( "Feature not supported by image format" ) ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSector ( ulong sectorAddress )
2015-12-25 20:47:40 +00:00
{
return ReadSectors ( sectorAddress , 1 ) ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectorTag ( ulong sectorAddress , SectorTagType tag )
2015-12-25 20:47:40 +00:00
{
return ReadSectorsTag ( sectorAddress , 1 , tag ) ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSector ( ulong sectorAddress , uint track )
2015-12-25 20:47:40 +00:00
{
return ReadSectors ( sectorAddress , 1 , track ) ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectorTag ( ulong sectorAddress , uint track , SectorTagType tag )
2015-12-25 20:47:40 +00:00
{
return ReadSectorsTag ( sectorAddress , 1 , track , tag ) ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectors ( ulong sectorAddress , uint length )
2015-12-25 20:47:40 +00:00
{
2016-04-19 02:11:47 +01:00
foreach ( KeyValuePair < uint , ulong > kvp in offsetmap )
2015-12-25 20:47:40 +00:00
{
2016-04-19 02:11:47 +01:00
if ( sectorAddress > = kvp . Value )
2015-12-25 20:47:40 +00:00
{
2016-04-19 02:11:47 +01:00
foreach ( GDITrack gdi_track in discimage . tracks )
2015-12-25 20:47:40 +00:00
{
2016-04-19 02:11:47 +01:00
if ( gdi_track . sequence = = kvp . Key )
2015-12-25 20:47:40 +00:00
{
2016-04-19 02:11:47 +01:00
if ( ( sectorAddress - kvp . Value ) < gdi_track . sectors )
2015-12-25 20:47:40 +00:00
return ReadSectors ( ( sectorAddress - kvp . Value ) , length , kvp . Key ) ;
}
}
}
}
ulong transitionStart ;
offsetmap . TryGetValue ( 0 , out transitionStart ) ;
2016-04-19 02:11:47 +01:00
if ( sectorAddress > = transitionStart & & sectorAddress < ( densitySeparationSectors + transitionStart ) )
2015-12-25 20:47:40 +00:00
return ReadSectors ( ( sectorAddress - transitionStart ) , length , 0 ) ;
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( sectorAddress ) , "Sector address not found" ) ;
2015-12-25 20:47:40 +00:00
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectorsTag ( ulong sectorAddress , uint length , SectorTagType tag )
2015-12-25 20:47:40 +00:00
{
2016-04-19 02:11:47 +01:00
foreach ( KeyValuePair < uint , ulong > kvp in offsetmap )
2015-12-25 20:47:40 +00:00
{
2016-04-19 02:11:47 +01:00
if ( sectorAddress > = kvp . Value )
2015-12-25 20:47:40 +00:00
{
2016-04-19 02:11:47 +01:00
foreach ( GDITrack gdi_track in discimage . tracks )
2015-12-25 20:47:40 +00:00
{
2016-04-19 02:11:47 +01:00
if ( gdi_track . sequence = = kvp . Key )
2015-12-25 20:47:40 +00:00
{
2016-04-19 02:11:47 +01:00
if ( ( sectorAddress - kvp . Value ) < gdi_track . sectors )
2015-12-25 20:47:40 +00:00
return ReadSectorsTag ( ( sectorAddress - kvp . Value ) , length , kvp . Key , tag ) ;
}
}
}
}
ulong transitionStart ;
offsetmap . TryGetValue ( 0 , out transitionStart ) ;
2016-04-19 02:11:47 +01:00
if ( sectorAddress > = transitionStart & & sectorAddress < ( densitySeparationSectors + transitionStart ) )
2015-12-25 20:47:40 +00:00
return ReadSectorsTag ( ( sectorAddress - transitionStart ) , length , 0 , tag ) ;
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( sectorAddress ) , "Sector address not found" ) ;
2015-12-25 20:47:40 +00:00
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectors ( ulong sectorAddress , uint length , uint track )
2015-12-25 20:47:40 +00:00
{
2016-04-19 02:11:47 +01:00
if ( track = = 0 )
2015-12-25 20:47:40 +00:00
{
if ( ( sectorAddress + length ) > densitySeparationSectors )
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( length ) , "Requested more sectors than present in track, won't cross tracks" ) ;
2015-12-25 20:47:40 +00:00
return new byte [ length * 2352 ] ;
}
GDITrack _track = new GDITrack ( ) ;
_track . sequence = 0 ;
2016-04-19 02:11:47 +01:00
foreach ( GDITrack gdi_track in discimage . tracks )
2015-12-25 20:47:40 +00:00
{
2016-04-19 02:11:47 +01:00
if ( gdi_track . sequence = = track )
2015-12-25 20:47:40 +00:00
{
_track = gdi_track ;
break ;
}
}
2016-04-19 02:11:47 +01:00
if ( _track . sequence = = 0 )
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( track ) , "Track does not exist in disc image" ) ;
2015-12-25 20:47:40 +00:00
2016-04-19 02:11:47 +01:00
if ( ( sectorAddress + length ) > _track . sectors )
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( length ) , "Requested more sectors than present in track, won't cross tracks" ) ;
2015-12-25 20:47:40 +00:00
uint sector_offset ;
uint sector_size ;
uint sector_skip ;
2016-04-19 02:11:47 +01:00
switch ( _track . tracktype )
2015-12-25 20:47:40 +00:00
{
case TrackType . Audio :
{
sector_offset = 0 ;
sector_size = 2352 ;
sector_skip = 0 ;
break ;
}
case TrackType . CDMode1 :
{
2016-04-19 02:11:47 +01:00
if ( _track . bps = = 2352 )
2015-12-25 20:47:40 +00:00
{
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 ;
2016-04-19 02:11:47 +01:00
if ( _track . pregap > 0 & & sectorAddress < _track . pregap )
2015-12-25 20:47:40 +00:00
{
ulong remainingPregap = _track . pregap - sectorAddress ;
byte [ ] zero ;
2016-04-19 02:11:47 +01:00
if ( length > remainingPregap )
2015-12-25 20:47:40 +00:00
{
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 ) ;
2016-04-19 02:11:47 +01:00
using ( BinaryReader br = new BinaryReader ( imageStream ) )
2015-12-25 20:47:40 +00:00
{
br . BaseStream . Seek ( _track . offset + ( long ) ( sectorAddress * ( sector_offset + sector_size + sector_skip ) + _track . pregap * _track . bps ) , SeekOrigin . Begin ) ;
2016-04-19 02:11:47 +01:00
if ( sector_offset = = 0 & & sector_skip = = 0 )
2015-12-25 20:47:40 +00:00
buffer = br . ReadBytes ( ( int ) ( sector_size * remainingSectors ) ) ;
else
{
2016-04-19 02:11:47 +01:00
for ( ulong i = 0 ; i < remainingSectors ; i + + )
2015-12-25 20:47:40 +00:00
{
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 ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectorsTag ( ulong sectorAddress , uint length , uint track , SectorTagType tag )
2015-12-25 20:47:40 +00:00
{
2016-04-19 02:11:47 +01:00
if ( track = = 0 )
2015-12-25 20:47:40 +00:00
{
if ( ( sectorAddress + length ) > densitySeparationSectors )
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( length ) , "Requested more sectors than present in track, won't cross tracks" ) ;
2015-12-25 20:47:40 +00:00
2016-04-19 02:11:47 +01:00
if ( tag = = SectorTagType . CDTrackFlags )
2015-12-25 20:47:40 +00:00
return new byte [ ] { 0x00 } ;
2016-07-28 22:25:26 +01:00
throw new ArgumentException ( "Unsupported tag requested for this track" , nameof ( tag ) ) ;
2015-12-25 20:47:40 +00:00
}
GDITrack _track = new GDITrack ( ) ;
_track . sequence = 0 ;
2016-04-19 02:11:47 +01:00
foreach ( GDITrack gdi_track in discimage . tracks )
2015-12-25 20:47:40 +00:00
{
2016-04-19 02:11:47 +01:00
if ( gdi_track . sequence = = track )
2015-12-25 20:47:40 +00:00
{
_track = gdi_track ;
break ;
}
}
2016-04-19 02:11:47 +01:00
if ( _track . sequence = = 0 )
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( track ) , "Track does not exist in disc image" ) ;
2015-12-25 20:47:40 +00:00
2016-04-19 02:11:47 +01:00
if ( length > _track . sectors )
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( length ) , "Requested more sectors than present in track, won't cross tracks" ) ;
2015-12-25 20:47:40 +00:00
uint sector_offset ;
uint sector_size ;
uint sector_skip ;
2016-04-19 02:11:47 +01:00
switch ( tag )
2015-12-25 20:47:40 +00:00
{
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 :
2016-07-28 22:25:26 +01:00
throw new ArgumentException ( "Unsupported tag requested" , nameof ( tag ) ) ;
2015-12-25 20:47:40 +00:00
}
2016-04-19 02:11:47 +01:00
switch ( _track . tracktype )
2015-12-25 20:47:40 +00:00
{
case TrackType . Audio :
2016-07-28 22:25:26 +01:00
throw new ArgumentException ( "There are no tags on audio tracks" , nameof ( tag ) ) ;
2015-12-25 20:47:40 +00:00
case TrackType . CDMode1 :
{
2016-04-19 02:11:47 +01:00
if ( _track . bps ! = 2352 )
2015-12-25 20:47:40 +00:00
throw new FeatureNotPresentImageException ( "Image does not include tags for mode 1 sectors" ) ;
2016-04-19 02:11:47 +01:00
switch ( tag )
2015-12-25 20:47:40 +00:00
{
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 :
2016-07-28 22:25:26 +01:00
throw new ArgumentException ( "Unsupported tag requested for this track" , nameof ( tag ) ) ;
2015-12-25 20:47:40 +00:00
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 :
2016-07-28 22:25:26 +01:00
throw new ArgumentException ( "Unsupported tag requested" , nameof ( tag ) ) ;
2015-12-25 20:47:40 +00:00
}
break ;
}
default :
throw new FeatureSupportedButNotImplementedImageException ( "Unsupported track type" ) ;
}
byte [ ] buffer = new byte [ sector_size * length ] ;
ulong remainingSectors = length ;
2016-04-19 02:11:47 +01:00
if ( _track . pregap > 0 & & sectorAddress < _track . pregap )
2015-12-25 20:47:40 +00:00
{
ulong remainingPregap = _track . pregap - sectorAddress ;
byte [ ] zero ;
2016-04-19 02:11:47 +01:00
if ( length > remainingPregap )
2015-12-25 20:47:40 +00:00
{
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 ) ;
2016-04-19 02:11:47 +01:00
using ( BinaryReader br = new BinaryReader ( imageStream ) )
2015-12-25 20:47:40 +00:00
{
br . BaseStream . Seek ( _track . offset + ( long ) ( sectorAddress * ( sector_offset + sector_size + sector_skip ) + _track . pregap * _track . bps ) , SeekOrigin . Begin ) ;
2016-04-19 02:11:47 +01:00
if ( sector_offset = = 0 & & sector_skip = = 0 )
2015-12-25 20:47:40 +00:00
buffer = br . ReadBytes ( ( int ) ( sector_size * remainingSectors ) ) ;
else
{
2016-04-19 02:11:47 +01:00
for ( ulong i = 0 ; i < remainingSectors ; i + + )
2015-12-25 20:47:40 +00:00
{
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 ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectorLong ( ulong sectorAddress )
2015-12-25 20:47:40 +00:00
{
return ReadSectorsLong ( sectorAddress , 1 ) ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectorLong ( ulong sectorAddress , uint track )
2015-12-25 20:47:40 +00:00
{
return ReadSectorsLong ( sectorAddress , 1 , track ) ;
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectorsLong ( ulong sectorAddress , uint length )
2015-12-25 20:47:40 +00:00
{
2016-04-19 02:11:47 +01:00
foreach ( KeyValuePair < uint , ulong > kvp in offsetmap )
2015-12-25 20:47:40 +00:00
{
2016-04-19 02:11:47 +01:00
if ( sectorAddress > = kvp . Value )
2015-12-25 20:47:40 +00:00
{
2016-04-19 02:11:47 +01:00
foreach ( GDITrack gdi_track in discimage . tracks )
2015-12-25 20:47:40 +00:00
{
2016-04-19 02:11:47 +01:00
if ( gdi_track . sequence = = kvp . Key )
2015-12-25 20:47:40 +00:00
{
2016-04-19 02:11:47 +01:00
if ( ( sectorAddress - kvp . Value ) < gdi_track . sectors )
2015-12-25 20:47:40 +00:00
return ReadSectorsLong ( ( sectorAddress - kvp . Value ) , length , kvp . Key ) ;
}
}
}
}
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( sectorAddress ) , "Sector address not found" ) ;
2015-12-25 20:47:40 +00:00
}
2016-07-28 22:25:26 +01:00
public override byte [ ] ReadSectorsLong ( ulong sectorAddress , uint length , uint track )
2015-12-25 20:47:40 +00:00
{
2016-04-19 02:11:47 +01:00
if ( track = = 0 )
2015-12-25 20:47:40 +00:00
{
if ( ( sectorAddress + length ) > densitySeparationSectors )
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( length ) , "Requested more sectors than present in track, won't cross tracks" ) ;
2015-12-25 20:47:40 +00:00
return new byte [ length * 2352 ] ;
}
GDITrack _track = new GDITrack ( ) ;
_track . sequence = 0 ;
2016-04-19 02:11:47 +01:00
foreach ( GDITrack gdi_track in discimage . tracks )
2015-12-25 20:47:40 +00:00
{
2016-04-19 02:11:47 +01:00
if ( gdi_track . sequence = = track )
2015-12-25 20:47:40 +00:00
{
_track = gdi_track ;
break ;
}
}
2016-04-19 02:11:47 +01:00
if ( _track . sequence = = 0 )
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( track ) , "Track does not exist in disc image" ) ;
2015-12-25 20:47:40 +00:00
2016-04-19 02:11:47 +01:00
if ( ( sectorAddress + length ) > _track . sectors )
2016-07-28 22:25:26 +01:00
throw new ArgumentOutOfRangeException ( nameof ( length ) , "Requested more sectors than present in track, won't cross tracks" ) ;
2015-12-25 20:47:40 +00:00
uint sector_offset ;
uint sector_size ;
uint sector_skip ;
2016-04-19 02:11:47 +01:00
switch ( _track . tracktype )
2015-12-25 20:47:40 +00:00
{
case TrackType . Audio :
{
sector_offset = 0 ;
sector_size = 2352 ;
sector_skip = 0 ;
break ;
}
case TrackType . CDMode1 :
{
2016-04-19 02:11:47 +01:00
if ( _track . bps = = 2352 )
2015-12-25 20:47:40 +00:00
{
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 ;
2016-04-19 02:11:47 +01:00
if ( _track . pregap > 0 & & sectorAddress < _track . pregap )
2015-12-25 20:47:40 +00:00
{
ulong remainingPregap = _track . pregap - sectorAddress ;
byte [ ] zero ;
2016-04-19 02:11:47 +01:00
if ( length > remainingPregap )
2015-12-25 20:47:40 +00:00
{
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 ) ;
2016-04-19 02:11:47 +01:00
using ( BinaryReader br = new BinaryReader ( imageStream ) )
2015-12-25 20:47:40 +00:00
{
br . BaseStream . Seek ( _track . offset + ( long ) ( sectorAddress * ( sector_offset + sector_size + sector_skip ) + _track . pregap * _track . bps ) , SeekOrigin . Begin ) ;
2016-04-19 02:11:47 +01:00
if ( sector_offset = = 0 & & sector_skip = = 0 )
2015-12-25 20:47:40 +00:00
buffer = br . ReadBytes ( ( int ) ( sector_size * remainingSectors ) ) ;
else
{
2016-04-19 02:11:47 +01:00
for ( ulong i = 0 ; i < remainingSectors ; i + + )
2015-12-25 20:47:40 +00:00
{
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 ;
}
2016-04-19 02:11:47 +01:00
public override string GetImageFormat ( )
2015-12-25 20:47:40 +00:00
{
return "Dreamcast GDI image" ;
}
2016-04-19 02:11:47 +01:00
public override string GetImageVersion ( )
2015-12-25 20:47:40 +00:00
{
return ImageInfo . imageVersion ;
}
2016-04-19 02:11:47 +01:00
public override string GetImageApplication ( )
2015-12-25 20:47:40 +00:00
{
return ImageInfo . imageApplication ;
}
2016-04-19 02:11:47 +01:00
public override string GetImageApplicationVersion ( )
2015-12-25 20:47:40 +00:00
{
return ImageInfo . imageApplicationVersion ;
}
public override DateTime GetImageCreationTime ( )
{
return ImageInfo . imageCreationTime ;
}
public override DateTime GetImageLastModificationTime ( )
{
return ImageInfo . imageLastModificationTime ;
}
2016-04-19 02:11:47 +01:00
public override string GetImageComments ( )
2015-12-25 20:47:40 +00:00
{
return ImageInfo . imageComments ;
}
2016-01-16 03:54:55 +00:00
public override string GetMediaSerialNumber ( )
2015-12-25 20:47:40 +00:00
{
2016-01-16 03:54:55 +00:00
return ImageInfo . mediaSerialNumber ;
2015-12-25 20:47:40 +00:00
}
2016-01-16 03:54:55 +00:00
public override string GetMediaBarcode ( )
2015-12-25 20:47:40 +00:00
{
2016-01-16 03:54:55 +00:00
return ImageInfo . mediaBarcode ;
2015-12-25 20:47:40 +00:00
}
2016-01-16 03:54:55 +00:00
public override MediaType GetMediaType ( )
2015-12-25 20:47:40 +00:00
{
2016-01-16 03:54:55 +00:00
return ImageInfo . mediaType ;
2015-12-25 20:47:40 +00:00
}
public override List < Partition > GetPartitions ( )
{
return partitions ;
}
public override List < Track > GetTracks ( )
{
List < Track > tracks = new List < Track > ( ) ;
2016-04-19 02:11:47 +01:00
foreach ( GDITrack gdi_track in discimage . tracks )
2015-12-25 20:47:40 +00:00
{
Track _track = new Track ( ) ;
_track . Indexes = new Dictionary < int , ulong > ( ) ;
_track . TrackDescription = null ;
_track . TrackStartSector = gdi_track . startSector ;
_track . TrackEndSector = _track . TrackStartSector + gdi_track . sectors - 1 ;
_track . TrackPregap = gdi_track . pregap ;
2016-04-19 02:11:47 +01:00
if ( gdi_track . highDensity )
2015-12-25 20:47:40 +00:00
_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 < Track > GetSessionTracks ( Session session )
{
2016-04-19 02:11:47 +01:00
if ( discimage . sessions . Contains ( session ) )
2015-12-25 20:47:40 +00:00
{
return GetSessionTracks ( session . SessionSequence ) ;
}
throw new ImageNotSupportedException ( "Session does not exist in disc image" ) ;
}
2016-07-28 22:25:26 +01:00
public override List < Track > GetSessionTracks ( ushort session )
2015-12-25 20:47:40 +00:00
{
List < Track > tracks = new List < Track > ( ) ;
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" ) ;
}
2016-04-19 02:11:47 +01:00
foreach ( GDITrack gdi_track in discimage . tracks )
2015-12-25 20:47:40 +00:00
{
2016-04-19 02:11:47 +01:00
if ( gdi_track . highDensity = = expectedDensity )
2015-12-25 20:47:40 +00:00
{
Track _track = new Track ( ) ;
_track . Indexes = new Dictionary < int , ulong > ( ) ;
_track . TrackDescription = null ;
_track . TrackStartSector = gdi_track . startSector ;
_track . TrackEndSector = _track . TrackStartSector + gdi_track . sectors - 1 ;
_track . TrackPregap = gdi_track . pregap ;
2016-04-19 02:11:47 +01:00
if ( gdi_track . highDensity )
2015-12-25 20:47:40 +00:00
_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 < Session > GetSessions ( )
{
return discimage . sessions ;
}
2016-07-28 22:25:26 +01:00
public override bool? VerifySector ( ulong sectorAddress )
2015-12-25 20:47:40 +00:00
{
byte [ ] buffer = ReadSectorLong ( sectorAddress ) ;
return Checksums . CDChecksums . CheckCDSector ( buffer ) ;
}
2016-07-28 22:25:26 +01:00
public override bool? VerifySector ( ulong sectorAddress , uint track )
2015-12-25 20:47:40 +00:00
{
byte [ ] buffer = ReadSectorLong ( sectorAddress , track ) ;
return Checksums . CDChecksums . CheckCDSector ( buffer ) ;
}
2016-07-28 22:25:26 +01:00
public override bool? VerifySectors ( ulong sectorAddress , uint length , out List < ulong > FailingLBAs , out List < ulong > UnknownLBAs )
2015-12-25 20:47:40 +00:00
{
byte [ ] buffer = ReadSectorsLong ( sectorAddress , length ) ;
int bps = ( int ) ( buffer . Length / length ) ;
byte [ ] sector = new byte [ bps ] ;
2016-07-28 22:25:26 +01:00
FailingLBAs = new List < ulong > ( ) ;
UnknownLBAs = new List < ulong > ( ) ;
2015-12-25 20:47:40 +00:00
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < length ; i + + )
2015-12-25 20:47:40 +00:00
{
Array . Copy ( buffer , i * bps , sector , 0 , bps ) ;
bool? sectorStatus = Checksums . CDChecksums . CheckCDSector ( sector ) ;
2016-04-19 02:11:47 +01:00
switch ( sectorStatus )
2015-12-25 20:47:40 +00:00
{
case null :
UnknownLBAs . Add ( ( ulong ) i + sectorAddress ) ;
break ;
case false :
FailingLBAs . Add ( ( ulong ) i + sectorAddress ) ;
break ;
}
}
2016-04-19 02:11:47 +01:00
if ( UnknownLBAs . Count > 0 )
2015-12-25 20:47:40 +00:00
return null ;
2016-04-19 02:11:47 +01:00
if ( FailingLBAs . Count > 0 )
2015-12-25 20:47:40 +00:00
return false ;
return true ;
}
2016-07-28 22:25:26 +01:00
public override bool? VerifySectors ( ulong sectorAddress , uint length , uint track , out List < ulong > FailingLBAs , out List < ulong > UnknownLBAs )
2015-12-25 20:47:40 +00:00
{
byte [ ] buffer = ReadSectorsLong ( sectorAddress , length , track ) ;
int bps = ( int ) ( buffer . Length / length ) ;
byte [ ] sector = new byte [ bps ] ;
2016-07-28 22:25:26 +01:00
FailingLBAs = new List < ulong > ( ) ;
UnknownLBAs = new List < ulong > ( ) ;
2015-12-25 20:47:40 +00:00
2016-04-19 02:11:47 +01:00
for ( int i = 0 ; i < length ; i + + )
2015-12-25 20:47:40 +00:00
{
Array . Copy ( buffer , i * bps , sector , 0 , bps ) ;
bool? sectorStatus = Checksums . CDChecksums . CheckCDSector ( sector ) ;
2016-04-19 02:11:47 +01:00
switch ( sectorStatus )
2015-12-25 20:47:40 +00:00
{
case null :
UnknownLBAs . Add ( ( ulong ) i + sectorAddress ) ;
break ;
case false :
FailingLBAs . Add ( ( ulong ) i + sectorAddress ) ;
break ;
}
}
2016-04-19 02:11:47 +01:00
if ( UnknownLBAs . Count > 0 )
2015-12-25 20:47:40 +00:00
return null ;
2016-04-19 02:11:47 +01:00
if ( FailingLBAs . Count > 0 )
2015-12-25 20:47:40 +00:00
return false ;
return true ;
}
2016-01-16 03:54:55 +00:00
public override bool? VerifyMediaImage ( )
2015-12-25 20:47:40 +00:00
{
return null ;
}
#endregion Public methods
#region Unsupported features
2016-04-19 02:11:47 +01:00
public override int GetMediaSequence ( )
2015-12-25 20:47:40 +00:00
{
2016-01-16 03:54:55 +00:00
return ImageInfo . mediaSequence ;
2015-12-25 20:47:40 +00:00
}
2016-04-19 02:11:47 +01:00
public override int GetLastDiskSequence ( )
2015-12-25 20:47:40 +00:00
{
2016-01-16 03:54:55 +00:00
return ImageInfo . lastMediaSequence ;
2015-12-25 20:47:40 +00:00
}
public override string GetDriveManufacturer ( )
{
return ImageInfo . driveManufacturer ;
}
public override string GetDriveModel ( )
{
return ImageInfo . driveModel ;
}
public override string GetDriveSerialNumber ( )
{
return ImageInfo . driveSerialNumber ;
}
2016-01-16 03:54:55 +00:00
public override string GetMediaPartNumber ( )
2015-12-25 20:47:40 +00:00
{
2016-01-16 03:54:55 +00:00
return ImageInfo . mediaPartNumber ;
2015-12-25 20:47:40 +00:00
}
2016-01-16 03:54:55 +00:00
public override string GetMediaManufacturer ( )
2015-12-25 20:47:40 +00:00
{
2016-01-16 03:54:55 +00:00
return ImageInfo . mediaManufacturer ;
2015-12-25 20:47:40 +00:00
}
2016-01-16 03:54:55 +00:00
public override string GetMediaModel ( )
2015-12-25 20:47:40 +00:00
{
2016-01-16 03:54:55 +00:00
return ImageInfo . mediaModel ;
2015-12-25 20:47:40 +00:00
}
2016-04-19 02:11:47 +01:00
public override string GetImageName ( )
2015-12-25 20:47:40 +00:00
{
return ImageInfo . imageName ;
}
2016-04-19 02:11:47 +01:00
public override string GetImageCreator ( )
2015-12-25 20:47:40 +00:00
{
return ImageInfo . imageCreator ;
}
#endregion Unsupported features
}
}