2014-04-17 19:58:14 +00:00
|
|
|
/***************************************************************************
|
2014-06-15 23:39:34 +01:00
|
|
|
The Disc Image Chef
|
2014-04-17 19:58:14 +00:00
|
|
|
----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
Filename : CDRWin.cs
|
|
|
|
|
Version : 1.0
|
|
|
|
|
Author(s) : Natalia Portillo
|
|
|
|
|
|
|
|
|
|
Component : Disc image plugins
|
|
|
|
|
|
|
|
|
|
Revision : $Revision$
|
|
|
|
|
Last change by : $Author$
|
|
|
|
|
Date : $Date$
|
|
|
|
|
|
|
|
|
|
--[ Description ] ----------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
Manages CDRWin cuesheets (cue/bin).
|
|
|
|
|
|
|
|
|
|
--[ License ] --------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
2014-04-19 18:23:00 +01:00
|
|
|
it under the terms of the GNU General Public License as
|
2014-04-17 19:58:14 +00:00
|
|
|
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
|
2014-04-19 18:23:00 +01:00
|
|
|
GNU General Public License for more details.
|
2014-04-17 19:58:14 +00:00
|
|
|
|
2014-04-19 18:23:00 +01:00
|
|
|
You should have received a copy of the GNU General Public License
|
2014-04-17 19:58:14 +00:00
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
----------------------------------------------------------------------------
|
|
|
|
|
Copyright (C) 2011-2014 Claunia.com
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
//$Id$
|
|
|
|
|
|
|
|
|
|
// TODO: Implement track flags
|
2013-12-14 23:02:04 +00:00
|
|
|
using System;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Text;
|
2013-12-16 01:04:17 +00:00
|
|
|
using System.Text.RegularExpressions;
|
2013-12-14 23:02:04 +00:00
|
|
|
using System.Collections.Generic;
|
2014-06-15 23:39:34 +01:00
|
|
|
using DiscImageChef;
|
2015-10-18 22:04:03 +01:00
|
|
|
using DiscImageChef.Console;
|
2015-11-23 21:44:58 +00:00
|
|
|
using DiscImageChef.CommonTypes;
|
2013-12-14 23:02:04 +00:00
|
|
|
|
2014-06-15 23:39:34 +01:00
|
|
|
namespace DiscImageChef.ImagePlugins
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
|
|
|
|
class CDRWin : ImagePlugin
|
|
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
#region Internal structures
|
2013-12-16 01:04:17 +00:00
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
struct CDRWinTrackFile
|
|
|
|
|
{
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Track #</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public UInt32 sequence;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Path of file containing track</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public string datafile;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Offset of track start in file</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public UInt64 offset;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Type of file</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public string filetype;
|
|
|
|
|
}
|
2013-12-16 01:04:17 +00:00
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
struct CDRWinTrack
|
|
|
|
|
{
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Track #</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public UInt32 sequence;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Track title (from CD-Text)</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public string title;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Track genre (from CD-Text)</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public string genre;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Track arranger (from CD-Text)</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public string arranger;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Track composer (from CD-Text)</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public string composer;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Track performer (from CD-Text)</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public string performer;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Track song writer (from CD-Text)</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public string songwriter;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Track ISRC</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public string isrc;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>File struct for this track</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public CDRWinTrackFile trackfile;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Indexes on this track</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public Dictionary<int, UInt64> indexes;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Track pre-gap in sectors</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public UInt64 pregap;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Track post-gap in sectors</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public UInt64 postgap;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Digical Copy Permitted</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public bool flag_dcp;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Track is quadraphonic</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public bool flag_4ch;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Track has preemphasis</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public bool flag_pre;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Track has SCMS</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public bool flag_scms;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Bytes per sector</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public UInt16 bps;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Sectors in track</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public UInt64 sectors;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Track type</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public string tracktype;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Track session</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public UInt16 session;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
struct CDRWinDisc
|
|
|
|
|
{
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Disk title (from CD-Text)</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public string title;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Disk genre (from CD-Text)</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public string genre;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Disk arranger (from CD-Text)</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public string arranger;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Disk composer (from CD-Text)</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public string composer;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Disk performer (from CD-Text)</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public string performer;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Disk song writer (from CD-Text)</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public string songwriter;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Media catalog number</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public string mcn;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Disk type</summary>
|
2016-01-16 03:54:55 +00:00
|
|
|
public MediaType disktype;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Disk type string</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public string disktypestr;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Disk CDDB ID</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public string disk_id;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Disk UPC/EAN</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public string barcode;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Sessions</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public List<Session> sessions;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Tracks</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public List<CDRWinTrack> tracks;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Disk comment</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public string comment;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>File containing CD-Text</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
public string cdtextfile;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region Internal consts
|
|
|
|
|
|
|
|
|
|
// Type for FILE entity
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Data as-is in little-endian</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeLittleEndian = "BINARY";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Data as-is in big-endian</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeBigEndian = "MOTOROLA";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Audio in Apple AIF file</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeAIFF = "AIFF";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Audio in Microsoft WAV file</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeRIFF = "WAVE";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Audio in MP3 file</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeMP3 = "MP3";
|
2015-12-06 07:37:20 +00:00
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
// Type for TRACK entity
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Audio track, 2352 bytes/sector</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinTrackTypeAudio = "AUDIO";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>CD+G track, 2448 bytes/sector (audio+subchannel)</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinTrackTypeCDG = "CDG";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Mode 1 track, cooked, 2048 bytes/sector</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinTrackTypeMode1 = "MODE1/2048";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Mode 1 track, raw, 2352 bytes/sector</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinTrackTypeMode1Raw = "MODE1/2352";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Mode 2 form 1 track, cooked, 2048 bytes/sector</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinTrackTypeMode2Form1 = "MODE2/2048";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Mode 2 form 2 track, cooked, 2324 bytes/sector</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinTrackTypeMode2Form2 = "MODE2/2324";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Mode 2 formless track, cooked, 2336 bytes/sector</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinTrackTypeMode2Formless = "MODE2/2336";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Mode 2 track, raw, 2352 bytes/sector</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinTrackTypeMode2Raw = "MODE2/2352";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>CD-i track, cooked, 2336 bytes/sector</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinTrackTypeCDI = "CDI/2336";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>CD-i track, raw, 2352 bytes/sector</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinTrackTypeCDIRaw = "CDI/2352";
|
2015-12-06 07:37:20 +00:00
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
// Type for REM ORIGINAL MEDIA-TYPE entity
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.CD</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeCD = "CD";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.CDRW</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeCDRW = "CD-RW";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.CDMRW</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeCDMRW = "CD-MRW";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.CDMRW</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeCDMRW2 = "CD-(MRW)";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.DVDROM</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeDVD = "DVD";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.DVDPRW</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeDVDPMRW = "DVD+MRW";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.DVDPRW</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeDVDPMRW2 = "DVD+(MRW)";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.DVDPRWDL</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeDVDPMRWDL = "DVD+MRW DL";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.DVDPRWDL</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeDVDPMRWDL2 = "DVD+(MRW) DL";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.DVDPR</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeDVDPR = "DVD+R";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.DVDPRDL</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeDVDPRDL = "DVD+R DL";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.DVDPRW</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeDVDPRW = "DVD+RW";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.DVDPRWDL</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeDVDPRWDL = "DVD+RW DL";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.DVDPR</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeDVDPVR = "DVD+VR";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.DVDRAM</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeDVDRAM = "DVD-RAM";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.DVDR</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeDVDR = "DVD-R";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.DVDRDL</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeDVDRDL = "DVD-R DL";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.DVDRW</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeDVDRW = "DVD-RW";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.DVDRWDL</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeDVDRWDL = "DVD-RW DL";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.DVDR</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeDVDVR = "DVD-VR";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.DVDRW</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeDVDRW2 = "DVDRW";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.HDDVDROM</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeHDDVD = "HD DVD";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.HDDVDRAM</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeHDDVDRAM = "HD DVD-RAM";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.HDDVDR</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeHDDVDR = "HD DVD-R";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.HDDVDR</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeHDDVDRDL = "HD DVD-R DL";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.HDDVDRW</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeHDDVDRW = "HD DVD-RW";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.HDDVDRW</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeHDDVDRWDL = "HD DVD-RW DL";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.BDROM</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeBD = "BD";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.BDR</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeBDR = "BD-R";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.BDRE</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeBDRE = "BD-RE";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.BDR</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeBDRDL = "BD-R DL";
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>DiskType.BDRE</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
const string CDRWinDiskTypeBDREDL = "BD-RE DL";
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Internal variables
|
|
|
|
|
|
|
|
|
|
string imagePath;
|
|
|
|
|
StreamReader cueStream;
|
|
|
|
|
FileStream imageStream;
|
2015-12-06 07:37:20 +00:00
|
|
|
/// <summary>Dictionary, index is track #, value is TrackFile</summary>
|
2014-04-14 01:14:20 +00:00
|
|
|
Dictionary<UInt32, UInt64> offsetmap;
|
|
|
|
|
CDRWinDisc discimage;
|
2015-10-05 19:45:07 +01:00
|
|
|
List<CommonTypes.Partition> partitions;
|
2014-04-14 01:14:20 +00:00
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Parsing regexs
|
|
|
|
|
|
|
|
|
|
const string SessionRegEx = "REM\\s+SESSION\\s+(?<number>\\d+).*$";
|
|
|
|
|
const string DiskTypeRegEx = "REM\\s+ORIGINAL MEDIA-TYPE:\\s+(?<mediatype>.+)$";
|
|
|
|
|
const string LeadOutRegEx = "REM\\s+LEAD-OUT\\s+(?<msf>[\\d]+:[\\d]+:[\\d]+)$";
|
|
|
|
|
// Not checked
|
2015-12-06 07:37:20 +00:00
|
|
|
const string LBARegEx = "REM MSF:\\s+(?<msf>[\\d]+:[\\d]+:[\\d]+)\\s+=\\s+LBA:\\s+(?<lba>[\\d]+)$";
|
2014-04-14 01:14:20 +00:00
|
|
|
const string DiskIDRegEx = "DISC_ID\\s+(?<diskid>[\\da-f]{8})$";
|
|
|
|
|
const string BarCodeRegEx = "UPC_EAN\\s+(?<barcode>[\\d]{12,13})$";
|
|
|
|
|
const string CommentRegEx = "REM\\s+(?<comment>.+)$";
|
|
|
|
|
const string CDTextRegEx = "CDTEXTFILE\\s+(?<filename>.+)$";
|
|
|
|
|
const string MCNRegEx = "CATALOG\\s+(?<catalog>\\d{13})$";
|
|
|
|
|
const string TitleRegEx = "TITLE\\s+(?<title>.+)$";
|
|
|
|
|
const string GenreRegEx = "GENRE\\s+(?<genre>.+)$";
|
|
|
|
|
const string ArrangerRegEx = "ARRANGER\\s+(?<arranger>.+)$";
|
|
|
|
|
const string ComposerRegEx = "COMPOSER\\s+(?<composer>.+)$";
|
|
|
|
|
const string PerformerRegEx = "PERFORMER\\s+(?<performer>.+)$";
|
|
|
|
|
const string SongWriterRegEx = "SONGWRITER\\s+(?<songwriter>.+)$";
|
|
|
|
|
const string FileRegEx = "FILE\\s+(?<filename>.+)\\s+(?<type>\\S+)$";
|
|
|
|
|
const string TrackRegEx = "TRACK\\s+(?<number>\\d+)\\s+(?<type>\\S+)$";
|
|
|
|
|
const string ISRCRegEx = "ISRC\\s+(?<isrc>\\w{12})$";
|
|
|
|
|
const string IndexRegEx = "INDEX\\s+(?<index>\\d+)\\s+(?<msf>[\\d]+:[\\d]+:[\\d]+)$";
|
|
|
|
|
const string PregapRegEx = "PREGAP\\s+(?<msf>[\\d]+:[\\d]+:[\\d]+)$";
|
|
|
|
|
const string PostgapRegex = "POSTGAP\\s+(?<msf>[\\d]+:[\\d]+:[\\d]+)$";
|
|
|
|
|
const string FlagsRegEx = "FLAGS\\s+(((?<dcp>DCP)|(?<quad>4CH)|(?<pre>PRE)|(?<scms>SCMS))\\s*)+$";
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Methods
|
|
|
|
|
|
2015-10-05 19:45:07 +01:00
|
|
|
public CDRWin()
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
2014-06-07 17:32:14 +01:00
|
|
|
Name = "CDRWin cuesheet";
|
2014-04-14 01:14:20 +00:00
|
|
|
PluginUUID = new Guid("664568B2-15D4-4E64-8A7A-20BDA8B8386F");
|
|
|
|
|
imagePath = "";
|
2014-08-28 19:29:18 +01:00
|
|
|
ImageInfo = new ImageInfo();
|
|
|
|
|
ImageInfo.readableSectorTags = new List<SectorTagType>();
|
2016-01-16 03:54:55 +00:00
|
|
|
ImageInfo.readableMediaTags = new List<MediaTagType>();
|
2014-08-28 19:29:18 +01: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;
|
2014-08-28 19:29:18 +01:00
|
|
|
ImageInfo.driveManufacturer = null;
|
|
|
|
|
ImageInfo.driveModel = null;
|
|
|
|
|
ImageInfo.driveSerialNumber = null;
|
2014-04-14 01:14:20 +00:00
|
|
|
}
|
2014-08-24 17:46:29 +01:00
|
|
|
|
2013-12-16 01:04:17 +00:00
|
|
|
// Due to .cue format, this method must parse whole file, ignoring errors (those will be thrown by OpenImage()).
|
|
|
|
|
public override bool IdentifyImage(string imagePath)
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
|
|
|
|
this.imagePath = imagePath;
|
|
|
|
|
|
2013-12-16 01:04:17 +00:00
|
|
|
try
|
|
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
cueStream = new StreamReader(this.imagePath);
|
2013-12-16 01:04:17 +00:00
|
|
|
int line = 0;
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
while (cueStream.Peek() >= 0)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
|
|
|
|
line++;
|
2014-04-14 01:14:20 +00:00
|
|
|
string _line = cueStream.ReadLine();
|
2013-12-16 01:04:17 +00:00
|
|
|
|
|
|
|
|
Regex Sr = new Regex(SessionRegEx);
|
|
|
|
|
Regex Rr = new Regex(CommentRegEx);
|
|
|
|
|
Regex Cr = new Regex(MCNRegEx);
|
|
|
|
|
Regex Fr = new Regex(FileRegEx);
|
|
|
|
|
|
|
|
|
|
Match Sm;
|
|
|
|
|
Match Rm;
|
|
|
|
|
Match Cm;
|
|
|
|
|
Match Fm;
|
|
|
|
|
|
|
|
|
|
// First line must be SESSION, REM, CATALOG or FILE.
|
|
|
|
|
Sm = Sr.Match(_line);
|
|
|
|
|
Rm = Rr.Match(_line);
|
|
|
|
|
Cm = Cr.Match(_line);
|
|
|
|
|
Fm = Fr.Match(_line);
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
if (!Sm.Success && !Rm.Success && !Cm.Success && !Fm.Success)
|
2013-12-16 01:04:17 +00:00
|
|
|
return false;
|
2014-04-14 01:14:20 +00:00
|
|
|
return true;
|
2013-12-16 01:04:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
catch (Exception ex)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01: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);
|
2013-12-16 01:04:17 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
2013-12-16 01:04:17 +00:00
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
public override bool OpenImage(string imagePath)
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
if (imagePath == null)
|
|
|
|
|
return false;
|
|
|
|
|
if (imagePath == "")
|
2013-12-16 01:04:17 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
this.imagePath = imagePath;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
cueStream = new StreamReader(imagePath);
|
2013-12-16 01:04:17 +00:00
|
|
|
int line = 0;
|
|
|
|
|
bool intrack = false;
|
|
|
|
|
byte currentsession = 1;
|
|
|
|
|
|
|
|
|
|
// Initialize all RegExs
|
|
|
|
|
Regex RegexSession = new Regex(SessionRegEx);
|
|
|
|
|
Regex RegexDiskType = new Regex(DiskTypeRegEx);
|
|
|
|
|
Regex RegexLeadOut = new Regex(LeadOutRegEx);
|
|
|
|
|
Regex RegexLBA = new Regex(LBARegEx);
|
|
|
|
|
Regex RegexDiskID = new Regex(DiskIDRegEx);
|
|
|
|
|
Regex RegexBarCode = new Regex(BarCodeRegEx);
|
|
|
|
|
Regex RegexComment = new Regex(CommentRegEx);
|
|
|
|
|
Regex RegexCDText = new Regex(CDTextRegEx);
|
|
|
|
|
Regex RegexMCN = new Regex(MCNRegEx);
|
|
|
|
|
Regex RegexTitle = new Regex(TitleRegEx);
|
|
|
|
|
Regex RegexGenre = new Regex(GenreRegEx);
|
|
|
|
|
Regex RegexArranger = new Regex(ArrangerRegEx);
|
|
|
|
|
Regex RegexComposer = new Regex(ComposerRegEx);
|
|
|
|
|
Regex RegexPerformer = new Regex(PerformerRegEx);
|
|
|
|
|
Regex RegexSongWriter = new Regex(SongWriterRegEx);
|
|
|
|
|
Regex RegexFile = new Regex(FileRegEx);
|
|
|
|
|
Regex RegexTrack = new Regex(TrackRegEx);
|
|
|
|
|
Regex RegexISRC = new Regex(ISRCRegEx);
|
|
|
|
|
Regex RegexIndex = new Regex(IndexRegEx);
|
|
|
|
|
Regex RegexPregap = new Regex(PregapRegEx);
|
|
|
|
|
Regex RegexPostgap = new Regex(PostgapRegex);
|
|
|
|
|
Regex RegexFlags = new Regex(FlagsRegEx);
|
|
|
|
|
|
|
|
|
|
// Initialize all RegEx matches
|
|
|
|
|
Match MatchSession;
|
|
|
|
|
Match MatchDiskType;
|
|
|
|
|
Match MatchLeadOut;
|
|
|
|
|
Match MatchLBA;
|
|
|
|
|
Match MatchDiskID;
|
|
|
|
|
Match MatchBarCode;
|
|
|
|
|
Match MatchComment;
|
|
|
|
|
Match MatchCDText;
|
|
|
|
|
Match MatchMCN;
|
|
|
|
|
Match MatchTitle;
|
|
|
|
|
Match MatchGenre;
|
|
|
|
|
Match MatchArranger;
|
|
|
|
|
Match MatchComposer;
|
|
|
|
|
Match MatchPerformer;
|
|
|
|
|
Match MatchSongWriter;
|
|
|
|
|
Match MatchFile;
|
|
|
|
|
Match MatchTrack;
|
|
|
|
|
Match MatchISRC;
|
|
|
|
|
Match MatchIndex;
|
|
|
|
|
Match MatchPregap;
|
|
|
|
|
Match MatchPostgap;
|
|
|
|
|
Match MatchFlags;
|
|
|
|
|
|
|
|
|
|
// Initialize disc
|
2014-04-14 01:14:20 +00:00
|
|
|
discimage = new CDRWinDisc();
|
|
|
|
|
discimage.sessions = new List<Session>();
|
|
|
|
|
discimage.tracks = new List<CDRWinTrack>();
|
|
|
|
|
discimage.comment = "";
|
2013-12-16 01:04:17 +00:00
|
|
|
|
|
|
|
|
CDRWinTrack currenttrack = new CDRWinTrack();
|
2014-04-14 01:14:20 +00:00
|
|
|
currenttrack.indexes = new Dictionary<int, ulong>();
|
|
|
|
|
CDRWinTrackFile currentfile = new CDRWinTrackFile();
|
|
|
|
|
ulong currentfileoffsetsector = 0;
|
|
|
|
|
|
|
|
|
|
CDRWinTrack[] cuetracks;
|
|
|
|
|
int track_count = 0;
|
|
|
|
|
|
|
|
|
|
while (cueStream.Peek() >= 0)
|
|
|
|
|
{
|
|
|
|
|
line++;
|
|
|
|
|
string _line = cueStream.ReadLine();
|
|
|
|
|
|
|
|
|
|
MatchTrack = RegexTrack.Match(_line);
|
|
|
|
|
if (MatchTrack.Success)
|
|
|
|
|
{
|
|
|
|
|
uint track_seq = uint.Parse(MatchTrack.Groups[1].Value);
|
|
|
|
|
if (track_count + 1 != track_seq)
|
|
|
|
|
throw new FeatureUnsupportedImageException(String.Format("Found TRACK {0} out of order in line {1}", track_seq, line));
|
|
|
|
|
|
|
|
|
|
track_count++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (track_count == 0)
|
|
|
|
|
throw new FeatureUnsupportedImageException("No tracks found");
|
|
|
|
|
|
|
|
|
|
cuetracks = new CDRWinTrack[track_count];
|
2013-12-16 01:04:17 +00:00
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
line = 0;
|
2015-05-23 05:29:35 +01:00
|
|
|
// Mono <= 3.5 allowed this to work, with .Peek() NOT returning EOF.
|
|
|
|
|
// However .NET framework has always returned EOF even with this rewind.
|
|
|
|
|
// Mono 4.0 copied their bug (feature?)
|
|
|
|
|
//cueStream.BaseStream.Seek(0, SeekOrigin.Begin);
|
|
|
|
|
|
|
|
|
|
// Forcing me to do
|
|
|
|
|
cueStream.Close();
|
|
|
|
|
cueStream = new StreamReader(imagePath);
|
2014-04-14 01:14:20 +00:00
|
|
|
|
|
|
|
|
while (cueStream.Peek() >= 0)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
|
|
|
|
line++;
|
2014-04-14 01:14:20 +00:00
|
|
|
string _line = cueStream.ReadLine();
|
2013-12-16 01:04:17 +00:00
|
|
|
|
|
|
|
|
MatchSession = RegexSession.Match(_line);
|
|
|
|
|
MatchDiskType = RegexDiskType.Match(_line);
|
|
|
|
|
MatchComment = RegexComment.Match(_line);
|
|
|
|
|
MatchLBA = RegexLBA.Match(_line); // Unhandled, just ignored
|
|
|
|
|
MatchLeadOut = RegexLeadOut.Match(_line); // Unhandled, just ignored
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
if (MatchDiskType.Success && !intrack)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Found REM ORIGINAL MEDIA TYPE at line {0}", line);
|
2014-04-14 01:14:20 +00:00
|
|
|
discimage.disktypestr = MatchDiskType.Groups[1].Value;
|
|
|
|
|
}
|
|
|
|
|
else if (MatchDiskType.Success && intrack)
|
|
|
|
|
{
|
|
|
|
|
throw new FeatureUnsupportedImageException(String.Format("Found REM ORIGINAL MEDIA TYPE field after a track in line {0}", line));
|
2013-12-16 01:04:17 +00:00
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
else if (MatchSession.Success)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Found REM SESSION at line {0}", line);
|
2013-12-16 01:04:17 +00:00
|
|
|
currentsession = Byte.Parse(MatchSession.Groups[1].Value);
|
|
|
|
|
|
|
|
|
|
// What happens between sessions
|
|
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
else if (MatchLBA.Success)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Found REM MSF at line {0}", line);
|
2013-12-16 01:04:17 +00:00
|
|
|
// Just ignored
|
|
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
else if (MatchLeadOut.Success)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Found REM LEAD-OUT at line {0}", line);
|
2013-12-16 01:04:17 +00:00
|
|
|
// Just ignored
|
|
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
else if (MatchComment.Success)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Found REM at line {0}", line);
|
2014-04-14 01:14:20 +00:00
|
|
|
if (discimage.comment == "")
|
|
|
|
|
discimage.comment = MatchComment.Groups[1].Value; // First comment
|
|
|
|
|
else
|
|
|
|
|
discimage.comment += Environment.NewLine + MatchComment.Groups[1].Value; // Append new comments as new lines
|
2013-12-16 01:04:17 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
MatchTrack = RegexTrack.Match(_line);
|
|
|
|
|
MatchTitle = RegexTitle.Match(_line);
|
|
|
|
|
MatchSongWriter = RegexSongWriter.Match(_line);
|
|
|
|
|
MatchPregap = RegexPregap.Match(_line);
|
|
|
|
|
MatchPostgap = RegexPostgap.Match(_line);
|
|
|
|
|
MatchPerformer = RegexPerformer.Match(_line);
|
|
|
|
|
MatchMCN = RegexMCN.Match(_line);
|
|
|
|
|
MatchISRC = RegexISRC.Match(_line);
|
|
|
|
|
MatchIndex = RegexIndex.Match(_line);
|
|
|
|
|
MatchGenre = RegexGenre.Match(_line);
|
|
|
|
|
MatchFlags = RegexFlags.Match(_line);
|
|
|
|
|
MatchFile = RegexFile.Match(_line);
|
|
|
|
|
MatchDiskID = RegexDiskID.Match(_line);
|
|
|
|
|
MatchComposer = RegexComposer.Match(_line);
|
|
|
|
|
MatchCDText = RegexCDText.Match(_line);
|
|
|
|
|
MatchBarCode = RegexBarCode.Match(_line);
|
|
|
|
|
MatchArranger = RegexArranger.Match(_line);
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
if (MatchArranger.Success)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Found ARRANGER at line {0}", line);
|
2014-04-14 01:14:20 +00:00
|
|
|
if (intrack)
|
2013-12-16 01:04:17 +00:00
|
|
|
currenttrack.arranger = MatchArranger.Groups[1].Value;
|
|
|
|
|
else
|
2014-04-14 01:14:20 +00:00
|
|
|
discimage.arranger = MatchArranger.Groups[1].Value;
|
2013-12-16 01:04:17 +00:00
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
else if (MatchBarCode.Success)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Found UPC_EAN at line {0}", line);
|
2014-04-14 01:14:20 +00:00
|
|
|
if (!intrack)
|
|
|
|
|
discimage.barcode = MatchBarCode.Groups[1].Value;
|
2013-12-16 01:04:17 +00:00
|
|
|
else
|
|
|
|
|
throw new FeatureUnsupportedImageException(String.Format("Found barcode field in incorrect place at line {0}", line));
|
|
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
else if (MatchCDText.Success)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Found CDTEXTFILE at line {0}", line);
|
2014-04-14 01:14:20 +00:00
|
|
|
if (!intrack)
|
|
|
|
|
discimage.cdtextfile = MatchCDText.Groups[1].Value;
|
2013-12-16 01:04:17 +00:00
|
|
|
else
|
|
|
|
|
throw new FeatureUnsupportedImageException(String.Format("Found CD-Text file field in incorrect place at line {0}", line));
|
|
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
else if (MatchComposer.Success)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Found COMPOSER at line {0}", line);
|
2014-04-14 01:14:20 +00:00
|
|
|
if (intrack)
|
2013-12-16 01:04:17 +00:00
|
|
|
currenttrack.arranger = MatchComposer.Groups[1].Value;
|
|
|
|
|
else
|
2014-04-14 01:14:20 +00:00
|
|
|
discimage.arranger = MatchComposer.Groups[1].Value;
|
2013-12-16 01:04:17 +00:00
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
else if (MatchDiskID.Success)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Found DISC_ID at line {0}", line);
|
2014-04-14 01:14:20 +00:00
|
|
|
if (!intrack)
|
|
|
|
|
discimage.disk_id = MatchDiskID.Groups[1].Value;
|
2013-12-16 01:04:17 +00:00
|
|
|
else
|
|
|
|
|
throw new FeatureUnsupportedImageException(String.Format("Found CDDB ID field in incorrect place at line {0}", line));
|
|
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
else if (MatchFile.Success)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Found FILE at line {0}", line);
|
2014-04-14 01:14:20 +00:00
|
|
|
|
|
|
|
|
if (currenttrack.sequence != 0)
|
|
|
|
|
{
|
|
|
|
|
currentfile.sequence = currenttrack.sequence;
|
|
|
|
|
currenttrack.trackfile = currentfile;
|
|
|
|
|
FileInfo finfo = new FileInfo(currentfile.datafile);
|
|
|
|
|
currenttrack.sectors = ((ulong)finfo.Length - currentfile.offset) / CDRWinTrackTypeToBytesPerSector(currenttrack.tracktype);
|
|
|
|
|
cuetracks[currenttrack.sequence - 1] = currenttrack;
|
|
|
|
|
intrack = false;
|
|
|
|
|
currenttrack = new CDRWinTrack();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
currentfile.datafile = MatchFile.Groups[1].Value;
|
|
|
|
|
currentfile.filetype = MatchFile.Groups[2].Value;
|
|
|
|
|
|
|
|
|
|
// Check if file path is quoted
|
|
|
|
|
if (currentfile.datafile[0] == '"' && currentfile.datafile[currentfile.datafile.Length - 1] == '"')
|
|
|
|
|
{
|
|
|
|
|
currentfile.datafile = currentfile.datafile.Substring(1, currentfile.datafile.Length - 2); // Unquote it
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if file exists
|
|
|
|
|
if (!File.Exists(currentfile.datafile))
|
|
|
|
|
{
|
|
|
|
|
if (currentfile.datafile[0] == '/' || (currentfile.datafile[0] == '/' && currentfile.datafile[1] == '.')) // UNIX absolute path
|
|
|
|
|
{
|
|
|
|
|
Regex unixpath = new Regex("^(.+)/([^/]+)$");
|
|
|
|
|
Match unixpathmatch = unixpath.Match(currentfile.datafile);
|
|
|
|
|
|
|
|
|
|
if (unixpathmatch.Success)
|
|
|
|
|
{
|
|
|
|
|
currentfile.datafile = unixpathmatch.Groups[1].Value;
|
|
|
|
|
|
|
|
|
|
if (!File.Exists(currentfile.datafile))
|
|
|
|
|
{
|
|
|
|
|
string path = Path.GetPathRoot(imagePath);
|
|
|
|
|
currentfile.datafile = path + Path.PathSeparator + currentfile.datafile;
|
|
|
|
|
|
|
|
|
|
if (!File.Exists(currentfile.datafile))
|
|
|
|
|
throw new FeatureUnsupportedImageException(String.Format("File \"{0}\" not found.", MatchFile.Groups[1].Value));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
throw new FeatureUnsupportedImageException(String.Format("File \"{0}\" not found.", MatchFile.Groups[1].Value));
|
|
|
|
|
}
|
|
|
|
|
else if ((currentfile.datafile[1] == ':' && currentfile.datafile[2] == '\\') ||
|
|
|
|
|
(currentfile.datafile[0] == '\\' && currentfile.datafile[1] == '\\') ||
|
|
|
|
|
((currentfile.datafile[0] == '.' && currentfile.datafile[1] == '\\'))) // Windows absolute path
|
|
|
|
|
{
|
|
|
|
|
Regex winpath = new Regex("^(?:[a-zA-Z]\\:(\\\\|\\/)|file\\:\\/\\/|\\\\\\\\|\\.(\\/|\\\\))([^\\\\\\/\\:\\*\\?\\<\\>\\\"\\|]+(\\\\|\\/){0,1})+$");
|
|
|
|
|
Match winpathmatch = winpath.Match(currentfile.datafile);
|
|
|
|
|
if (winpathmatch.Success)
|
|
|
|
|
{
|
|
|
|
|
currentfile.datafile = winpathmatch.Groups[1].Value;
|
|
|
|
|
|
|
|
|
|
if (!File.Exists(currentfile.datafile))
|
|
|
|
|
{
|
|
|
|
|
string path = Path.GetPathRoot(imagePath);
|
|
|
|
|
currentfile.datafile = path + Path.PathSeparator + currentfile.datafile;
|
|
|
|
|
|
|
|
|
|
if (!File.Exists(currentfile.datafile))
|
|
|
|
|
throw new FeatureUnsupportedImageException(String.Format("File \"{0}\" not found.", MatchFile.Groups[1].Value));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
throw new FeatureUnsupportedImageException(String.Format("File \"{0}\" not found.", MatchFile.Groups[1].Value));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
string path = Path.GetDirectoryName(imagePath);
|
|
|
|
|
currentfile.datafile = path + Path.DirectorySeparatorChar + currentfile.datafile;
|
|
|
|
|
|
|
|
|
|
if (!File.Exists(currentfile.datafile))
|
|
|
|
|
throw new FeatureUnsupportedImageException(String.Format("File \"{0}\" not found.", MatchFile.Groups[1].Value));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// File does exist, process it
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "File \"{0}\" found", currentfile.datafile);
|
2014-04-14 01:14:20 +00:00
|
|
|
|
|
|
|
|
switch (currentfile.filetype)
|
|
|
|
|
{
|
|
|
|
|
case CDRWinDiskTypeLittleEndian:
|
|
|
|
|
break;
|
|
|
|
|
case CDRWinDiskTypeBigEndian:
|
|
|
|
|
case CDRWinDiskTypeAIFF:
|
|
|
|
|
case CDRWinDiskTypeRIFF:
|
|
|
|
|
case CDRWinDiskTypeMP3:
|
|
|
|
|
throw new FeatureSupportedButNotImplementedImageException(String.Format("Unsupported file type {0}", currentfile.filetype));
|
|
|
|
|
default:
|
|
|
|
|
throw new FeatureUnsupportedImageException(String.Format("Unknown file type {0}", currentfile.filetype));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
currentfile.offset = 0;
|
|
|
|
|
currentfile.sequence = 0;
|
2013-12-16 01:04:17 +00:00
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
else if (MatchFlags.Success)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Found FLAGS at line {0}", line);
|
2014-04-14 01:14:20 +00:00
|
|
|
if (!intrack)
|
2013-12-16 01:04:17 +00:00
|
|
|
throw new FeatureUnsupportedImageException(String.Format("Found FLAGS field in incorrect place at line {0}", line));
|
2015-12-23 23:46:31 +00:00
|
|
|
|
|
|
|
|
const string FlagsRegEx = "FLAGS\\s+(((?<dcp>DCP)|(?<quad>4CH)|(?<pre>PRE)|(?<scms>SCMS))\\s*)+$";
|
|
|
|
|
currenttrack.flag_dcp |= MatchFile.Groups["dcp"].Value == "DCP";
|
|
|
|
|
currenttrack.flag_4ch |= MatchFile.Groups["quad"].Value == "4CH";
|
|
|
|
|
currenttrack.flag_pre |= MatchFile.Groups["pre"].Value == "PRE";
|
|
|
|
|
currenttrack.flag_scms |= MatchFile.Groups["scms"].Value == "SCMS";
|
2013-12-16 01:04:17 +00:00
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
else if (MatchGenre.Success)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Found GENRE at line {0}", line);
|
2014-04-14 01:14:20 +00:00
|
|
|
if (intrack)
|
2013-12-16 01:04:17 +00:00
|
|
|
currenttrack.genre = MatchGenre.Groups[1].Value;
|
|
|
|
|
else
|
2014-04-14 01:14:20 +00:00
|
|
|
discimage.genre = MatchGenre.Groups[1].Value;
|
2013-12-16 01:04:17 +00:00
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
else if (MatchIndex.Success)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Found INDEX at line {0}", line);
|
2014-04-14 01:14:20 +00:00
|
|
|
if (!intrack)
|
2013-12-16 01:04:17 +00:00
|
|
|
throw new FeatureUnsupportedImageException(String.Format("Found INDEX before a track {0}", line));
|
|
|
|
|
else
|
|
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
int index = int.Parse(MatchIndex.Groups[1].Value);
|
|
|
|
|
ulong offset = CDRWinMSFToLBA(MatchIndex.Groups[2].Value);
|
|
|
|
|
|
|
|
|
|
if ((index != 0 && index != 1) && currenttrack.indexes.Count == 0)
|
|
|
|
|
throw new FeatureUnsupportedImageException(String.Format("Found INDEX {0} before INDEX 00 or INDEX 01", index));
|
|
|
|
|
|
|
|
|
|
if ((index == 0 || (index == 1 && !currenttrack.indexes.ContainsKey(0))))
|
|
|
|
|
{
|
|
|
|
|
if ((int)(currenttrack.sequence - 2) >= 0 && offset > 1)
|
|
|
|
|
{
|
|
|
|
|
cuetracks[currenttrack.sequence - 2].sectors = offset - currentfileoffsetsector;
|
|
|
|
|
currentfile.offset += cuetracks[currenttrack.sequence - 2].sectors * cuetracks[currenttrack.sequence - 2].bps;
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Sets currentfile.offset to {0} at line 553", currentfile.offset);
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "cuetracks[currenttrack.sequence-2].sectors = {0}", cuetracks[currenttrack.sequence - 2].sectors);
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "cuetracks[currenttrack.sequence-2].bps = {0}", cuetracks[currenttrack.sequence - 2].bps);
|
2014-04-14 01:14:20 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((index == 0 || (index == 1 && !currenttrack.indexes.ContainsKey(0))) && currenttrack.sequence == 1)
|
|
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Sets currentfile.offset to {0} at line 559", offset * currenttrack.bps);
|
2014-04-14 01:14:20 +00:00
|
|
|
currentfile.offset = offset * currenttrack.bps;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
currentfileoffsetsector = offset;
|
|
|
|
|
currenttrack.indexes.Add(index, offset);
|
2013-12-16 01:04:17 +00:00
|
|
|
}
|
|
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
else if (MatchISRC.Success)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Found ISRC at line {0}", line);
|
2014-04-14 01:14:20 +00:00
|
|
|
if (!intrack)
|
2013-12-16 01:04:17 +00:00
|
|
|
throw new FeatureUnsupportedImageException(String.Format("Found ISRC before a track {0}", line));
|
2014-04-14 01:14:20 +00:00
|
|
|
currenttrack.isrc = MatchISRC.Groups[1].Value;
|
2013-12-16 01:04:17 +00:00
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
else if (MatchMCN.Success)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Found CATALOG at line {0}", line);
|
2014-04-14 01:14:20 +00:00
|
|
|
if (!intrack)
|
|
|
|
|
discimage.mcn = MatchMCN.Groups[1].Value;
|
2013-12-16 01:04:17 +00:00
|
|
|
else
|
|
|
|
|
throw new FeatureUnsupportedImageException(String.Format("Found CATALOG field in incorrect place at line {0}", line));
|
|
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
else if (MatchPerformer.Success)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Found PERFORMER at line {0}", line);
|
2014-04-14 01:14:20 +00:00
|
|
|
if (intrack)
|
2013-12-16 01:04:17 +00:00
|
|
|
currenttrack.performer = MatchPerformer.Groups[1].Value;
|
|
|
|
|
else
|
2014-04-14 01:14:20 +00:00
|
|
|
discimage.performer = MatchPerformer.Groups[1].Value;
|
2013-12-16 01:04:17 +00:00
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
else if (MatchPostgap.Success)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Found POSTGAP at line {0}", line);
|
2014-04-14 01:14:20 +00:00
|
|
|
if (intrack)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
currenttrack.postgap = CDRWinMSFToLBA(MatchPostgap.Groups[1].Value);
|
2013-12-16 01:04:17 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
throw new FeatureUnsupportedImageException(String.Format("Found POSTGAP field before a track at line {0}", line));
|
|
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
else if (MatchPregap.Success)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Found PREGAP at line {0}", line);
|
2014-04-14 01:14:20 +00:00
|
|
|
if (intrack)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
currenttrack.pregap = CDRWinMSFToLBA(MatchPregap.Groups[1].Value);
|
2013-12-16 01:04:17 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
throw new FeatureUnsupportedImageException(String.Format("Found PREGAP field before a track at line {0}", line));
|
|
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
else if (MatchSongWriter.Success)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Found SONGWRITER at line {0}", line);
|
2014-04-14 01:14:20 +00:00
|
|
|
if (intrack)
|
2013-12-16 01:04:17 +00:00
|
|
|
currenttrack.songwriter = MatchSongWriter.Groups[1].Value;
|
|
|
|
|
else
|
2014-04-14 01:14:20 +00:00
|
|
|
discimage.songwriter = MatchSongWriter.Groups[1].Value;
|
2013-12-16 01:04:17 +00:00
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
else if (MatchTitle.Success)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Found TITLE at line {0}", line);
|
2014-04-14 01:14:20 +00:00
|
|
|
if (intrack)
|
2013-12-16 01:04:17 +00:00
|
|
|
currenttrack.title = MatchTitle.Groups[1].Value;
|
|
|
|
|
else
|
2014-04-14 01:14:20 +00:00
|
|
|
discimage.title = MatchTitle.Groups[1].Value;
|
2013-12-16 01:04:17 +00:00
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
else if (MatchTrack.Success)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Found TRACK at line {0}", line);
|
2014-04-14 01:14:20 +00:00
|
|
|
if (currentfile.datafile == "")
|
2013-12-16 01:04:17 +00:00
|
|
|
throw new FeatureUnsupportedImageException(String.Format("Found TRACK field before a file is defined at line {0}", line));
|
2014-04-14 01:14:20 +00:00
|
|
|
if (intrack)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
if (currenttrack.indexes.ContainsKey(0) && currenttrack.pregap == 0)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
currenttrack.indexes.TryGetValue(0, out currenttrack.pregap);
|
2013-12-16 01:04:17 +00:00
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
currentfile.sequence = currenttrack.sequence;
|
|
|
|
|
currenttrack.trackfile = currentfile;
|
|
|
|
|
cuetracks[currenttrack.sequence - 1] = currenttrack;
|
|
|
|
|
}
|
|
|
|
|
currenttrack = new CDRWinTrack();
|
|
|
|
|
currenttrack.indexes = new Dictionary<int, ulong>();
|
|
|
|
|
currenttrack.sequence = uint.Parse(MatchTrack.Groups[1].Value);
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Setting currenttrack.sequence to {0}", currenttrack.sequence);
|
2014-04-14 01:14:20 +00:00
|
|
|
currentfile.sequence = currenttrack.sequence;
|
|
|
|
|
currenttrack.bps = CDRWinTrackTypeToBytesPerSector(MatchTrack.Groups[2].Value);
|
|
|
|
|
currenttrack.tracktype = MatchTrack.Groups[2].Value;
|
|
|
|
|
currenttrack.session = currentsession;
|
|
|
|
|
intrack = true;
|
|
|
|
|
}
|
|
|
|
|
else if (_line == "") // Empty line, ignore it
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else // Non-empty unknown field
|
|
|
|
|
{
|
|
|
|
|
throw new FeatureUnsupportedImageException(String.Format("Found unknown field defined at line {0}: \"{1}\"", line, _line));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (currenttrack.sequence != 0)
|
|
|
|
|
{
|
|
|
|
|
currentfile.sequence = currenttrack.sequence;
|
|
|
|
|
currenttrack.trackfile = currentfile;
|
|
|
|
|
FileInfo finfo = new FileInfo(currentfile.datafile);
|
|
|
|
|
currenttrack.sectors = ((ulong)finfo.Length - currentfile.offset) / CDRWinTrackTypeToBytesPerSector(currenttrack.tracktype);
|
|
|
|
|
cuetracks[currenttrack.sequence - 1] = currenttrack;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Session[] _sessions = new Session[currentsession];
|
|
|
|
|
for (int s = 1; s <= _sessions.Length; s++)
|
|
|
|
|
{
|
|
|
|
|
_sessions[s - 1].SessionSequence = 1;
|
|
|
|
|
|
|
|
|
|
if (s > 1)
|
|
|
|
|
_sessions[s - 1].StartSector = _sessions[s - 2].EndSector + 1;
|
|
|
|
|
else
|
|
|
|
|
_sessions[s - 1].StartSector = 0;
|
|
|
|
|
|
|
|
|
|
ulong session_sectors = 0;
|
|
|
|
|
int last_session_track = 0;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < cuetracks.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
if (cuetracks[i].session == s)
|
|
|
|
|
{
|
|
|
|
|
session_sectors += cuetracks[i].sectors;
|
|
|
|
|
if (i > last_session_track)
|
|
|
|
|
last_session_track = i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_sessions[s - 1].EndTrack = cuetracks[last_session_track].sequence;
|
|
|
|
|
_sessions[s - 1].EndSector = session_sectors - 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int s = 1; s <= _sessions.Length; s++)
|
|
|
|
|
discimage.sessions.Add(_sessions[s - 1]);
|
|
|
|
|
|
|
|
|
|
for (int t = 1; t <= cuetracks.Length; t++)
|
|
|
|
|
discimage.tracks.Add(cuetracks[t - 1]);
|
|
|
|
|
|
2016-01-16 03:54:55 +00:00
|
|
|
discimage.disktype = CDRWinIsoBusterDiscTypeToMediaType(discimage.disktypestr);
|
2013-12-16 01:04:17 +00:00
|
|
|
|
2016-01-16 03:54:55 +00:00
|
|
|
if (discimage.disktype == MediaType.Unknown || discimage.disktype == MediaType.CD)
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
|
|
|
|
bool data = false;
|
|
|
|
|
bool cdg = false;
|
|
|
|
|
bool cdi = false;
|
|
|
|
|
bool mode2 = false;
|
|
|
|
|
bool firstaudio = false;
|
|
|
|
|
bool firstdata = false;
|
|
|
|
|
bool audio = false;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < discimage.tracks.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
// First track is audio
|
|
|
|
|
firstaudio |= i == 0 && discimage.tracks[i].tracktype == CDRWinTrackTypeAudio;
|
|
|
|
|
|
|
|
|
|
// First track is data
|
|
|
|
|
firstdata |= i == 0 && discimage.tracks[i].tracktype != CDRWinTrackTypeAudio;
|
|
|
|
|
|
|
|
|
|
// Any non first track is data
|
|
|
|
|
data |= i != 0 && discimage.tracks[i].tracktype != CDRWinTrackTypeAudio;
|
|
|
|
|
|
|
|
|
|
// Any non first track is audio
|
|
|
|
|
audio |= i != 0 && discimage.tracks[i].tracktype == CDRWinTrackTypeAudio;
|
|
|
|
|
|
|
|
|
|
switch (discimage.tracks[i].tracktype)
|
|
|
|
|
{
|
|
|
|
|
case CDRWinTrackTypeCDG:
|
|
|
|
|
cdg = true;
|
|
|
|
|
break;
|
|
|
|
|
case CDRWinTrackTypeCDI:
|
|
|
|
|
case CDRWinTrackTypeCDIRaw:
|
|
|
|
|
cdi = true;
|
|
|
|
|
break;
|
|
|
|
|
case CDRWinTrackTypeMode2Form1:
|
|
|
|
|
case CDRWinTrackTypeMode2Form2:
|
|
|
|
|
case CDRWinTrackTypeMode2Formless:
|
|
|
|
|
case CDRWinTrackTypeMode2Raw:
|
|
|
|
|
mode2 = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!data && !firstdata)
|
2016-01-16 03:54:55 +00:00
|
|
|
discimage.disktype = MediaType.CDDA;
|
2014-04-14 01:14:20 +00:00
|
|
|
else if (cdg)
|
2016-01-16 03:54:55 +00:00
|
|
|
discimage.disktype = MediaType.CDG;
|
2014-04-14 01:14:20 +00:00
|
|
|
else if (cdi)
|
2016-01-16 03:54:55 +00:00
|
|
|
discimage.disktype = MediaType.CDI;
|
2014-04-14 01:14:20 +00:00
|
|
|
else if (firstaudio && data && discimage.sessions.Count > 1 && mode2)
|
2016-01-16 03:54:55 +00:00
|
|
|
discimage.disktype = MediaType.CDPLUS;
|
* commandline:
* DiscImageChef.Settings/Settings.cs:
* DiscImageChef.Settings/docs/README.txt:
* DiscImageChef.Settings/packages.config:
* DiscImageChef.Settings/docs/LICENSE.txt:
* DiscImageChef.Settings/docs/ChangeLog.txt:
* DiscImageChef.Settings/docs/mono/index.xml:
* DiscImageChef.Settings/docs/html/index.html:
* DiscImageChef.Settings/Properties/AssemblyInfo.cs:
* DiscImageChef.Settings/DiscImageChef.Settings.csproj:
* DiscImageChef.Settings/docs/mono/ns-Claunia.PropertyList.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/UID.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/UID.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSSet.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/index.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSSet.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSDate.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSData.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSDate.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSData.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSArray.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSNumber.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSString.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSObject.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSArray.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSNumber.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSString.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSObject.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSDictionary.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSDictionary.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/PropertyListParser.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/PropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/XmlPropertyListParser.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/XmlPropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/ASCIIPropertyListParser.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/ASCIIPropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/BinaryPropertyListParser.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/BinaryPropertyListWriter.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/BinaryPropertyListWriter.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/BinaryPropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/PropertyListFormatException.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/PropertyListFormatException.html:
Added supports for settings
* DiscImageChef/Commands/Configure.cs:
Added support for settings.
* DiscImageChef/Core/Statistics.cs:
* DiscImageChef/Commands/Verify.cs:
* DiscImageChef/Commands/Entropy.cs:
* DiscImageChef/Commands/Formats.cs:
* DiscImageChef/Commands/PrintHex.cs:
* DiscImageChef/Commands/MediaInfo.cs:
* DiscImageChef/Commands/Statistics.cs:
Added statistics.
* DiscImageChef.Decoders/SCSI/Inquiry.cs:
Corrected bug on inquiry decoding.
* DiscImageChef.Decoders/SCSI/Modes.cs:
Corrected bug on decoding mode page 2Ah without write
performance descriptors.
Corrected bug when there is a vendor page 0 in mode sense
decoding.
* DiscImageChef.Devices/Device/Constructor.cs:
Corrected detecting USB or FireWire attached CD/DVD/BD and
tape drives.
Try ATA identify on USB or FireWire that don't have SCSI
INQUIRY.
* DiscImageChef.DiscImages/CDRWin.cs:
Corrected CD-ROM XA vs CD-ROM detection.
* DiscImageChef.Partitions/AppleMap.cs:
Corrected big endian working.
Added debug output.
* DiscImageChef.sln:
Added supports for settings.
* DiscImageChef/Commands/Decode.cs:
* DiscImageChef/Commands/Analyze.cs:
* DiscImageChef/Commands/Compare.cs:
* DiscImageChef/Commands/Checksum.cs:
* DiscImageChef/Commands/Benchmark.cs:
* DiscImageChef/Commands/DeviceInfo.cs:
* DiscImageChef/Commands/CreateSidecar.cs:
Added statistics.
* DiscImageChef/Commands/DeviceReport.cs:
Added statistics.
Correct handling empty inquiry string fields.
Suppose it is not removable, til proved wrong.
Corrected MODE SENSE (6/10) detection and calling order.
If device is MMC type but reports neither mode page 2Ah
neither GET CONFIGURATION, try all CDs (old drives work like
that).
Try reading Lead-In and Lead-Out in Audio CD using Audio READ
CD commands.
Corrected READ LONG information handling, some drives return
2s-complement in 32 bit. Upper 16 bits are ignored.
Added support for DVD raw block (37856 bytes).
Check READ LONG up to 36 times the cooked block size. That
should be enough to detect huge blocked media (like DVD and
BD) without taking ages.
If READ LONG size had to be bruteforced, and debug is
activated, save the result.
* DiscImageChef/Commands/DumpMedia.cs:
Added statistics.
Corrected READ LONG information handling, some drives return
2s-complement in 32 bit. Upper 16 bits are ignored.
Start trying with 64 blocks at a time. Some drives report to
be able to read 255 at a time, but they really don't, they
take a lot longer to read.
* DiscImageChef/Commands/MediaScan.cs:
Added statistics.
Start trying with 64 blocks at a time. Some drives report to
be able to read 255 at a time, but they really don't, they
take a lot longer to read.
* DiscImageChef/DiscImageChef.csproj:
Added support for settings.
Added statistics.
* DiscImageChef/Main.cs:
* DiscImageChef/Options.cs:
Added support for settings.
Added statistics.
2016-02-03 18:58:11 +00:00
|
|
|
else if ((firstdata && audio) || mode2)
|
2016-01-16 03:54:55 +00:00
|
|
|
discimage.disktype = MediaType.CDROMXA;
|
2014-04-14 01:14:20 +00:00
|
|
|
else if (!audio)
|
2016-01-16 03:54:55 +00:00
|
|
|
discimage.disktype = MediaType.CDROM;
|
2014-04-14 01:14:20 +00:00
|
|
|
else
|
2016-01-16 03:54:55 +00:00
|
|
|
discimage.disktype = MediaType.CD;
|
2014-04-14 01:14:20 +00:00
|
|
|
}
|
|
|
|
|
|
2015-10-18 22:04:03 +01:00
|
|
|
// DEBUG information
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Disc image parsing results");
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Disc CD-TEXT:");
|
|
|
|
|
if (discimage.arranger == null)
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tArranger is not set.");
|
|
|
|
|
else
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tArranger: {0}", discimage.arranger);
|
|
|
|
|
if (discimage.composer == null)
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tComposer is not set.");
|
|
|
|
|
else
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tComposer: {0}", discimage.composer);
|
|
|
|
|
if (discimage.genre == null)
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tGenre is not set.");
|
|
|
|
|
else
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tGenre: {0}", discimage.genre);
|
|
|
|
|
if (discimage.performer == null)
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tPerformer is not set.");
|
|
|
|
|
else
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tPerformer: {0}", discimage.performer);
|
|
|
|
|
if (discimage.songwriter == null)
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tSongwriter is not set.");
|
|
|
|
|
else
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tSongwriter: {0}", discimage.songwriter);
|
|
|
|
|
if (discimage.title == null)
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tTitle is not set.");
|
|
|
|
|
else
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tTitle: {0}", discimage.title);
|
|
|
|
|
if (discimage.cdtextfile == null)
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tCD-TEXT binary file not set.");
|
|
|
|
|
else
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tCD-TEXT binary file: {0}", discimage.cdtextfile);
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Disc information:");
|
|
|
|
|
if (discimage.disktypestr == null)
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tISOBuster disc type not set.");
|
|
|
|
|
else
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tISOBuster disc type: {0}", discimage.disktypestr);
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tGuessed disk type: {0}", discimage.disktype);
|
|
|
|
|
if (discimage.barcode == null)
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tBarcode not set.");
|
|
|
|
|
else
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tBarcode: {0}", discimage.barcode);
|
|
|
|
|
if (discimage.disk_id == null)
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tDisc ID not set.");
|
|
|
|
|
else
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tDisc ID: {0}", discimage.disk_id);
|
|
|
|
|
if (discimage.mcn == null)
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tMCN not set.");
|
|
|
|
|
else
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tMCN: {0}", discimage.mcn);
|
|
|
|
|
if (discimage.comment == null)
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tComment not set.");
|
|
|
|
|
else
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tComment: \"{0}\"", discimage.comment);
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Session information:");
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tDisc contains {0} sessions", discimage.sessions.Count);
|
|
|
|
|
for (int i = 0; i < discimage.sessions.Count; i++)
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tSession {0} information:", i + 1);
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tStarting track: {0}", discimage.sessions[i].StartTrack);
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tStarting sector: {0}", discimage.sessions[i].StartSector);
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tEnding track: {0}", discimage.sessions[i].EndTrack);
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tEnding sector: {0}", discimage.sessions[i].EndSector);
|
|
|
|
|
}
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Track information:");
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tDisc contains {0} tracks", discimage.tracks.Count);
|
|
|
|
|
for (int i = 0; i < discimage.tracks.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tTrack {0} information:", discimage.tracks[i].sequence);
|
|
|
|
|
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\t{0} bytes per sector", discimage.tracks[i].bps);
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tPregap: {0} sectors", discimage.tracks[i].pregap);
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tData: {0} sectors", discimage.tracks[i].sectors);
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tPostgap: {0} sectors", discimage.tracks[i].postgap);
|
|
|
|
|
|
|
|
|
|
if (discimage.tracks[i].flag_4ch)
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tTrack is flagged as quadraphonic");
|
|
|
|
|
if (discimage.tracks[i].flag_dcp)
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tTrack allows digital copy");
|
|
|
|
|
if (discimage.tracks[i].flag_pre)
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tTrack has pre-emphasis applied");
|
|
|
|
|
if (discimage.tracks[i].flag_scms)
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tTrack has SCMS");
|
|
|
|
|
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tTrack resides in file {0}, type defined as {1}, starting at byte {2}",
|
|
|
|
|
discimage.tracks[i].trackfile.datafile, discimage.tracks[i].trackfile.filetype, discimage.tracks[i].trackfile.offset);
|
|
|
|
|
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tIndexes:");
|
|
|
|
|
foreach (KeyValuePair<int, ulong> kvp in discimage.tracks[i].indexes)
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\t\tIndex {0} starts at sector {1}", kvp.Key, kvp.Value);
|
|
|
|
|
|
|
|
|
|
if (discimage.tracks[i].isrc == null)
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tISRC is not set.");
|
2014-04-14 01:14:20 +00:00
|
|
|
else
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tISRC: {0}", discimage.tracks[i].isrc);
|
|
|
|
|
|
|
|
|
|
if (discimage.tracks[i].arranger == null)
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tArranger is not set.");
|
2014-04-14 01:14:20 +00:00
|
|
|
else
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tArranger: {0}", discimage.tracks[i].arranger);
|
|
|
|
|
if (discimage.tracks[i].composer == null)
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tComposer is not set.");
|
2014-04-14 01:14:20 +00:00
|
|
|
else
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tComposer: {0}", discimage.tracks[i].composer);
|
|
|
|
|
if (discimage.tracks[i].genre == null)
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tGenre is not set.");
|
2014-04-14 01:31:32 +00:00
|
|
|
else
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tGenre: {0}", discimage.tracks[i].genre);
|
|
|
|
|
if (discimage.tracks[i].performer == null)
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tPerformer is not set.");
|
2014-04-14 01:31:32 +00:00
|
|
|
else
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tPerformer: {0}", discimage.tracks[i].performer);
|
|
|
|
|
if (discimage.tracks[i].songwriter == null)
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tSongwriter is not set.");
|
2014-04-14 01:31:32 +00:00
|
|
|
else
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tSongwriter: {0}", discimage.tracks[i].songwriter);
|
|
|
|
|
if (discimage.tracks[i].title == null)
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tTitle is not set.");
|
2014-04-14 01:31:32 +00:00
|
|
|
else
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\t\tTitle: {0}", discimage.tracks[i].title);
|
2014-04-14 01:14:20 +00:00
|
|
|
}
|
|
|
|
|
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Building offset map");
|
2014-04-14 01:14:20 +00:00
|
|
|
|
2015-10-05 19:45:07 +01:00
|
|
|
partitions = new List<CommonTypes.Partition>();
|
2014-04-14 01:14:20 +00:00
|
|
|
|
|
|
|
|
ulong byte_offset = 0;
|
|
|
|
|
ulong sector_offset = 0;
|
|
|
|
|
ulong partitionSequence = 0;
|
|
|
|
|
ulong index_zero_offset = 0;
|
|
|
|
|
ulong index_one_offset = 0;
|
|
|
|
|
bool index_zero = false;
|
|
|
|
|
|
|
|
|
|
offsetmap = new Dictionary<uint, ulong>();
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < discimage.tracks.Count; i++)
|
|
|
|
|
{
|
2015-11-09 19:42:00 +00:00
|
|
|
ulong index0_len = 0;
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
if (discimage.tracks[i].sequence == 1 && i != 0)
|
|
|
|
|
throw new ImageNotSupportedException("Unordered tracks");
|
|
|
|
|
|
2015-10-05 19:45:07 +01:00
|
|
|
CommonTypes.Partition partition = new CommonTypes.Partition();
|
2014-04-14 01:14:20 +00:00
|
|
|
|
|
|
|
|
if (discimage.tracks[i].pregap > 0)
|
|
|
|
|
{
|
|
|
|
|
partition.PartitionDescription = String.Format("Track {0} pregap.", discimage.tracks[i].sequence);
|
|
|
|
|
partition.PartitionName = discimage.tracks[i].title;
|
|
|
|
|
partition.PartitionStartSector = sector_offset;
|
|
|
|
|
partition.PartitionLength = discimage.tracks[i].pregap * discimage.tracks[i].bps;
|
|
|
|
|
partition.PartitionSectors = discimage.tracks[i].pregap;
|
|
|
|
|
partition.PartitionSequence = partitionSequence;
|
|
|
|
|
partition.PartitionStart = byte_offset;
|
|
|
|
|
partition.PartitionType = discimage.tracks[i].tracktype;
|
|
|
|
|
|
|
|
|
|
sector_offset += partition.PartitionSectors;
|
|
|
|
|
byte_offset += partition.PartitionLength;
|
|
|
|
|
partitionSequence++;
|
|
|
|
|
|
2014-04-14 01:31:32 +00:00
|
|
|
if (!offsetmap.ContainsKey(discimage.tracks[i].sequence))
|
2014-04-14 01:14:20 +00:00
|
|
|
offsetmap.Add(discimage.tracks[i].sequence, partition.PartitionStartSector);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ulong old_start;
|
|
|
|
|
offsetmap.TryGetValue(discimage.tracks[i].sequence, out old_start);
|
|
|
|
|
|
2014-04-14 01:31:32 +00:00
|
|
|
if (partition.PartitionStartSector < old_start)
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
|
|
|
|
offsetmap.Remove(discimage.tracks[i].sequence);
|
|
|
|
|
offsetmap.Add(discimage.tracks[i].sequence, partition.PartitionStartSector);
|
2013-12-16 01:04:17 +00:00
|
|
|
}
|
|
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
|
|
|
|
|
partitions.Add(partition);
|
2015-10-05 19:45:07 +01:00
|
|
|
partition = new CommonTypes.Partition();
|
2013-12-16 01:04:17 +00:00
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
|
|
|
|
|
index_zero |= discimage.tracks[i].indexes.TryGetValue(0, out index_zero_offset);
|
|
|
|
|
|
|
|
|
|
if (!discimage.tracks[i].indexes.TryGetValue(1, out index_one_offset))
|
|
|
|
|
throw new ImageNotSupportedException(String.Format("Track {0} lacks index 01", discimage.tracks[i].sequence));
|
|
|
|
|
|
|
|
|
|
if (index_zero && index_one_offset > index_zero_offset)
|
|
|
|
|
{
|
|
|
|
|
partition.PartitionDescription = String.Format("Track {0} index 00.", discimage.tracks[i].sequence);
|
|
|
|
|
partition.PartitionName = discimage.tracks[i].title;
|
|
|
|
|
partition.PartitionStartSector = sector_offset;
|
|
|
|
|
partition.PartitionLength = (index_one_offset - index_zero_offset) * discimage.tracks[i].bps;
|
|
|
|
|
partition.PartitionSectors = index_one_offset - index_zero_offset;
|
|
|
|
|
partition.PartitionSequence = partitionSequence;
|
|
|
|
|
partition.PartitionStart = byte_offset;
|
|
|
|
|
partition.PartitionType = discimage.tracks[i].tracktype;
|
|
|
|
|
|
|
|
|
|
sector_offset += partition.PartitionSectors;
|
|
|
|
|
byte_offset += partition.PartitionLength;
|
2015-11-09 19:42:00 +00:00
|
|
|
index0_len = partition.PartitionSectors;
|
2014-04-14 01:14:20 +00:00
|
|
|
partitionSequence++;
|
|
|
|
|
|
2014-04-14 01:31:32 +00:00
|
|
|
if (!offsetmap.ContainsKey(discimage.tracks[i].sequence))
|
2014-04-14 01:14:20 +00:00
|
|
|
offsetmap.Add(discimage.tracks[i].sequence, partition.PartitionStartSector);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ulong old_start;
|
|
|
|
|
offsetmap.TryGetValue(discimage.tracks[i].sequence, out old_start);
|
|
|
|
|
|
2014-04-14 01:31:32 +00:00
|
|
|
if (partition.PartitionStartSector < old_start)
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
|
|
|
|
offsetmap.Remove(discimage.tracks[i].sequence);
|
|
|
|
|
offsetmap.Add(discimage.tracks[i].sequence, partition.PartitionStartSector);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
partitions.Add(partition);
|
2015-10-05 19:45:07 +01:00
|
|
|
partition = new CommonTypes.Partition();
|
2014-04-14 01:14:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Index 01
|
|
|
|
|
partition.PartitionDescription = String.Format("Track {0}.", discimage.tracks[i].sequence);
|
|
|
|
|
partition.PartitionName = discimage.tracks[i].title;
|
|
|
|
|
partition.PartitionStartSector = sector_offset;
|
2015-11-09 19:42:00 +00:00
|
|
|
partition.PartitionLength = (discimage.tracks[i].sectors - index0_len) * discimage.tracks[i].bps;
|
|
|
|
|
partition.PartitionSectors = (discimage.tracks[i].sectors - index0_len);
|
2014-04-14 01:14:20 +00:00
|
|
|
partition.PartitionSequence = partitionSequence;
|
|
|
|
|
partition.PartitionStart = byte_offset;
|
|
|
|
|
partition.PartitionType = discimage.tracks[i].tracktype;
|
|
|
|
|
|
|
|
|
|
sector_offset += partition.PartitionSectors;
|
|
|
|
|
byte_offset += partition.PartitionLength;
|
|
|
|
|
partitionSequence++;
|
|
|
|
|
|
2014-04-14 01:31:32 +00:00
|
|
|
if (!offsetmap.ContainsKey(discimage.tracks[i].sequence))
|
2014-04-14 01:14:20 +00:00
|
|
|
offsetmap.Add(discimage.tracks[i].sequence, partition.PartitionStartSector);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ulong old_start;
|
|
|
|
|
offsetmap.TryGetValue(discimage.tracks[i].sequence, out old_start);
|
|
|
|
|
|
2014-04-14 01:31:32 +00:00
|
|
|
if (partition.PartitionStartSector < old_start)
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
|
|
|
|
offsetmap.Remove(discimage.tracks[i].sequence);
|
|
|
|
|
offsetmap.Add(discimage.tracks[i].sequence, partition.PartitionStartSector);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
partitions.Add(partition);
|
2015-10-05 19:45:07 +01:00
|
|
|
partition = new CommonTypes.Partition();
|
2013-12-16 01:04:17 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-14 01:31:32 +00:00
|
|
|
// Print offset map
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "printing partition map");
|
|
|
|
|
foreach (CommonTypes.Partition partition in partitions)
|
2014-04-14 01:31:32 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "Partition sequence: {0}", partition.PartitionSequence);
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tPartition name: {0}", partition.PartitionName);
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tPartition description: {0}", partition.PartitionDescription);
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tPartition type: {0}", partition.PartitionType);
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tPartition starting sector: {0}", partition.PartitionStartSector);
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tPartition sectors: {0}", partition.PartitionSectors);
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tPartition starting offset: {0}", partition.PartitionStart);
|
|
|
|
|
DicConsole.DebugWriteLine("CDRWin plugin", "\tPartition size in bytes: {0}", partition.PartitionLength);
|
2014-04-14 01:31:32 +00:00
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
|
2014-08-24 17:46:29 +01:00
|
|
|
foreach (CDRWinTrack track in discimage.tracks)
|
2014-08-28 19:29:18 +01:00
|
|
|
ImageInfo.imageSize += track.bps * track.sectors;
|
2014-08-24 17:46:29 +01:00
|
|
|
foreach (CDRWinTrack track in discimage.tracks)
|
2014-08-28 19:29:18 +01:00
|
|
|
ImageInfo.sectors += track.sectors;
|
2014-08-24 17:46:29 +01:00
|
|
|
|
2016-01-16 03:54:55 +00:00
|
|
|
if (discimage.disktype == MediaType.CDG || discimage.disktype == MediaType.CDEG || discimage.disktype == MediaType.CDMIDI)
|
2014-08-28 19:29:18 +01:00
|
|
|
ImageInfo.sectorSize = 2448; // CD+G subchannels ARE user data, as CD+G are useless without them
|
2016-01-16 03:54:55 +00:00
|
|
|
else if (discimage.disktype != MediaType.CDROMXA && discimage.disktype != MediaType.CDDA && discimage.disktype != MediaType.CDI && discimage.disktype != MediaType.CDPLUS)
|
2014-08-28 19:29:18 +01:00
|
|
|
ImageInfo.sectorSize = 2048; // Only data tracks
|
2014-08-24 17:46:29 +01:00
|
|
|
else
|
2014-08-28 19:29:18 +01:00
|
|
|
ImageInfo.sectorSize = 2352; // All others
|
2014-08-24 17:46:29 +01:00
|
|
|
|
|
|
|
|
if (discimage.mcn != null)
|
2016-01-16 03:54:55 +00:00
|
|
|
ImageInfo.readableMediaTags.Add(MediaTagType.CD_MCN);
|
2014-08-24 17:46:29 +01:00
|
|
|
if (discimage.cdtextfile != null)
|
2016-01-16 03:54:55 +00:00
|
|
|
ImageInfo.readableMediaTags.Add(MediaTagType.CD_TEXT);
|
2014-08-24 17:46:29 +01:00
|
|
|
|
|
|
|
|
// Detect ISOBuster extensions
|
|
|
|
|
if (discimage.disktypestr != null || discimage.comment.ToLower().Contains("isobuster") || discimage.sessions.Count > 1)
|
2014-08-28 19:29:18 +01:00
|
|
|
ImageInfo.imageApplication = "ISOBuster";
|
2014-08-24 17:46:29 +01:00
|
|
|
else
|
2014-08-28 19:29:18 +01:00
|
|
|
ImageInfo.imageApplication = "CDRWin";
|
2014-08-24 17:46:29 +01:00
|
|
|
|
|
|
|
|
FileInfo fi = new FileInfo(discimage.tracks[0].trackfile.datafile);
|
|
|
|
|
|
2014-08-28 19:29:18 +01:00
|
|
|
ImageInfo.imageCreationTime = fi.CreationTimeUtc;
|
|
|
|
|
ImageInfo.imageLastModificationTime = fi.LastWriteTimeUtc;
|
2014-08-24 17:46:29 +01:00
|
|
|
|
2014-08-28 19:29:18 +01:00
|
|
|
ImageInfo.imageComments = discimage.comment;
|
2016-01-16 03:54:55 +00:00
|
|
|
ImageInfo.mediaSerialNumber = discimage.mcn;
|
|
|
|
|
ImageInfo.mediaBarcode = discimage.barcode;
|
|
|
|
|
ImageInfo.mediaType = discimage.disktype;
|
2014-08-24 17:46:29 +01:00
|
|
|
|
2015-12-23 23:46:31 +00:00
|
|
|
ImageInfo.readableSectorTags.Add(SectorTagType.CDTrackFlags);
|
|
|
|
|
|
2014-08-25 05:00:25 +01:00
|
|
|
foreach (CDRWinTrack track in discimage.tracks)
|
2014-08-24 17:46:29 +01:00
|
|
|
{
|
2014-08-25 05:00:25 +01:00
|
|
|
switch (track.tracktype)
|
2014-08-24 17:46:29 +01:00
|
|
|
{
|
|
|
|
|
case CDRWinTrackTypeAudio:
|
|
|
|
|
{
|
2014-08-28 19:29:18 +01:00
|
|
|
if (!ImageInfo.readableSectorTags.Contains(SectorTagType.CDTrackISRC))
|
|
|
|
|
ImageInfo.readableSectorTags.Add(SectorTagType.CDTrackISRC);
|
2014-08-24 17:46:29 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CDRWinTrackTypeCDG:
|
|
|
|
|
{
|
2014-08-28 19:29:18 +01:00
|
|
|
if (!ImageInfo.readableSectorTags.Contains(SectorTagType.CDTrackISRC))
|
|
|
|
|
ImageInfo.readableSectorTags.Add(SectorTagType.CDTrackISRC);
|
|
|
|
|
if (!ImageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSubchannel))
|
|
|
|
|
ImageInfo.readableSectorTags.Add(SectorTagType.CDSectorSubchannel);
|
2014-08-24 17:46:29 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CDRWinTrackTypeMode2Formless:
|
|
|
|
|
case CDRWinTrackTypeCDI:
|
|
|
|
|
{
|
2014-08-28 19:29:18 +01:00
|
|
|
if (!ImageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSubHeader))
|
|
|
|
|
ImageInfo.readableSectorTags.Add(SectorTagType.CDSectorSubHeader);
|
|
|
|
|
if (!ImageInfo.readableSectorTags.Contains(SectorTagType.CDSectorEDC))
|
|
|
|
|
ImageInfo.readableSectorTags.Add(SectorTagType.CDSectorEDC);
|
2014-08-24 17:46:29 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CDRWinTrackTypeMode2Raw:
|
|
|
|
|
case CDRWinTrackTypeCDIRaw:
|
|
|
|
|
{
|
2014-08-28 19:29:18 +01:00
|
|
|
if (!ImageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSync))
|
|
|
|
|
ImageInfo.readableSectorTags.Add(SectorTagType.CDSectorSync);
|
|
|
|
|
if (!ImageInfo.readableSectorTags.Contains(SectorTagType.CDSectorHeader))
|
|
|
|
|
ImageInfo.readableSectorTags.Add(SectorTagType.CDSectorHeader);
|
|
|
|
|
if (!ImageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSubHeader))
|
|
|
|
|
ImageInfo.readableSectorTags.Add(SectorTagType.CDSectorSubHeader);
|
|
|
|
|
if (!ImageInfo.readableSectorTags.Contains(SectorTagType.CDSectorEDC))
|
|
|
|
|
ImageInfo.readableSectorTags.Add(SectorTagType.CDSectorEDC);
|
2014-08-24 17:46:29 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CDRWinTrackTypeMode1Raw:
|
|
|
|
|
{
|
2014-08-28 19:29:18 +01:00
|
|
|
if (!ImageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSync))
|
|
|
|
|
ImageInfo.readableSectorTags.Add(SectorTagType.CDSectorSync);
|
|
|
|
|
if (!ImageInfo.readableSectorTags.Contains(SectorTagType.CDSectorHeader))
|
|
|
|
|
ImageInfo.readableSectorTags.Add(SectorTagType.CDSectorHeader);
|
|
|
|
|
if (!ImageInfo.readableSectorTags.Contains(SectorTagType.CDSectorSubHeader))
|
|
|
|
|
ImageInfo.readableSectorTags.Add(SectorTagType.CDSectorSubHeader);
|
|
|
|
|
if (!ImageInfo.readableSectorTags.Contains(SectorTagType.CDSectorECC))
|
|
|
|
|
ImageInfo.readableSectorTags.Add(SectorTagType.CDSectorECC);
|
|
|
|
|
if (!ImageInfo.readableSectorTags.Contains(SectorTagType.CDSectorECC_P))
|
|
|
|
|
ImageInfo.readableSectorTags.Add(SectorTagType.CDSectorECC_P);
|
|
|
|
|
if (!ImageInfo.readableSectorTags.Contains(SectorTagType.CDSectorECC_Q))
|
|
|
|
|
ImageInfo.readableSectorTags.Add(SectorTagType.CDSectorECC_Q);
|
|
|
|
|
if (!ImageInfo.readableSectorTags.Contains(SectorTagType.CDSectorEDC))
|
|
|
|
|
ImageInfo.readableSectorTags.Add(SectorTagType.CDSectorEDC);
|
2014-08-24 17:46:29 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-05 17:21:47 +00:00
|
|
|
ImageInfo.xmlMediaType = XmlMediaType.OpticalDisc;
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
return true;
|
2013-12-16 01:04:17 +00:00
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
catch (Exception ex)
|
2013-12-16 01:04:17 +00:00
|
|
|
{
|
2015-10-18 22:04:03 +01:00
|
|
|
DicConsole.ErrorWriteLine("Exception trying to identify image file {0}", imagePath);
|
|
|
|
|
DicConsole.ErrorWriteLine("Exception: {0}", ex.Message);
|
|
|
|
|
DicConsole.ErrorWriteLine("Stack trace: {0}", ex.StackTrace);
|
2013-12-16 01:04:17 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
2013-12-16 01:04:17 +00:00
|
|
|
|
2013-12-14 23:02:04 +00:00
|
|
|
public override bool ImageHasPartitions()
|
|
|
|
|
{
|
2014-08-28 19:29:18 +01:00
|
|
|
return ImageInfo.imageHasPartitions;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override UInt64 GetImageSize()
|
|
|
|
|
{
|
2014-08-28 19:29:18 +01:00
|
|
|
return ImageInfo.imageSize;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
|
2013-12-14 23:02:04 +00:00
|
|
|
public override UInt64 GetSectors()
|
|
|
|
|
{
|
2014-08-28 19:29:18 +01:00
|
|
|
return ImageInfo.sectors;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
|
2013-12-14 23:02:04 +00:00
|
|
|
public override UInt32 GetSectorSize()
|
|
|
|
|
{
|
2014-08-28 19:29:18 +01:00
|
|
|
return ImageInfo.sectorSize;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
2016-01-16 03:54:55 +00:00
|
|
|
public override byte[] ReadDiskTag(MediaTagType tag)
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
switch (tag)
|
|
|
|
|
{
|
2016-01-16 03:54:55 +00:00
|
|
|
case MediaTagType.CD_MCN:
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
|
|
|
|
if (discimage.mcn != null)
|
|
|
|
|
{
|
|
|
|
|
return Encoding.ASCII.GetBytes(discimage.mcn);
|
|
|
|
|
}
|
|
|
|
|
throw new FeatureNotPresentImageException("Image does not contain MCN information.");
|
|
|
|
|
}
|
2016-01-16 03:54:55 +00:00
|
|
|
case MediaTagType.CD_TEXT:
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
|
|
|
|
if (discimage.cdtextfile != null)
|
|
|
|
|
// TODO: Check that binary text file exists, open it, read it, send it to caller.
|
|
|
|
|
throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
|
|
|
|
|
throw new FeatureNotPresentImageException("Image does not contain CD-TEXT information.");
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
throw new FeatureSupportedButNotImplementedImageException("Feature not supported by image format");
|
|
|
|
|
}
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
public override byte[] ReadSector(UInt64 sectorAddress)
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
return ReadSectors(sectorAddress, 1);
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
public override byte[] ReadSectorTag(UInt64 sectorAddress, SectorTagType tag)
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
return ReadSectorsTag(sectorAddress, 1, tag);
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
public override byte[] ReadSector(UInt64 sectorAddress, UInt32 track)
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
return ReadSectors(sectorAddress, 1, track);
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
public override byte[] ReadSectorTag(UInt64 sectorAddress, UInt32 track, SectorTagType tag)
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
return ReadSectorsTag(sectorAddress, 1, track, tag);
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
public override byte[] ReadSectors(UInt64 sectorAddress, UInt32 length)
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
foreach (KeyValuePair<uint, ulong> kvp in offsetmap)
|
|
|
|
|
{
|
|
|
|
|
if (sectorAddress >= kvp.Value)
|
|
|
|
|
{
|
|
|
|
|
foreach (CDRWinTrack cdrwin_track in discimage.tracks)
|
|
|
|
|
{
|
|
|
|
|
if (cdrwin_track.sequence == kvp.Key)
|
|
|
|
|
{
|
2014-04-14 01:31:32 +00:00
|
|
|
if ((sectorAddress - kvp.Value) < cdrwin_track.sectors)
|
2014-04-14 01:14:20 +00:00
|
|
|
return ReadSectors((sectorAddress - kvp.Value), length, kvp.Key);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
throw new ArgumentOutOfRangeException("sectorAddress", "Sector address not found");
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
public override byte[] ReadSectorsTag(UInt64 sectorAddress, UInt32 length, SectorTagType tag)
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
foreach (KeyValuePair<uint, ulong> kvp in offsetmap)
|
|
|
|
|
{
|
|
|
|
|
if (sectorAddress >= kvp.Value)
|
|
|
|
|
{
|
|
|
|
|
foreach (CDRWinTrack cdrwin_track in discimage.tracks)
|
|
|
|
|
{
|
|
|
|
|
if (cdrwin_track.sequence == kvp.Key)
|
|
|
|
|
{
|
2014-04-14 01:31:32 +00:00
|
|
|
if ((sectorAddress - kvp.Value) < cdrwin_track.sectors)
|
2014-04-14 01:14:20 +00:00
|
|
|
return ReadSectorsTag((sectorAddress - kvp.Value), length, kvp.Key, tag);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
throw new ArgumentOutOfRangeException("sectorAddress", "Sector address not found");
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
public override byte[] ReadSectors(UInt64 sectorAddress, UInt32 length, UInt32 track)
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
CDRWinTrack _track = new CDRWinTrack();
|
|
|
|
|
|
|
|
|
|
_track.sequence = 0;
|
|
|
|
|
|
|
|
|
|
foreach (CDRWinTrack cdrwin_track in discimage.tracks)
|
|
|
|
|
{
|
|
|
|
|
if (cdrwin_track.sequence == track)
|
|
|
|
|
{
|
|
|
|
|
_track = cdrwin_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 (_track.tracktype)
|
|
|
|
|
{
|
|
|
|
|
case CDRWinTrackTypeMode1:
|
|
|
|
|
case CDRWinTrackTypeMode2Form1:
|
|
|
|
|
{
|
|
|
|
|
sector_offset = 0;
|
|
|
|
|
sector_size = 2048;
|
|
|
|
|
sector_skip = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CDRWinTrackTypeMode2Form2:
|
|
|
|
|
{
|
|
|
|
|
sector_offset = 0;
|
|
|
|
|
sector_size = 2324;
|
|
|
|
|
sector_skip = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CDRWinTrackTypeMode2Formless:
|
|
|
|
|
case CDRWinTrackTypeCDI:
|
|
|
|
|
{
|
|
|
|
|
sector_offset = 0;
|
|
|
|
|
sector_size = 2336;
|
|
|
|
|
sector_skip = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CDRWinTrackTypeAudio:
|
|
|
|
|
{
|
|
|
|
|
sector_offset = 0;
|
|
|
|
|
sector_size = 2352;
|
|
|
|
|
sector_skip = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CDRWinTrackTypeMode1Raw:
|
|
|
|
|
{
|
|
|
|
|
sector_offset = 16;
|
|
|
|
|
sector_size = 2048;
|
|
|
|
|
sector_skip = 288;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CDRWinTrackTypeMode2Raw:
|
|
|
|
|
{
|
|
|
|
|
sector_offset = 16;
|
|
|
|
|
sector_size = 2336;
|
|
|
|
|
sector_skip = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CDRWinTrackTypeCDIRaw:
|
|
|
|
|
{
|
|
|
|
|
sector_offset = 16;
|
|
|
|
|
sector_size = 2336;
|
|
|
|
|
sector_skip = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CDRWinTrackTypeCDG:
|
|
|
|
|
{
|
|
|
|
|
sector_offset = 0;
|
|
|
|
|
sector_size = 2352;
|
|
|
|
|
sector_skip = 96;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
throw new FeatureSupportedButNotImplementedImageException("Unsupported track type");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
byte[] buffer = new byte[sector_size * length];
|
|
|
|
|
|
2014-04-14 02:29:13 +00:00
|
|
|
imageStream = new FileStream(_track.trackfile.datafile, FileMode.Open, FileAccess.Read);
|
|
|
|
|
using (BinaryReader br = new BinaryReader(imageStream))
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
2014-04-14 02:29:13 +00:00
|
|
|
br.BaseStream.Seek((long)_track.trackfile.offset + (long)(sectorAddress * (sector_offset + sector_size + sector_skip)), SeekOrigin.Begin);
|
|
|
|
|
if (sector_offset == 0 && sector_skip == 0)
|
|
|
|
|
buffer = br.ReadBytes((int)(sector_size * length));
|
|
|
|
|
else
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
2014-04-14 02:29:13 +00:00
|
|
|
for (int i = 0; i < length; 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, i * sector_size, sector_size);
|
|
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-14 02:29:13 +00:00
|
|
|
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
return buffer;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
public override byte[] ReadSectorsTag(UInt64 sectorAddress, UInt32 length, UInt32 track, SectorTagType tag)
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
CDRWinTrack _track = new CDRWinTrack();
|
|
|
|
|
|
|
|
|
|
_track.sequence = 0;
|
|
|
|
|
|
|
|
|
|
foreach (CDRWinTrack cdrwin_track in discimage.tracks)
|
|
|
|
|
{
|
|
|
|
|
if (cdrwin_track.sequence == track)
|
|
|
|
|
{
|
|
|
|
|
_track = cdrwin_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.CDSectorSubchannel:
|
|
|
|
|
case SectorTagType.CDSectorSubHeader:
|
|
|
|
|
case SectorTagType.CDSectorSync:
|
|
|
|
|
break;
|
|
|
|
|
case SectorTagType.CDTrackFlags:
|
|
|
|
|
{
|
|
|
|
|
byte[] flags = new byte[1];
|
|
|
|
|
|
|
|
|
|
if (_track.tracktype != CDRWinTrackTypeAudio && _track.tracktype != CDRWinTrackTypeCDG)
|
|
|
|
|
flags[0] += 0x40;
|
|
|
|
|
|
|
|
|
|
if (_track.flag_dcp)
|
|
|
|
|
flags[0] += 0x20;
|
|
|
|
|
|
|
|
|
|
if (_track.flag_pre)
|
|
|
|
|
flags[0] += 0x10;
|
|
|
|
|
|
2015-12-23 23:46:31 +00:00
|
|
|
if (_track.flag_4ch)
|
|
|
|
|
flags[0] += 0x80;
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
return flags;
|
|
|
|
|
}
|
|
|
|
|
case SectorTagType.CDTrackISRC:
|
|
|
|
|
return Encoding.UTF8.GetBytes(_track.isrc);
|
|
|
|
|
case SectorTagType.CDTrackText:
|
|
|
|
|
throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
|
|
|
|
|
default:
|
|
|
|
|
throw new ArgumentException("Unsupported tag requested", "tag");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (_track.tracktype)
|
|
|
|
|
{
|
|
|
|
|
case CDRWinTrackTypeMode1:
|
|
|
|
|
case CDRWinTrackTypeMode2Form1:
|
|
|
|
|
case CDRWinTrackTypeMode2Form2:
|
|
|
|
|
throw new ArgumentException("No tags in image for requested track", "tag");
|
|
|
|
|
case CDRWinTrackTypeMode2Formless:
|
|
|
|
|
case CDRWinTrackTypeCDI:
|
|
|
|
|
{
|
|
|
|
|
switch (tag)
|
|
|
|
|
{
|
|
|
|
|
case SectorTagType.CDSectorSync:
|
|
|
|
|
case SectorTagType.CDSectorHeader:
|
|
|
|
|
case SectorTagType.CDSectorSubchannel:
|
|
|
|
|
case SectorTagType.CDSectorECC:
|
|
|
|
|
case SectorTagType.CDSectorECC_P:
|
|
|
|
|
case SectorTagType.CDSectorECC_Q:
|
|
|
|
|
throw new ArgumentException("Unsupported tag requested for this track", "tag");
|
|
|
|
|
case SectorTagType.CDSectorSubHeader:
|
|
|
|
|
{
|
|
|
|
|
sector_offset = 0;
|
|
|
|
|
sector_size = 8;
|
|
|
|
|
sector_skip = 2328;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SectorTagType.CDSectorEDC:
|
|
|
|
|
{
|
|
|
|
|
sector_offset = 2332;
|
|
|
|
|
sector_size = 4;
|
|
|
|
|
sector_skip = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
throw new ArgumentException("Unsupported tag requested", "tag");
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CDRWinTrackTypeAudio:
|
|
|
|
|
throw new ArgumentException("There are no tags on audio tracks", "tag");
|
|
|
|
|
case CDRWinTrackTypeMode1Raw:
|
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
case CDRWinTrackTypeMode2Raw: // Requires reading sector
|
|
|
|
|
case CDRWinTrackTypeCDIRaw:
|
|
|
|
|
throw new FeatureSupportedButNotImplementedImageException("Feature not yet implemented");
|
|
|
|
|
case CDRWinTrackTypeCDG:
|
|
|
|
|
{
|
2014-04-14 01:31:32 +00:00
|
|
|
if (tag != SectorTagType.CDSectorSubchannel)
|
2014-04-14 01:14:20 +00:00
|
|
|
throw new ArgumentException("Unsupported tag requested for this track", "tag");
|
|
|
|
|
|
|
|
|
|
sector_offset = 2352;
|
|
|
|
|
sector_size = 96;
|
|
|
|
|
sector_skip = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
throw new FeatureSupportedButNotImplementedImageException("Unsupported track type");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
byte[] buffer = new byte[sector_size * length];
|
|
|
|
|
|
2014-04-14 02:29:13 +00:00
|
|
|
imageStream = new FileStream(_track.trackfile.datafile, FileMode.Open, FileAccess.Read);
|
|
|
|
|
using (BinaryReader br = new BinaryReader(imageStream))
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
2014-04-14 02:29:13 +00:00
|
|
|
br.BaseStream.Seek((long)_track.trackfile.offset + (long)(sectorAddress * (sector_offset + sector_size + sector_skip)), SeekOrigin.Begin);
|
|
|
|
|
if (sector_offset == 0 && sector_skip == 0)
|
|
|
|
|
buffer = br.ReadBytes((int)(sector_size * length));
|
|
|
|
|
else
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
2014-04-14 02:29:13 +00:00
|
|
|
for (int i = 0; i < length; 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, i * sector_size, sector_size);
|
|
|
|
|
}
|
2014-04-14 01:14:20 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-14 02:29:13 +00:00
|
|
|
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
return buffer;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
public override byte[] ReadSectorLong(UInt64 sectorAddress)
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
return ReadSectorsLong(sectorAddress, 1);
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
public override byte[] ReadSectorLong(UInt64 sectorAddress, UInt32 track)
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
return ReadSectorsLong(sectorAddress, 1, track);
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
public override byte[] ReadSectorsLong(UInt64 sectorAddress, UInt32 length)
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
foreach (KeyValuePair<uint, ulong> kvp in offsetmap)
|
|
|
|
|
{
|
|
|
|
|
if (sectorAddress >= kvp.Value)
|
|
|
|
|
{
|
|
|
|
|
foreach (CDRWinTrack cdrwin_track in discimage.tracks)
|
|
|
|
|
{
|
|
|
|
|
if (cdrwin_track.sequence == kvp.Key)
|
|
|
|
|
{
|
2014-04-14 01:31:32 +00:00
|
|
|
if ((sectorAddress - kvp.Value) < cdrwin_track.sectors)
|
2014-04-14 01:14:20 +00:00
|
|
|
return ReadSectorsLong((sectorAddress - kvp.Value), length, kvp.Key);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
throw new ArgumentOutOfRangeException("sectorAddress", "Sector address not found");
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
public override byte[] ReadSectorsLong(UInt64 sectorAddress, UInt32 length, UInt32 track)
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
CDRWinTrack _track = new CDRWinTrack();
|
|
|
|
|
|
|
|
|
|
_track.sequence = 0;
|
|
|
|
|
|
|
|
|
|
foreach (CDRWinTrack cdrwin_track in discimage.tracks)
|
|
|
|
|
{
|
|
|
|
|
if (cdrwin_track.sequence == track)
|
|
|
|
|
{
|
|
|
|
|
_track = cdrwin_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 (_track.tracktype)
|
|
|
|
|
{
|
|
|
|
|
case CDRWinTrackTypeMode1:
|
|
|
|
|
case CDRWinTrackTypeMode2Form1:
|
|
|
|
|
{
|
|
|
|
|
sector_offset = 0;
|
|
|
|
|
sector_size = 2048;
|
|
|
|
|
sector_skip = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CDRWinTrackTypeMode2Form2:
|
|
|
|
|
{
|
|
|
|
|
sector_offset = 0;
|
|
|
|
|
sector_size = 2324;
|
|
|
|
|
sector_skip = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CDRWinTrackTypeMode2Formless:
|
|
|
|
|
case CDRWinTrackTypeCDI:
|
|
|
|
|
{
|
|
|
|
|
sector_offset = 0;
|
|
|
|
|
sector_size = 2336;
|
|
|
|
|
sector_skip = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CDRWinTrackTypeMode1Raw:
|
|
|
|
|
case CDRWinTrackTypeMode2Raw:
|
|
|
|
|
case CDRWinTrackTypeCDIRaw:
|
|
|
|
|
case CDRWinTrackTypeAudio:
|
|
|
|
|
{
|
|
|
|
|
sector_offset = 0;
|
|
|
|
|
sector_size = 2352;
|
|
|
|
|
sector_skip = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CDRWinTrackTypeCDG:
|
|
|
|
|
{
|
|
|
|
|
sector_offset = 0;
|
2015-12-06 05:09:31 +00:00
|
|
|
sector_size = 2352;
|
|
|
|
|
sector_skip = 96;
|
2014-04-14 01:14:20 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
throw new FeatureSupportedButNotImplementedImageException("Unsupported track type");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
byte[] buffer = new byte[sector_size * length];
|
|
|
|
|
|
2014-04-14 02:29:13 +00:00
|
|
|
imageStream = new FileStream(_track.trackfile.datafile, FileMode.Open, FileAccess.Read);
|
|
|
|
|
BinaryReader br = new BinaryReader(imageStream);
|
2014-04-14 01:14:20 +00:00
|
|
|
|
2014-04-14 01:31:32 +00:00
|
|
|
br.BaseStream.Seek((long)_track.trackfile.offset + (long)(sectorAddress * (sector_offset + sector_size + sector_skip)), SeekOrigin.Begin);
|
2014-04-14 01:14:20 +00:00
|
|
|
|
|
|
|
|
if (sector_offset == 0 && sector_skip == 0)
|
|
|
|
|
buffer = br.ReadBytes((int)(sector_size * length));
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < length; i++)
|
|
|
|
|
{
|
2014-04-14 02:29:13 +00:00
|
|
|
byte[] sector;
|
2014-04-14 01:14:20 +00:00
|
|
|
br.BaseStream.Seek(sector_offset, SeekOrigin.Current);
|
|
|
|
|
sector = br.ReadBytes((int)sector_size);
|
|
|
|
|
br.BaseStream.Seek(sector_skip, SeekOrigin.Current);
|
|
|
|
|
|
2014-04-14 02:29:13 +00:00
|
|
|
Array.Copy(sector, 0, buffer, i * sector_size, sector_size);
|
2014-04-14 01:14:20 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return buffer;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string GetImageFormat()
|
|
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
return "CDRWin CUESheet";
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string GetImageVersion()
|
|
|
|
|
{
|
2014-08-28 19:29:18 +01:00
|
|
|
return ImageInfo.imageVersion;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string GetImageApplication()
|
|
|
|
|
{
|
2014-08-28 19:29:18 +01:00
|
|
|
return ImageInfo.imageApplication;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string GetImageApplicationVersion()
|
|
|
|
|
{
|
2014-08-28 19:29:18 +01:00
|
|
|
return ImageInfo.imageApplicationVersion;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override DateTime GetImageCreationTime()
|
|
|
|
|
{
|
2014-08-28 19:29:18 +01:00
|
|
|
return ImageInfo.imageCreationTime;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override DateTime GetImageLastModificationTime()
|
|
|
|
|
{
|
2014-08-28 19:29:18 +01:00
|
|
|
return ImageInfo.imageLastModificationTime;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string GetImageComments()
|
|
|
|
|
{
|
2014-08-28 19:29:18 +01:00
|
|
|
return ImageInfo.imageComments;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
2016-01-16 03:54:55 +00:00
|
|
|
public override string GetMediaSerialNumber()
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
2016-01-16 03:54:55 +00:00
|
|
|
return ImageInfo.mediaSerialNumber;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
2016-01-16 03:54:55 +00:00
|
|
|
public override string GetMediaBarcode()
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
2016-01-16 03:54:55 +00:00
|
|
|
return ImageInfo.mediaBarcode;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
2016-01-16 03:54:55 +00:00
|
|
|
public override MediaType GetMediaType()
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
2016-01-16 03:54:55 +00:00
|
|
|
return ImageInfo.mediaType;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
2015-10-05 19:45:07 +01:00
|
|
|
public override List<CommonTypes.Partition> GetPartitions()
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
return partitions;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override List<Track> GetTracks()
|
|
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
List<Track> tracks = new List<Track>();
|
|
|
|
|
|
2014-08-25 05:00:25 +01:00
|
|
|
UInt64 previousStartSector = 0;
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
foreach (CDRWinTrack cdr_track in discimage.tracks)
|
|
|
|
|
{
|
|
|
|
|
Track _track = new Track();
|
|
|
|
|
|
|
|
|
|
_track.Indexes = cdr_track.indexes;
|
|
|
|
|
_track.TrackDescription = cdr_track.title;
|
|
|
|
|
if (!cdr_track.indexes.TryGetValue(0, out _track.TrackStartSector))
|
|
|
|
|
cdr_track.indexes.TryGetValue(1, out _track.TrackStartSector);
|
2015-11-09 22:17:45 +00:00
|
|
|
_track.TrackStartSector = previousStartSector;
|
2014-04-14 01:14:20 +00:00
|
|
|
_track.TrackEndSector = _track.TrackStartSector + cdr_track.sectors - 1;
|
|
|
|
|
_track.TrackPregap = cdr_track.pregap;
|
|
|
|
|
_track.TrackSession = cdr_track.session;
|
|
|
|
|
_track.TrackSequence = cdr_track.sequence;
|
|
|
|
|
_track.TrackType = CDRWinTrackTypeToTrackType(cdr_track.tracktype);
|
2015-12-06 05:09:31 +00:00
|
|
|
_track.TrackFile = cdr_track.trackfile.datafile;
|
|
|
|
|
_track.TrackFileOffset = cdr_track.trackfile.offset;
|
|
|
|
|
_track.TrackFileType = cdr_track.trackfile.filetype;
|
|
|
|
|
_track.TrackRawBytesPerSector = cdr_track.bps;
|
|
|
|
|
_track.TrackBytesPerSector = CDRWinTrackTypeToCookedBytesPerSector(cdr_track.tracktype);
|
|
|
|
|
if (cdr_track.bps == 2448)
|
|
|
|
|
{
|
|
|
|
|
_track.TrackSubchannelFile = cdr_track.trackfile.datafile;
|
|
|
|
|
_track.TrackSubchannelOffset = cdr_track.trackfile.offset;
|
|
|
|
|
_track.TrackSubchannelType = TrackSubchannelType.RawInterleaved;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
_track.TrackSubchannelType = TrackSubchannelType.None;
|
2014-04-14 01:14:20 +00:00
|
|
|
|
|
|
|
|
tracks.Add(_track);
|
2014-08-25 05:00:25 +01:00
|
|
|
previousStartSector = _track.TrackEndSector + 1;
|
2014-04-14 01:14:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return tracks;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
public override List<Track> GetSessionTracks(Session session)
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
if (discimage.sessions.Contains(session))
|
|
|
|
|
{
|
|
|
|
|
return GetSessionTracks(session.SessionSequence);
|
|
|
|
|
}
|
2014-04-14 02:29:13 +00:00
|
|
|
throw new ImageNotSupportedException("Session does not exist in disc image");
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
public override List<Track> GetSessionTracks(UInt16 session)
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
List<Track> tracks = new List<Track>();
|
|
|
|
|
|
|
|
|
|
foreach (CDRWinTrack cdr_track in discimage.tracks)
|
|
|
|
|
{
|
|
|
|
|
if (cdr_track.session == session)
|
|
|
|
|
{
|
|
|
|
|
Track _track = new Track();
|
|
|
|
|
|
|
|
|
|
_track.Indexes = cdr_track.indexes;
|
|
|
|
|
_track.TrackDescription = cdr_track.title;
|
|
|
|
|
if (!cdr_track.indexes.TryGetValue(0, out _track.TrackStartSector))
|
|
|
|
|
cdr_track.indexes.TryGetValue(1, out _track.TrackStartSector);
|
|
|
|
|
_track.TrackEndSector = _track.TrackStartSector + cdr_track.sectors - 1;
|
|
|
|
|
_track.TrackPregap = cdr_track.pregap;
|
|
|
|
|
_track.TrackSession = cdr_track.session;
|
|
|
|
|
_track.TrackSequence = cdr_track.sequence;
|
|
|
|
|
_track.TrackType = CDRWinTrackTypeToTrackType(cdr_track.tracktype);
|
2015-12-06 05:09:31 +00:00
|
|
|
_track.TrackFile = cdr_track.trackfile.datafile;
|
|
|
|
|
_track.TrackFileOffset = cdr_track.trackfile.offset;
|
|
|
|
|
_track.TrackFileType = cdr_track.trackfile.filetype;
|
|
|
|
|
_track.TrackRawBytesPerSector = cdr_track.bps;
|
|
|
|
|
_track.TrackBytesPerSector = CDRWinTrackTypeToCookedBytesPerSector(cdr_track.tracktype);
|
|
|
|
|
if (cdr_track.bps == 2448)
|
|
|
|
|
{
|
|
|
|
|
_track.TrackSubchannelFile = cdr_track.trackfile.datafile;
|
|
|
|
|
_track.TrackSubchannelOffset = cdr_track.trackfile.offset;
|
|
|
|
|
_track.TrackSubchannelType = TrackSubchannelType.RawInterleaved;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
_track.TrackSubchannelType = TrackSubchannelType.None;
|
2014-04-14 01:14:20 +00:00
|
|
|
|
|
|
|
|
tracks.Add(_track);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return tracks;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override List<Session> GetSessions()
|
|
|
|
|
{
|
2014-04-14 01:14:20 +00:00
|
|
|
return discimage.sessions;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
2014-08-25 05:00:25 +01:00
|
|
|
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<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs)
|
|
|
|
|
{
|
|
|
|
|
byte[] buffer = ReadSectorsLong(sectorAddress, length);
|
|
|
|
|
int bps = (int)(buffer.Length / length);
|
|
|
|
|
byte[] sector = new byte[bps];
|
|
|
|
|
FailingLBAs = new List<UInt64>();
|
|
|
|
|
UnknownLBAs = new List<UInt64>();
|
|
|
|
|
|
|
|
|
|
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<UInt64> FailingLBAs, out List<UInt64> UnknownLBAs)
|
|
|
|
|
{
|
|
|
|
|
byte[] buffer = ReadSectorsLong(sectorAddress, length, track);
|
|
|
|
|
int bps = (int)(buffer.Length / length);
|
|
|
|
|
byte[] sector = new byte[bps];
|
|
|
|
|
FailingLBAs = new List<UInt64>();
|
|
|
|
|
UnknownLBAs = new List<UInt64>();
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-16 03:54:55 +00:00
|
|
|
public override bool? VerifyMediaImage()
|
2014-08-25 05:00:25 +01:00
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Private methods
|
|
|
|
|
|
|
|
|
|
static UInt64 CDRWinMSFToLBA(string MSF)
|
|
|
|
|
{
|
|
|
|
|
string[] MSFElements;
|
|
|
|
|
UInt64 minute, second, frame, sectors;
|
|
|
|
|
|
|
|
|
|
MSFElements = MSF.Split(':');
|
|
|
|
|
minute = UInt64.Parse(MSFElements[0]);
|
|
|
|
|
second = UInt64.Parse(MSFElements[1]);
|
|
|
|
|
frame = UInt64.Parse(MSFElements[2]);
|
|
|
|
|
|
|
|
|
|
sectors = (minute * 60 * 75) + (second * 75) + frame;
|
|
|
|
|
|
|
|
|
|
return sectors;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static UInt16 CDRWinTrackTypeToBytesPerSector(string trackType)
|
|
|
|
|
{
|
|
|
|
|
switch (trackType)
|
|
|
|
|
{
|
|
|
|
|
case CDRWinTrackTypeMode1:
|
|
|
|
|
case CDRWinTrackTypeMode2Form1:
|
|
|
|
|
return 2048;
|
|
|
|
|
case CDRWinTrackTypeMode2Form2:
|
|
|
|
|
return 2324;
|
|
|
|
|
case CDRWinTrackTypeMode2Formless:
|
|
|
|
|
case CDRWinTrackTypeCDI:
|
|
|
|
|
return 2336;
|
|
|
|
|
case CDRWinTrackTypeAudio:
|
|
|
|
|
case CDRWinTrackTypeMode1Raw:
|
|
|
|
|
case CDRWinTrackTypeMode2Raw:
|
|
|
|
|
case CDRWinTrackTypeCDIRaw:
|
|
|
|
|
return 2352;
|
|
|
|
|
case CDRWinTrackTypeCDG:
|
|
|
|
|
return 2448;
|
|
|
|
|
default:
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-06 05:09:31 +00:00
|
|
|
static UInt16 CDRWinTrackTypeToCookedBytesPerSector(string trackType)
|
|
|
|
|
{
|
|
|
|
|
switch (trackType)
|
|
|
|
|
{
|
|
|
|
|
case CDRWinTrackTypeMode1:
|
|
|
|
|
case CDRWinTrackTypeMode2Form1:
|
|
|
|
|
case CDRWinTrackTypeMode1Raw:
|
|
|
|
|
return 2048;
|
|
|
|
|
case CDRWinTrackTypeMode2Form2:
|
|
|
|
|
return 2324;
|
|
|
|
|
case CDRWinTrackTypeMode2Formless:
|
|
|
|
|
case CDRWinTrackTypeCDI:
|
|
|
|
|
case CDRWinTrackTypeMode2Raw:
|
|
|
|
|
case CDRWinTrackTypeCDIRaw:
|
|
|
|
|
return 2336;
|
|
|
|
|
case CDRWinTrackTypeAudio:
|
|
|
|
|
return 2352;
|
|
|
|
|
case CDRWinTrackTypeCDG:
|
|
|
|
|
return 2448;
|
|
|
|
|
default:
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
static TrackType CDRWinTrackTypeToTrackType(string trackType)
|
|
|
|
|
{
|
|
|
|
|
switch (trackType)
|
|
|
|
|
{
|
|
|
|
|
case CDRWinTrackTypeMode1:
|
|
|
|
|
case CDRWinTrackTypeMode1Raw:
|
|
|
|
|
return TrackType.CDMode1;
|
|
|
|
|
case CDRWinTrackTypeMode2Form1:
|
|
|
|
|
return TrackType.CDMode2Form1;
|
|
|
|
|
case CDRWinTrackTypeMode2Form2:
|
|
|
|
|
return TrackType.CDMode2Form2;
|
|
|
|
|
case CDRWinTrackTypeCDIRaw:
|
|
|
|
|
case CDRWinTrackTypeCDI:
|
|
|
|
|
case CDRWinTrackTypeMode2Raw:
|
|
|
|
|
case CDRWinTrackTypeMode2Formless:
|
|
|
|
|
return TrackType.CDMode2Formless;
|
|
|
|
|
case CDRWinTrackTypeAudio:
|
|
|
|
|
case CDRWinTrackTypeCDG:
|
|
|
|
|
return TrackType.Audio;
|
|
|
|
|
default:
|
|
|
|
|
return TrackType.Data;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-16 03:54:55 +00:00
|
|
|
static MediaType CDRWinIsoBusterDiscTypeToMediaType(string discType)
|
2014-04-14 01:14:20 +00:00
|
|
|
{
|
|
|
|
|
switch (discType)
|
|
|
|
|
{
|
|
|
|
|
case CDRWinDiskTypeCD:
|
2016-01-16 03:54:55 +00:00
|
|
|
return MediaType.CD;
|
2014-04-14 01:14:20 +00:00
|
|
|
case CDRWinDiskTypeCDRW:
|
|
|
|
|
case CDRWinDiskTypeCDMRW:
|
|
|
|
|
case CDRWinDiskTypeCDMRW2:
|
2016-01-16 03:54:55 +00:00
|
|
|
return MediaType.CDRW;
|
2014-04-14 01:14:20 +00:00
|
|
|
case CDRWinDiskTypeDVD:
|
2016-01-16 03:54:55 +00:00
|
|
|
return MediaType.DVDROM;
|
2014-04-14 01:14:20 +00:00
|
|
|
case CDRWinDiskTypeDVDPRW:
|
|
|
|
|
case CDRWinDiskTypeDVDPMRW:
|
|
|
|
|
case CDRWinDiskTypeDVDPMRW2:
|
2016-01-16 03:54:55 +00:00
|
|
|
return MediaType.DVDPRW;
|
2014-04-14 01:14:20 +00:00
|
|
|
case CDRWinDiskTypeDVDPRWDL:
|
|
|
|
|
case CDRWinDiskTypeDVDPMRWDL:
|
|
|
|
|
case CDRWinDiskTypeDVDPMRWDL2:
|
2016-01-16 03:54:55 +00:00
|
|
|
return MediaType.DVDPRWDL;
|
2014-04-14 01:14:20 +00:00
|
|
|
case CDRWinDiskTypeDVDPR:
|
|
|
|
|
case CDRWinDiskTypeDVDPVR:
|
2016-01-16 03:54:55 +00:00
|
|
|
return MediaType.DVDPR;
|
2014-04-14 01:14:20 +00:00
|
|
|
case CDRWinDiskTypeDVDPRDL:
|
2016-01-16 03:54:55 +00:00
|
|
|
return MediaType.DVDPRDL;
|
2014-04-14 01:14:20 +00:00
|
|
|
case CDRWinDiskTypeDVDRAM:
|
2016-01-16 03:54:55 +00:00
|
|
|
return MediaType.DVDRAM;
|
2014-04-14 01:14:20 +00:00
|
|
|
case CDRWinDiskTypeDVDVR:
|
|
|
|
|
case CDRWinDiskTypeDVDR:
|
2016-01-16 03:54:55 +00:00
|
|
|
return MediaType.DVDR;
|
2014-04-14 01:14:20 +00:00
|
|
|
case CDRWinDiskTypeDVDRDL:
|
2016-01-16 03:54:55 +00:00
|
|
|
return MediaType.DVDRDL;
|
2014-04-14 01:14:20 +00:00
|
|
|
case CDRWinDiskTypeDVDRW:
|
|
|
|
|
case CDRWinDiskTypeDVDRWDL:
|
|
|
|
|
case CDRWinDiskTypeDVDRW2:
|
2016-01-16 03:54:55 +00:00
|
|
|
return MediaType.DVDRW;
|
2014-04-14 01:14:20 +00:00
|
|
|
case CDRWinDiskTypeHDDVD:
|
2016-01-16 03:54:55 +00:00
|
|
|
return MediaType.HDDVDROM;
|
2014-04-14 01:14:20 +00:00
|
|
|
case CDRWinDiskTypeHDDVDRAM:
|
2016-01-16 03:54:55 +00:00
|
|
|
return MediaType.HDDVDRAM;
|
2014-04-14 01:14:20 +00:00
|
|
|
case CDRWinDiskTypeHDDVDR:
|
|
|
|
|
case CDRWinDiskTypeHDDVDRDL:
|
2016-01-16 03:54:55 +00:00
|
|
|
return MediaType.HDDVDR;
|
2014-04-14 01:14:20 +00:00
|
|
|
case CDRWinDiskTypeHDDVDRW:
|
|
|
|
|
case CDRWinDiskTypeHDDVDRWDL:
|
2016-01-16 03:54:55 +00:00
|
|
|
return MediaType.HDDVDRW;
|
2014-04-14 01:14:20 +00:00
|
|
|
case CDRWinDiskTypeBD:
|
2016-01-16 03:54:55 +00:00
|
|
|
return MediaType.BDROM;
|
2014-04-14 01:14:20 +00:00
|
|
|
case CDRWinDiskTypeBDR:
|
|
|
|
|
case CDRWinDiskTypeBDRDL:
|
2016-01-16 03:54:55 +00:00
|
|
|
return MediaType.BDR;
|
2014-04-14 01:14:20 +00:00
|
|
|
case CDRWinDiskTypeBDRE:
|
|
|
|
|
case CDRWinDiskTypeBDREDL:
|
2016-01-16 03:54:55 +00:00
|
|
|
return MediaType.BDRE;
|
2014-04-14 01:14:20 +00:00
|
|
|
default:
|
2016-01-16 03:54:55 +00:00
|
|
|
return MediaType.Unknown;
|
2014-04-14 01:14:20 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Unsupported features
|
|
|
|
|
|
2016-01-16 03:54:55 +00:00
|
|
|
public override int GetMediaSequence()
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
2016-01-16 03:54:55 +00:00
|
|
|
return ImageInfo.mediaSequence;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override int GetLastDiskSequence()
|
|
|
|
|
{
|
2016-01-16 03:54:55 +00:00
|
|
|
return ImageInfo.lastMediaSequence;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string GetDriveManufacturer()
|
|
|
|
|
{
|
2014-08-28 19:29:18 +01:00
|
|
|
return ImageInfo.driveManufacturer;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string GetDriveModel()
|
|
|
|
|
{
|
2014-08-28 19:29:18 +01:00
|
|
|
return ImageInfo.driveModel;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string GetDriveSerialNumber()
|
|
|
|
|
{
|
2014-08-28 19:29:18 +01:00
|
|
|
return ImageInfo.driveSerialNumber;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
2016-01-16 03:54:55 +00:00
|
|
|
public override string GetMediaPartNumber()
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
2016-01-16 03:54:55 +00:00
|
|
|
return ImageInfo.mediaPartNumber;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
2016-01-16 03:54:55 +00:00
|
|
|
public override string GetMediaManufacturer()
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
2016-01-16 03:54:55 +00:00
|
|
|
return ImageInfo.mediaManufacturer;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
2016-01-16 03:54:55 +00:00
|
|
|
public override string GetMediaModel()
|
2013-12-14 23:02:04 +00:00
|
|
|
{
|
2016-01-16 03:54:55 +00:00
|
|
|
return ImageInfo.mediaModel;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string GetImageName()
|
|
|
|
|
{
|
2014-08-28 19:29:18 +01:00
|
|
|
return ImageInfo.imageName;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string GetImageCreator()
|
|
|
|
|
{
|
2014-08-28 19:29:18 +01:00
|
|
|
return ImageInfo.imageCreator;
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
2014-08-25 05:00:25 +01:00
|
|
|
|
2014-04-14 01:14:20 +00:00
|
|
|
#endregion
|
2013-12-14 23:02:04 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|