mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
For DiscImageChef format, add support for Apple long sectors (with tags).
This commit is contained in:
@@ -115,7 +115,7 @@ namespace DiscImageChef.Decoders
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts this tag to Sony format
|
/// Converts this tag to Sony format
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SonyTag Sony()
|
public SonyTag ToSony()
|
||||||
{
|
{
|
||||||
return new SonyTag
|
return new SonyTag
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ using System.Text;
|
|||||||
using DiscImageChef.Checksums;
|
using DiscImageChef.Checksums;
|
||||||
using DiscImageChef.CommonTypes;
|
using DiscImageChef.CommonTypes;
|
||||||
using DiscImageChef.Console;
|
using DiscImageChef.Console;
|
||||||
|
using DiscImageChef.Decoders;
|
||||||
using DiscImageChef.Filters;
|
using DiscImageChef.Filters;
|
||||||
using SharpCompress.Compressors.LZMA;
|
using SharpCompress.Compressors.LZMA;
|
||||||
|
|
||||||
@@ -345,6 +346,13 @@ namespace DiscImageChef.DiscImages
|
|||||||
if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel))
|
if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel))
|
||||||
imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel);
|
imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel);
|
||||||
break;
|
break;
|
||||||
|
case DataType.AppleProfileTag:
|
||||||
|
case DataType.AppleSonyTag:
|
||||||
|
case DataType.PriamDataTowerTag:
|
||||||
|
sectorSubchannel = data;
|
||||||
|
if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag))
|
||||||
|
imageInfo.ReadableSectorTags.Add(SectorTagType.AppleSectorTag);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
MediaTagType mediaTagType = GetMediaTagTypeForDataType(blockHeader.type);
|
MediaTagType mediaTagType = GetMediaTagTypeForDataType(blockHeader.type);
|
||||||
|
|
||||||
@@ -749,7 +757,14 @@ namespace DiscImageChef.DiscImages
|
|||||||
{
|
{
|
||||||
byte[] sector = ReadSector(tracks[i].TrackStartSector);
|
byte[] sector = ReadSector(tracks[i].TrackStartSector);
|
||||||
tracks[i].TrackBytesPerSector = sector.Length;
|
tracks[i].TrackBytesPerSector = sector.Length;
|
||||||
tracks[i].TrackRawBytesPerSector = sector.Length;
|
tracks[i].TrackRawBytesPerSector =
|
||||||
|
sectorPrefix != null && sectorSuffix != null ? 2352 : sector.Length;
|
||||||
|
|
||||||
|
if(sectorSubchannel == null) continue;
|
||||||
|
|
||||||
|
tracks[i].TrackSubchannelFile = tracks[i].TrackFile;
|
||||||
|
tracks[i].TrackSubchannelFilter = tracks[i].TrackFilter;
|
||||||
|
tracks[i].TrackSubchannelType = TrackSubchannelType.Raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tracks = tracks.ToList();
|
Tracks = tracks.ToList();
|
||||||
@@ -1058,7 +1073,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
default: throw new FeatureSupportedButNotImplementedImageException("Unsupported track type");
|
default: throw new FeatureSupportedButNotImplementedImageException("Unsupported track type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else throw new NotImplementedException();
|
else throw new FeatureNotPresentImageException("Feature not present in image");
|
||||||
|
|
||||||
if(dataSource == null) throw new ArgumentException("Unsupported tag requested", nameof(tag));
|
if(dataSource == null) throw new ArgumentException("Unsupported tag requested", nameof(tag));
|
||||||
|
|
||||||
@@ -1111,35 +1126,50 @@ namespace DiscImageChef.DiscImages
|
|||||||
|
|
||||||
public byte[] ReadSectorLong(ulong sectorAddress)
|
public byte[] ReadSectorLong(ulong sectorAddress)
|
||||||
{
|
{
|
||||||
if(imageInfo.XmlMediaType == XmlMediaType.OpticalDisc)
|
switch(imageInfo.XmlMediaType)
|
||||||
{
|
{
|
||||||
Track trk = Tracks.FirstOrDefault(t => sectorAddress >= t.TrackStartSector &&
|
case XmlMediaType.OpticalDisc:
|
||||||
sectorAddress <= t.TrackEndSector);
|
Track trk = Tracks.FirstOrDefault(t => sectorAddress >= t.TrackStartSector &&
|
||||||
if(trk.TrackSequence == 0)
|
sectorAddress <= t.TrackEndSector);
|
||||||
throw new ArgumentOutOfRangeException(nameof(sectorAddress),
|
if(trk.TrackSequence == 0)
|
||||||
"Can't found track containing requested sector");
|
throw new ArgumentOutOfRangeException(nameof(sectorAddress),
|
||||||
|
"Can't found track containing requested sector");
|
||||||
|
|
||||||
if(sectorSuffix == null || sectorPrefix == null) return ReadSector(sectorAddress);
|
if(sectorSuffix == null || sectorPrefix == null) return ReadSector(sectorAddress);
|
||||||
|
|
||||||
byte[] sector = new byte[2352];
|
byte[] sector = new byte[2352];
|
||||||
byte[] data = ReadSector(sectorAddress);
|
byte[] data = ReadSector(sectorAddress);
|
||||||
|
|
||||||
switch(trk.TrackType)
|
switch(trk.TrackType)
|
||||||
{
|
{
|
||||||
case TrackType.Audio:
|
case TrackType.Audio:
|
||||||
case TrackType.Data: return data;
|
case TrackType.Data: return data;
|
||||||
case TrackType.CdMode1:
|
case TrackType.CdMode1:
|
||||||
Array.Copy(sectorPrefix, (int)sectorAddress * 16, sector, 0, 16);
|
Array.Copy(sectorPrefix, (int)sectorAddress * 16, sector, 0, 16);
|
||||||
Array.Copy(data, 0, sector, 16, 2048);
|
Array.Copy(data, 0, sector, 16, 2048);
|
||||||
Array.Copy(sectorSuffix, (int)sectorAddress * 288, sector, 2064, 288);
|
Array.Copy(sectorSuffix, (int)sectorAddress * 288, sector, 2064, 288);
|
||||||
return sector;
|
return sector;
|
||||||
case TrackType.CdMode2Formless:
|
case TrackType.CdMode2Formless:
|
||||||
case TrackType.CdMode2Form1:
|
case TrackType.CdMode2Form1:
|
||||||
case TrackType.CdMode2Form2:
|
case TrackType.CdMode2Form2:
|
||||||
Array.Copy(sectorPrefix, (int)sectorAddress * 16, sector, 0, 16);
|
Array.Copy(sectorPrefix, (int)sectorAddress * 16, sector, 0, 16);
|
||||||
Array.Copy(data, 0, sector, 16, 2336);
|
Array.Copy(data, 0, sector, 16, 2336);
|
||||||
return sector;
|
return sector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case XmlMediaType.BlockMedia:
|
||||||
|
switch(imageInfo.MediaType)
|
||||||
|
{
|
||||||
|
case MediaType.AppleFileWare:
|
||||||
|
case MediaType.AppleProfile:
|
||||||
|
case MediaType.AppleSonySS:
|
||||||
|
case MediaType.AppleSonyDS:
|
||||||
|
case MediaType.AppleWidget:
|
||||||
|
case MediaType.PriamDataTower: return ReadSectorsLong(sectorAddress, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new FeatureNotPresentImageException("Feature not present in image");
|
throw new FeatureNotPresentImageException("Feature not present in image");
|
||||||
@@ -1159,20 +1189,107 @@ namespace DiscImageChef.DiscImages
|
|||||||
|
|
||||||
public byte[] ReadSectorsLong(ulong sectorAddress, uint length)
|
public byte[] ReadSectorsLong(ulong sectorAddress, uint length)
|
||||||
{
|
{
|
||||||
if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc)
|
byte[] sectors;
|
||||||
throw new FeatureNotPresentImageException("Feature not present in image");
|
byte[] data;
|
||||||
|
|
||||||
Track trk = Tracks.FirstOrDefault(t => sectorAddress >= t.TrackStartSector &&
|
switch(imageInfo.XmlMediaType)
|
||||||
sectorAddress <= t.TrackEndSector);
|
{
|
||||||
if(trk.TrackSequence == 0)
|
case XmlMediaType.OpticalDisc:
|
||||||
throw new ArgumentOutOfRangeException(nameof(sectorAddress),
|
Track trk = Tracks.FirstOrDefault(t => sectorAddress >= t.TrackStartSector &&
|
||||||
"Can't found track containing requested sector");
|
sectorAddress <= t.TrackEndSector);
|
||||||
|
if(trk.TrackSequence == 0)
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(sectorAddress),
|
||||||
|
"Can't found track containing requested sector");
|
||||||
|
|
||||||
if(trk.TrackStartSector + sectorAddress + length > trk.TrackEndSector + 1)
|
if(trk.TrackStartSector + sectorAddress + length > trk.TrackEndSector + 1)
|
||||||
throw new ArgumentOutOfRangeException(nameof(length),
|
throw new ArgumentOutOfRangeException(nameof(length),
|
||||||
$"Requested more sectors ({length + sectorAddress}) than present in track ({trk.TrackEndSector - trk.TrackStartSector + 1}), won't cross tracks");
|
$"Requested more sectors ({length + sectorAddress}) than present in track ({trk.TrackEndSector - trk.TrackStartSector + 1}), won't cross tracks");
|
||||||
|
|
||||||
return ReadSectorsLong(trk.TrackStartSector + sectorAddress, length);
|
switch(trk.TrackType)
|
||||||
|
{
|
||||||
|
case TrackType.Audio:
|
||||||
|
case TrackType.Data: return ReadSectors(sectorAddress, length);
|
||||||
|
case TrackType.CdMode1:
|
||||||
|
if(sectorPrefix == null || sectorSuffix == null) return ReadSectors(sectorAddress, length);
|
||||||
|
|
||||||
|
sectors = new byte[2352 * length];
|
||||||
|
data = ReadSectors(sectorAddress, length);
|
||||||
|
for(uint i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
Array.Copy(sectorPrefix, (int)((sectorAddress + i) * 16), sectors,
|
||||||
|
(int)((sectorAddress + i) * 2352), 16);
|
||||||
|
Array.Copy(data, (int)((sectorAddress + i) * 2048), sectors,
|
||||||
|
(int)((sectorAddress + i) * 2352) + 16, 2048);
|
||||||
|
Array.Copy(sectorSuffix, (int)((sectorAddress + i) * 288), sectors,
|
||||||
|
(int)((sectorAddress + i) * 2352) + 2064, 288);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sectors;
|
||||||
|
case TrackType.CdMode2Formless:
|
||||||
|
case TrackType.CdMode2Form1:
|
||||||
|
case TrackType.CdMode2Form2:
|
||||||
|
if(sectorPrefix == null || sectorSuffix == null) return ReadSectors(sectorAddress, length);
|
||||||
|
|
||||||
|
sectors = new byte[2352 * length];
|
||||||
|
data = ReadSectors(sectorAddress, length);
|
||||||
|
for(uint i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
Array.Copy(sectorPrefix, (int)((sectorAddress + i) * 16), sectors,
|
||||||
|
(int)((sectorAddress + i) * 2352), 16);
|
||||||
|
Array.Copy(data, (int)((sectorAddress + i) * 2336), sectors,
|
||||||
|
(int)((sectorAddress + i) * 2352) + 16, 2336);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sectors;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case XmlMediaType.BlockMedia:
|
||||||
|
switch(imageInfo.MediaType)
|
||||||
|
{
|
||||||
|
case MediaType.AppleFileWare:
|
||||||
|
case MediaType.AppleProfile:
|
||||||
|
case MediaType.AppleSonySS:
|
||||||
|
case MediaType.AppleSonyDS:
|
||||||
|
case MediaType.AppleWidget:
|
||||||
|
case MediaType.PriamDataTower:
|
||||||
|
if(sectorSubchannel == null) return ReadSector(sectorAddress);
|
||||||
|
|
||||||
|
uint tagSize = 0;
|
||||||
|
switch(imageInfo.MediaType)
|
||||||
|
{
|
||||||
|
case MediaType.AppleFileWare:
|
||||||
|
case MediaType.AppleProfile:
|
||||||
|
case MediaType.AppleWidget:
|
||||||
|
tagSize = 20;
|
||||||
|
break;
|
||||||
|
case MediaType.AppleSonySS:
|
||||||
|
case MediaType.AppleSonyDS:
|
||||||
|
tagSize = 12;
|
||||||
|
break;
|
||||||
|
case MediaType.PriamDataTower:
|
||||||
|
tagSize = 24;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint sectorSize = 512 + tagSize;
|
||||||
|
data = ReadSectors(sectorAddress, length);
|
||||||
|
sectors = new byte[(sectorSize + 512) * length];
|
||||||
|
for(uint i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
Array.Copy(sectorSubchannel, (int)((sectorAddress + i) * tagSize), sectors,
|
||||||
|
(int)((sectorAddress + i) * sectorSize + 512), tagSize);
|
||||||
|
Array.Copy(data, (int)((sectorAddress + i) * 512), sectors,
|
||||||
|
(int)((sectorAddress + i) * 512), 512);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sectors;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new FeatureNotPresentImageException("Feature not present in image");
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
|
public byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
|
||||||
@@ -1480,7 +1597,6 @@ namespace DiscImageChef.DiscImages
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Optimize this
|
|
||||||
public bool WriteSectors(byte[] data, ulong sectorAddress, uint length)
|
public bool WriteSectors(byte[] data, ulong sectorAddress, uint length)
|
||||||
{
|
{
|
||||||
if(!IsWriting)
|
if(!IsWriting)
|
||||||
@@ -1518,90 +1634,219 @@ namespace DiscImageChef.DiscImages
|
|||||||
|
|
||||||
byte[] sector;
|
byte[] sector;
|
||||||
|
|
||||||
if(imageInfo.XmlMediaType == XmlMediaType.OpticalDisc)
|
switch(imageInfo.XmlMediaType)
|
||||||
{
|
{
|
||||||
Track track =
|
case XmlMediaType.OpticalDisc:
|
||||||
Tracks.FirstOrDefault(trk => sectorAddress >= trk.TrackStartSector &&
|
Track track =
|
||||||
sectorAddress <= trk.TrackEndSector);
|
Tracks.FirstOrDefault(trk => sectorAddress >= trk.TrackStartSector &&
|
||||||
|
sectorAddress <= trk.TrackEndSector);
|
||||||
|
|
||||||
if(track.TrackSequence == 0)
|
if(track.TrackSequence == 0)
|
||||||
{
|
{
|
||||||
ErrorMessage = $"Can't found track containing {sectorAddress}";
|
ErrorMessage = $"Can't found track containing {sectorAddress}";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data.Length != 2352)
|
if(data.Length != 2352)
|
||||||
{
|
{
|
||||||
ErrorMessage = "Incorrect data size";
|
ErrorMessage = "Incorrect data size";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(track.TrackType)
|
switch(track.TrackType)
|
||||||
{
|
{
|
||||||
case TrackType.Audio:
|
case TrackType.Audio:
|
||||||
case TrackType.Data: return WriteSector(data, sectorAddress);
|
case TrackType.Data: return WriteSector(data, sectorAddress);
|
||||||
case TrackType.CdMode1:
|
case TrackType.CdMode1:
|
||||||
if(sectorPrefix == null) sectorPrefix = new byte[imageInfo.Sectors * 16];
|
if(sectorPrefix == null) sectorPrefix = new byte[imageInfo.Sectors * 16];
|
||||||
if(sectorSuffix == null) sectorSuffix = new byte[imageInfo.Sectors * 288];
|
if(sectorSuffix == null) sectorSuffix = new byte[imageInfo.Sectors * 288];
|
||||||
sector = new byte[2048];
|
sector = new byte[2048];
|
||||||
Array.Copy(data, 0, sectorPrefix, (int)sectorAddress * 16, 16);
|
Array.Copy(data, 0, sectorPrefix, (int)sectorAddress * 16, 16);
|
||||||
Array.Copy(data, 16, sector, 0, 2048);
|
Array.Copy(data, 16, sector, 0, 2048);
|
||||||
Array.Copy(data, 2064, sectorSuffix, (int)sectorAddress * 288, 288);
|
Array.Copy(data, 2064, sectorSuffix, (int)sectorAddress * 288, 288);
|
||||||
return WriteSector(sector, sectorAddress);
|
return WriteSector(sector, sectorAddress);
|
||||||
case TrackType.CdMode2Formless:
|
case TrackType.CdMode2Formless:
|
||||||
case TrackType.CdMode2Form1:
|
case TrackType.CdMode2Form1:
|
||||||
case TrackType.CdMode2Form2:
|
case TrackType.CdMode2Form2:
|
||||||
if(sectorPrefix == null) sectorPrefix = new byte[imageInfo.Sectors * 16];
|
if(sectorPrefix == null) sectorPrefix = new byte[imageInfo.Sectors * 16];
|
||||||
if(sectorSuffix == null) sectorSuffix = new byte[imageInfo.Sectors * 288];
|
if(sectorSuffix == null) sectorSuffix = new byte[imageInfo.Sectors * 288];
|
||||||
sector = new byte[2336];
|
sector = new byte[2336];
|
||||||
Array.Copy(data, 0, sectorPrefix, (int)sectorAddress * 16, 16);
|
Array.Copy(data, 0, sectorPrefix, (int)sectorAddress * 16, 16);
|
||||||
Array.Copy(data, 16, sector, 0, 2336);
|
Array.Copy(data, 16, sector, 0, 2336);
|
||||||
return WriteSector(sector, sectorAddress);
|
return WriteSector(sector, sectorAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case XmlMediaType.BlockMedia:
|
||||||
|
switch(imageInfo.MediaType)
|
||||||
|
{
|
||||||
|
case MediaType.AppleFileWare:
|
||||||
|
case MediaType.AppleProfile:
|
||||||
|
case MediaType.AppleSonyDS:
|
||||||
|
case MediaType.AppleSonySS:
|
||||||
|
case MediaType.AppleWidget:
|
||||||
|
case MediaType.PriamDataTower:
|
||||||
|
byte[] oldTag;
|
||||||
|
byte[] newTag;
|
||||||
|
|
||||||
|
switch(data.Length - 512)
|
||||||
|
{
|
||||||
|
// Sony tag, convert to Profile
|
||||||
|
case 12 when imageInfo.MediaType == MediaType.AppleProfile ||
|
||||||
|
imageInfo.MediaType == MediaType.AppleFileWare:
|
||||||
|
oldTag = new byte[12];
|
||||||
|
Array.Copy(data, 512, oldTag, 0, 12);
|
||||||
|
newTag = LisaTag.DecodeSonyTag(oldTag)?.ToProfile().GetBytes();
|
||||||
|
break;
|
||||||
|
// Sony tag, convert to Priam
|
||||||
|
case 12 when imageInfo.MediaType == MediaType.PriamDataTower:
|
||||||
|
oldTag = new byte[12];
|
||||||
|
Array.Copy(data, 512, oldTag, 0, 12);
|
||||||
|
newTag = LisaTag.DecodeSonyTag(oldTag)?.ToPriam().GetBytes();
|
||||||
|
break;
|
||||||
|
// Sony tag, copy to Sony
|
||||||
|
case 12 when imageInfo.MediaType == MediaType.AppleSonySS ||
|
||||||
|
imageInfo.MediaType == MediaType.AppleSonySS:
|
||||||
|
newTag = new byte[12];
|
||||||
|
Array.Copy(data, 512, newTag, 0, 12);
|
||||||
|
break;
|
||||||
|
// Profile tag, copy to Profile
|
||||||
|
case 20 when imageInfo.MediaType == MediaType.AppleProfile ||
|
||||||
|
imageInfo.MediaType == MediaType.AppleFileWare:
|
||||||
|
newTag = new byte[20];
|
||||||
|
Array.Copy(data, 512, newTag, 0, 20);
|
||||||
|
break;
|
||||||
|
// Profile tag, convert to Priam
|
||||||
|
case 20 when imageInfo.MediaType == MediaType.PriamDataTower:
|
||||||
|
oldTag = new byte[20];
|
||||||
|
Array.Copy(data, 512, oldTag, 0, 20);
|
||||||
|
newTag = LisaTag.DecodeProfileTag(oldTag)?.ToPriam().GetBytes();
|
||||||
|
break;
|
||||||
|
// Profile tag, convert to Sony
|
||||||
|
case 20 when imageInfo.MediaType == MediaType.AppleSonySS ||
|
||||||
|
imageInfo.MediaType == MediaType.AppleSonySS:
|
||||||
|
oldTag = new byte[20];
|
||||||
|
Array.Copy(data, 512, oldTag, 0, 20);
|
||||||
|
newTag = LisaTag.DecodeProfileTag(oldTag)?.ToSony().GetBytes();
|
||||||
|
break;
|
||||||
|
// Priam tag, convert to Profile
|
||||||
|
case 24 when imageInfo.MediaType == MediaType.AppleProfile ||
|
||||||
|
imageInfo.MediaType == MediaType.AppleFileWare:
|
||||||
|
oldTag = new byte[24];
|
||||||
|
Array.Copy(data, 512, oldTag, 0, 24);
|
||||||
|
newTag = LisaTag.DecodePriamTag(oldTag)?.ToProfile().GetBytes();
|
||||||
|
break;
|
||||||
|
// Priam tag, copy to Priam
|
||||||
|
case 12 when imageInfo.MediaType == MediaType.PriamDataTower:
|
||||||
|
newTag = new byte[24];
|
||||||
|
Array.Copy(data, 512, newTag, 0, 24);
|
||||||
|
break;
|
||||||
|
// Priam tag, convert to Sony
|
||||||
|
case 24 when imageInfo.MediaType == MediaType.AppleSonySS ||
|
||||||
|
imageInfo.MediaType == MediaType.AppleSonySS:
|
||||||
|
oldTag = new byte[24];
|
||||||
|
Array.Copy(data, 512, oldTag, 0, 24);
|
||||||
|
newTag = LisaTag.DecodePriamTag(oldTag)?.ToSony().GetBytes();
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
newTag = null;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ErrorMessage = "Incorrect data size";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sector = new byte[512];
|
||||||
|
Array.Copy(data, 0, sector, 0, 512);
|
||||||
|
|
||||||
|
if(newTag == null) return WriteSector(sector, sectorAddress);
|
||||||
|
|
||||||
|
if(sectorSubchannel == null)
|
||||||
|
sectorSubchannel = new byte[newTag.Length * (int)imageInfo.Sectors];
|
||||||
|
Array.Copy(newTag, 0, sectorSubchannel, newTag.Length * (int)sectorAddress, newTag.Length);
|
||||||
|
|
||||||
|
return WriteSector(sector, sectorAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Implement
|
ErrorMessage = "Unknown long sector type, cannot write.";
|
||||||
ErrorMessage = "Unknown sector tag type, cannot write.";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool WriteSectorsLong(byte[] data, ulong sectorAddress, uint length)
|
public bool WriteSectorsLong(byte[] data, ulong sectorAddress, uint length)
|
||||||
{
|
{
|
||||||
if(imageInfo.XmlMediaType == XmlMediaType.OpticalDisc)
|
byte[] sector;
|
||||||
|
switch(imageInfo.XmlMediaType)
|
||||||
{
|
{
|
||||||
Track track =
|
case XmlMediaType.OpticalDisc:
|
||||||
Tracks.FirstOrDefault(trk => sectorAddress >= trk.TrackStartSector &&
|
Track track =
|
||||||
sectorAddress <= trk.TrackEndSector);
|
Tracks.FirstOrDefault(trk => sectorAddress >= trk.TrackStartSector &&
|
||||||
|
sectorAddress <= trk.TrackEndSector);
|
||||||
|
|
||||||
if(track.TrackSequence == 0)
|
if(track.TrackSequence == 0)
|
||||||
{
|
{
|
||||||
ErrorMessage = $"Can't found track containing {sectorAddress}";
|
ErrorMessage = $"Can't found track containing {sectorAddress}";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data.Length % 2352 != 0)
|
if(data.Length % 2352 != 0)
|
||||||
{
|
{
|
||||||
ErrorMessage = "Incorrect data size";
|
ErrorMessage = "Incorrect data size";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(track.TrackStartSector + sectorAddress + length > track.TrackEndSector + 1)
|
if(track.TrackStartSector + sectorAddress + length > track.TrackEndSector + 1)
|
||||||
throw new ArgumentOutOfRangeException(nameof(length),
|
throw new ArgumentOutOfRangeException(nameof(length),
|
||||||
$"Requested more sectors ({length + sectorAddress}) than present in track ({track.TrackEndSector - track.TrackStartSector + 1}), won't cross tracks");
|
$"Requested more sectors ({length + sectorAddress}) than present in track ({track.TrackEndSector - track.TrackStartSector + 1}), won't cross tracks");
|
||||||
|
|
||||||
byte[] sector = new byte[2352];
|
sector = new byte[2352];
|
||||||
for(uint i = 0; i < length; i++)
|
for(uint i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
Array.Copy(data, 2352 * i, sector, 0, 2352);
|
Array.Copy(data, 2352 * i, sector, 0, 2352);
|
||||||
if(!WriteSectorLong(sector, sectorAddress + i)) return false;
|
if(!WriteSectorLong(sector, sectorAddress + i)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorMessage = "";
|
ErrorMessage = "";
|
||||||
return true;
|
return true;
|
||||||
|
case XmlMediaType.BlockMedia:
|
||||||
|
switch(imageInfo.MediaType)
|
||||||
|
{
|
||||||
|
case MediaType.AppleFileWare:
|
||||||
|
case MediaType.AppleProfile:
|
||||||
|
case MediaType.AppleSonyDS:
|
||||||
|
case MediaType.AppleSonySS:
|
||||||
|
case MediaType.AppleWidget:
|
||||||
|
case MediaType.PriamDataTower:
|
||||||
|
int sectorSize = 0;
|
||||||
|
if(data.Length % 524 == 0) sectorSize = 524;
|
||||||
|
else if(data.Length % 532 == 0)
|
||||||
|
sectorSize = 532;
|
||||||
|
else if(data.Length % 536 == 0)
|
||||||
|
sectorSize = 536;
|
||||||
|
|
||||||
|
if(sectorSize == 0)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Incorrect data size";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sector = new byte[sectorSize];
|
||||||
|
for(uint i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
Array.Copy(data, sectorSize * i, sector, 0, sectorSize);
|
||||||
|
if(!WriteSectorLong(sector, sectorAddress + i)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorMessage = "";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Implement
|
ErrorMessage = "Unknown long sector type, cannot write.";
|
||||||
ErrorMessage = "Unknown sector tag type, cannot write.";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2011,6 +2256,79 @@ namespace DiscImageChef.DiscImages
|
|||||||
imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length);
|
imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(imageInfo.XmlMediaType == XmlMediaType.BlockMedia)
|
||||||
|
if(sectorSubchannel != null &&
|
||||||
|
(imageInfo.MediaType == MediaType.AppleFileWare ||
|
||||||
|
imageInfo.MediaType == MediaType.AppleSonySS ||
|
||||||
|
imageInfo.MediaType == MediaType.AppleSonyDS ||
|
||||||
|
imageInfo.MediaType == MediaType.AppleProfile ||
|
||||||
|
imageInfo.MediaType == MediaType.AppleWidget ||
|
||||||
|
imageInfo.MediaType == MediaType.PriamDataTower))
|
||||||
|
{
|
||||||
|
DataType tagType = DataType.NoData;
|
||||||
|
|
||||||
|
switch(imageInfo.MediaType)
|
||||||
|
{
|
||||||
|
case MediaType.AppleSonySS:
|
||||||
|
case MediaType.AppleSonyDS:
|
||||||
|
tagType = DataType.AppleSonyTag;
|
||||||
|
break;
|
||||||
|
case MediaType.AppleFileWare:
|
||||||
|
case MediaType.AppleProfile:
|
||||||
|
case MediaType.AppleWidget:
|
||||||
|
tagType = DataType.AppleProfileTag;
|
||||||
|
break;
|
||||||
|
case MediaType.PriamDataTower:
|
||||||
|
tagType = DataType.PriamDataTowerTag;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
idxEntry = new IndexEntry
|
||||||
|
{
|
||||||
|
blockType = BlockType.DataBlock,
|
||||||
|
dataType = tagType,
|
||||||
|
offset = (ulong)imageStream.Position
|
||||||
|
};
|
||||||
|
|
||||||
|
DicConsole.DebugWriteLine("DiscImageChef format plugin",
|
||||||
|
"Writing apple sector tag block to position {0}", idxEntry.offset);
|
||||||
|
|
||||||
|
Crc64Context.Data(sectorSubchannel, out byte[] blockCrc);
|
||||||
|
|
||||||
|
BlockHeader subchannelBlock = new BlockHeader
|
||||||
|
{
|
||||||
|
identifier = BlockType.DataBlock,
|
||||||
|
type = tagType,
|
||||||
|
length = (uint)sectorSubchannel.Length,
|
||||||
|
crc64 = BitConverter.ToUInt64(blockCrc, 0)
|
||||||
|
};
|
||||||
|
|
||||||
|
blockStream = new MemoryStream();
|
||||||
|
compressedBlockStream = new LzmaStream(new LzmaEncoderProperties(), false, blockStream);
|
||||||
|
compressedBlockStream.Write(sectorSubchannel, 0, sectorSubchannel.Length);
|
||||||
|
byte[] lzmaProperties = compressedBlockStream.Properties;
|
||||||
|
compressedBlockStream.Close();
|
||||||
|
|
||||||
|
Crc64Context.Data(blockStream.ToArray(), out blockCrc);
|
||||||
|
subchannelBlock.cmpLength = (uint)blockStream.Length + LZMA_PROPERTIES_LENGTH;
|
||||||
|
subchannelBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0);
|
||||||
|
subchannelBlock.compression = CompressionType.Lzma;
|
||||||
|
|
||||||
|
compressedBlockStream = null;
|
||||||
|
|
||||||
|
structurePointer = Marshal.AllocHGlobal(Marshal.SizeOf(subchannelBlock));
|
||||||
|
structureBytes = new byte[Marshal.SizeOf(subchannelBlock)];
|
||||||
|
Marshal.StructureToPtr(subchannelBlock, structurePointer, true);
|
||||||
|
Marshal.Copy(structurePointer, structureBytes, 0, structureBytes.Length);
|
||||||
|
Marshal.FreeHGlobal(structurePointer);
|
||||||
|
imageStream.Write(structureBytes, 0, structureBytes.Length);
|
||||||
|
if(subchannelBlock.compression == CompressionType.Lzma)
|
||||||
|
imageStream.Write(lzmaProperties, 0, lzmaProperties.Length);
|
||||||
|
imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length);
|
||||||
|
|
||||||
|
index.Add(idxEntry);
|
||||||
|
blockStream = null;
|
||||||
|
}
|
||||||
|
|
||||||
MetadataBlock metadataBlock = new MetadataBlock();
|
MetadataBlock metadataBlock = new MetadataBlock();
|
||||||
blockStream = new MemoryStream();
|
blockStream = new MemoryStream();
|
||||||
@@ -2331,7 +2649,9 @@ namespace DiscImageChef.DiscImages
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
default: throw new NotImplementedException();
|
default:
|
||||||
|
ErrorMessage = $"Don't know how to write sector tag type {tag}";
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2374,7 +2694,9 @@ namespace DiscImageChef.DiscImages
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
default: throw new NotImplementedException();
|
default:
|
||||||
|
ErrorMessage = $"Don't know how to write sector tag type {tag}";
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2729,7 +3051,10 @@ namespace DiscImageChef.DiscImages
|
|||||||
XboxPfi = 68,
|
XboxPfi = 68,
|
||||||
CdSectorPrefix = 69,
|
CdSectorPrefix = 69,
|
||||||
CdSectorSuffix = 70,
|
CdSectorSuffix = 70,
|
||||||
CdSectorSubchannel = 71
|
CdSectorSubchannel = 71,
|
||||||
|
AppleProfileTag = 72,
|
||||||
|
AppleSonyTag = 73,
|
||||||
|
PriamDataTowerTag = 74
|
||||||
}
|
}
|
||||||
|
|
||||||
enum BlockType : uint
|
enum BlockType : uint
|
||||||
|
|||||||
Reference in New Issue
Block a user