mirror of
https://github.com/aaru-dps/Aaru.git
synced 2026-04-05 21:44:17 +00:00
[WinOnCD] Implement missing methods.
This commit is contained in:
@@ -96,9 +96,11 @@ public sealed partial class WinOnCD
|
||||
}
|
||||
|
||||
// Step 3: Process track blocks and build tracks, sessions, and partitions
|
||||
Tracks = [];
|
||||
Sessions = [];
|
||||
Partitions = [];
|
||||
Tracks = [];
|
||||
Sessions = [];
|
||||
Partitions = [];
|
||||
_trackFlags = new Dictionary<uint, byte>();
|
||||
_trackIsrcs = new Dictionary<uint, string>();
|
||||
|
||||
var lastSession = 0;
|
||||
var lastPoint = 0;
|
||||
@@ -308,6 +310,14 @@ public sealed partial class WinOnCD
|
||||
Type = trackType.Humanize()
|
||||
};
|
||||
|
||||
// Store C2D flags for this track
|
||||
_trackFlags[trackSequence] = (byte)entry.flags;
|
||||
|
||||
// Store ISRC if present
|
||||
string isrc = Encoding.ASCII.GetString(entry.isrc).TrimEnd('\0');
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(isrc)) _trackIsrcs[trackSequence] = isrc;
|
||||
|
||||
Tracks.Add(track);
|
||||
Partitions.Add(partition);
|
||||
}
|
||||
@@ -333,7 +343,26 @@ public sealed partial class WinOnCD
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(description)) _imageInfo.Comments = description;
|
||||
|
||||
if(header.has_upc_ean != 0) _imageInfo.MediaBarcode = Encoding.ASCII.GetString(header.upc_ean).TrimEnd('\0');
|
||||
if(header.has_upc_ean != 0)
|
||||
{
|
||||
_mcn = Encoding.ASCII.GetString(header.upc_ean).TrimEnd('\0');
|
||||
_imageInfo.MediaBarcode = _mcn;
|
||||
_imageInfo.ReadableMediaTags.Add(MediaTagType.CD_MCN);
|
||||
}
|
||||
|
||||
// Read CD-Text if present
|
||||
if(header.size_cdtext > 0)
|
||||
{
|
||||
long cdTextOffset = header.offset_tracks + header.num_track_blocks * Marshal.SizeOf<C2dTrackBlock>();
|
||||
|
||||
stream.Seek(cdTextOffset, SeekOrigin.Begin);
|
||||
_cdtext = new byte[header.size_cdtext];
|
||||
stream.EnsureRead(_cdtext, 0, (int)header.size_cdtext);
|
||||
_imageInfo.ReadableMediaTags.Add(MediaTagType.CD_TEXT);
|
||||
}
|
||||
|
||||
if(_trackIsrcs.Count > 0 && !_imageInfo.ReadableSectorTags.Contains(SectorTagType.CdTrackIsrc))
|
||||
_imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackIsrc);
|
||||
|
||||
// Determine media type based on tracks
|
||||
var hasData = false;
|
||||
|
||||
542
Aaru.Images/WinOnCD/Read.cs
Normal file
542
Aaru.Images/WinOnCD/Read.cs
Normal file
@@ -0,0 +1,542 @@
|
||||
// /***************************************************************************
|
||||
// Aaru Data Preservation Suite
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// Filename : Read.cs
|
||||
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||
//
|
||||
// Component : Disc image plugins.
|
||||
//
|
||||
// --[ Description ] ----------------------------------------------------------
|
||||
//
|
||||
// Reads WinOnCD disc images.
|
||||
//
|
||||
// --[ License ] --------------------------------------------------------------
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as
|
||||
// published by the Free Software Foundation; either version 2.1 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright © 2011-2026 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using Aaru.CommonTypes.Structs;
|
||||
using Aaru.Helpers;
|
||||
using Session = Aaru.CommonTypes.Structs.Session;
|
||||
|
||||
namespace Aaru.Images;
|
||||
|
||||
public sealed partial class WinOnCD
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ReadSector(ulong sectorAddress, uint track, out byte[] buffer, out SectorStatus sectorStatus)
|
||||
{
|
||||
buffer = null;
|
||||
sectorStatus = SectorStatus.NotDumped;
|
||||
|
||||
Track trk = Tracks.FirstOrDefault(t => t.Sequence == track);
|
||||
|
||||
if(trk is null) return ErrorNumber.SectorNotFound;
|
||||
|
||||
if(sectorAddress < trk.StartSector || sectorAddress > trk.EndSector) return ErrorNumber.OutOfRange;
|
||||
|
||||
ulong offsetInTrack = sectorAddress - trk.StartSector;
|
||||
int stride = trk.RawBytesPerSector + (trk.SubchannelType != TrackSubchannelType.None ? 96 : 0);
|
||||
var fileOffset = (long)(trk.FileOffset + offsetInTrack * (ulong)stride);
|
||||
|
||||
if(trk.RawBytesPerSector == trk.BytesPerSector)
|
||||
{
|
||||
buffer = new byte[trk.BytesPerSector];
|
||||
_imageStream.Seek(fileOffset, SeekOrigin.Begin);
|
||||
_imageStream.EnsureRead(buffer, 0, trk.BytesPerSector);
|
||||
}
|
||||
else
|
||||
{
|
||||
var rawSector = new byte[trk.RawBytesPerSector];
|
||||
_imageStream.Seek(fileOffset, SeekOrigin.Begin);
|
||||
_imageStream.EnsureRead(rawSector, 0, trk.RawBytesPerSector);
|
||||
|
||||
buffer = new byte[trk.BytesPerSector];
|
||||
|
||||
switch(trk.Type)
|
||||
{
|
||||
case TrackType.CdMode1 when trk.RawBytesPerSector == 2352:
|
||||
Array.Copy(rawSector, 16, buffer, 0, trk.BytesPerSector);
|
||||
|
||||
break;
|
||||
case TrackType.CdMode2Formless when trk.RawBytesPerSector == 2352:
|
||||
Array.Copy(rawSector, 16, buffer, 0, trk.BytesPerSector);
|
||||
|
||||
break;
|
||||
default:
|
||||
Array.Copy(rawSector, 0, buffer, 0, trk.BytesPerSector);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sectorStatus = SectorStatus.Dumped;
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ReadSectors(ulong sectorAddress, uint length, uint track, out byte[] buffer,
|
||||
out SectorStatus[] sectorStatus)
|
||||
{
|
||||
buffer = null;
|
||||
sectorStatus = null;
|
||||
|
||||
Track trk = Tracks.FirstOrDefault(t => t.Sequence == track);
|
||||
|
||||
if(trk is null) return ErrorNumber.SectorNotFound;
|
||||
|
||||
if(sectorAddress + length - 1 > trk.EndSector) return ErrorNumber.OutOfRange;
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
sectorStatus = new SectorStatus[length];
|
||||
|
||||
for(uint i = 0; i < length; i++)
|
||||
{
|
||||
ErrorNumber errno = ReadSector(sectorAddress + i, track, out byte[] sectorData, out SectorStatus status);
|
||||
|
||||
if(errno != ErrorNumber.NoError) return errno;
|
||||
|
||||
ms.Write(sectorData, 0, sectorData.Length);
|
||||
sectorStatus[i] = status;
|
||||
}
|
||||
|
||||
buffer = ms.ToArray();
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ReadSector(ulong sectorAddress, bool negative, out byte[] buffer, out SectorStatus sectorStatus)
|
||||
{
|
||||
buffer = null;
|
||||
sectorStatus = SectorStatus.NotDumped;
|
||||
|
||||
if(negative) return ErrorNumber.NotSupported;
|
||||
|
||||
Track trk = Tracks.FirstOrDefault(t => sectorAddress >= t.StartSector && sectorAddress <= t.EndSector);
|
||||
|
||||
if(trk is null) return ErrorNumber.SectorNotFound;
|
||||
|
||||
return ReadSector(sectorAddress, trk.Sequence, out buffer, out sectorStatus);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ReadSectors(ulong sectorAddress, bool negative, uint length, out byte[] buffer,
|
||||
out SectorStatus[] sectorStatus)
|
||||
{
|
||||
buffer = null;
|
||||
sectorStatus = null;
|
||||
|
||||
if(negative) return ErrorNumber.NotSupported;
|
||||
|
||||
Track trk = Tracks.FirstOrDefault(t => sectorAddress >= t.StartSector && sectorAddress <= t.EndSector);
|
||||
|
||||
if(trk is null) return ErrorNumber.SectorNotFound;
|
||||
|
||||
return ReadSectors(sectorAddress, length, trk.Sequence, out buffer, out sectorStatus);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ReadSectorLong(ulong sectorAddress, uint track, out byte[] buffer, out SectorStatus sectorStatus)
|
||||
{
|
||||
buffer = null;
|
||||
sectorStatus = SectorStatus.NotDumped;
|
||||
|
||||
Track trk = Tracks.FirstOrDefault(t => t.Sequence == track);
|
||||
|
||||
if(trk is null) return ErrorNumber.SectorNotFound;
|
||||
|
||||
if(sectorAddress < trk.StartSector || sectorAddress > trk.EndSector) return ErrorNumber.OutOfRange;
|
||||
|
||||
ulong offsetInTrack = sectorAddress - trk.StartSector;
|
||||
int stride = trk.RawBytesPerSector + (trk.SubchannelType != TrackSubchannelType.None ? 96 : 0);
|
||||
var fileOffset = (long)(trk.FileOffset + offsetInTrack * (ulong)stride);
|
||||
|
||||
switch(trk.Type)
|
||||
{
|
||||
case TrackType.Audio:
|
||||
{
|
||||
buffer = new byte[2352];
|
||||
_imageStream.Seek(fileOffset, SeekOrigin.Begin);
|
||||
_imageStream.EnsureRead(buffer, 0, 2352);
|
||||
|
||||
break;
|
||||
}
|
||||
case TrackType.CdMode1:
|
||||
{
|
||||
if(trk.RawBytesPerSector >= 2352)
|
||||
{
|
||||
buffer = new byte[2352];
|
||||
_imageStream.Seek(fileOffset, SeekOrigin.Begin);
|
||||
_imageStream.EnsureRead(buffer, 0, 2352);
|
||||
}
|
||||
else
|
||||
{
|
||||
var userData = new byte[trk.RawBytesPerSector];
|
||||
_imageStream.Seek(fileOffset, SeekOrigin.Begin);
|
||||
_imageStream.EnsureRead(userData, 0, trk.RawBytesPerSector);
|
||||
|
||||
buffer = new byte[2352];
|
||||
Array.Copy(userData, 0, buffer, 16, trk.RawBytesPerSector);
|
||||
_sectorBuilder.ReconstructPrefix(ref buffer, TrackType.CdMode1, (long)sectorAddress);
|
||||
_sectorBuilder.ReconstructEcc(ref buffer, TrackType.CdMode1);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case TrackType.CdMode2Form1:
|
||||
{
|
||||
var userData = new byte[trk.RawBytesPerSector];
|
||||
_imageStream.Seek(fileOffset, SeekOrigin.Begin);
|
||||
_imageStream.EnsureRead(userData, 0, trk.RawBytesPerSector);
|
||||
|
||||
buffer = new byte[2352];
|
||||
Array.Copy(userData, 0, buffer, 24, trk.RawBytesPerSector);
|
||||
_sectorBuilder.ReconstructPrefix(ref buffer, TrackType.CdMode2Form1, (long)sectorAddress);
|
||||
_sectorBuilder.ReconstructEcc(ref buffer, TrackType.CdMode2Form1);
|
||||
|
||||
break;
|
||||
}
|
||||
case TrackType.CdMode2Form2:
|
||||
{
|
||||
var userData = new byte[trk.RawBytesPerSector];
|
||||
_imageStream.Seek(fileOffset, SeekOrigin.Begin);
|
||||
_imageStream.EnsureRead(userData, 0, trk.RawBytesPerSector);
|
||||
|
||||
buffer = new byte[2352];
|
||||
Array.Copy(userData, 0, buffer, 24, trk.RawBytesPerSector);
|
||||
_sectorBuilder.ReconstructPrefix(ref buffer, TrackType.CdMode2Form2, (long)sectorAddress);
|
||||
_sectorBuilder.ReconstructEcc(ref buffer, TrackType.CdMode2Form2);
|
||||
|
||||
break;
|
||||
}
|
||||
case TrackType.CdMode2Formless:
|
||||
{
|
||||
if(trk.RawBytesPerSector >= 2352)
|
||||
{
|
||||
buffer = new byte[2352];
|
||||
_imageStream.Seek(fileOffset, SeekOrigin.Begin);
|
||||
_imageStream.EnsureRead(buffer, 0, 2352);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = new byte[2352];
|
||||
_sectorBuilder.ReconstructPrefix(ref buffer, TrackType.CdMode2Formless, (long)sectorAddress);
|
||||
|
||||
_imageStream.Seek(fileOffset, SeekOrigin.Begin);
|
||||
_imageStream.EnsureRead(buffer, 16, trk.RawBytesPerSector);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return ErrorNumber.NotSupported;
|
||||
}
|
||||
|
||||
sectorStatus = SectorStatus.Dumped;
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ReadSectorsLong(ulong sectorAddress, uint length, uint track, out byte[] buffer,
|
||||
out SectorStatus[] sectorStatus)
|
||||
{
|
||||
buffer = null;
|
||||
sectorStatus = null;
|
||||
|
||||
Track trk = Tracks.FirstOrDefault(t => t.Sequence == track);
|
||||
|
||||
if(trk is null) return ErrorNumber.SectorNotFound;
|
||||
|
||||
if(sectorAddress + length - 1 > trk.EndSector) return ErrorNumber.OutOfRange;
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
sectorStatus = new SectorStatus[length];
|
||||
|
||||
for(uint i = 0; i < length; i++)
|
||||
{
|
||||
ErrorNumber errno =
|
||||
ReadSectorLong(sectorAddress + i, track, out byte[] sectorData, out SectorStatus status);
|
||||
|
||||
if(errno != ErrorNumber.NoError) return errno;
|
||||
|
||||
ms.Write(sectorData, 0, sectorData.Length);
|
||||
sectorStatus[i] = status;
|
||||
}
|
||||
|
||||
buffer = ms.ToArray();
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ReadSectorLong(ulong sectorAddress, bool negative, out byte[] buffer,
|
||||
out SectorStatus sectorStatus)
|
||||
{
|
||||
buffer = null;
|
||||
sectorStatus = SectorStatus.NotDumped;
|
||||
|
||||
if(negative) return ErrorNumber.NotSupported;
|
||||
|
||||
Track trk = Tracks.FirstOrDefault(t => sectorAddress >= t.StartSector && sectorAddress <= t.EndSector);
|
||||
|
||||
if(trk is null) return ErrorNumber.SectorNotFound;
|
||||
|
||||
return ReadSectorLong(sectorAddress, trk.Sequence, out buffer, out sectorStatus);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ReadSectorsLong(ulong sectorAddress, bool negative, uint length, out byte[] buffer,
|
||||
out SectorStatus[] sectorStatus)
|
||||
{
|
||||
buffer = null;
|
||||
sectorStatus = null;
|
||||
|
||||
if(negative) return ErrorNumber.NotSupported;
|
||||
|
||||
Track trk = Tracks.FirstOrDefault(t => sectorAddress >= t.StartSector && sectorAddress <= t.EndSector);
|
||||
|
||||
if(trk is null) return ErrorNumber.SectorNotFound;
|
||||
|
||||
return ReadSectorsLong(sectorAddress, length, trk.Sequence, out buffer, out sectorStatus);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag, out byte[] buffer)
|
||||
{
|
||||
buffer = null;
|
||||
|
||||
Track trk = Tracks.FirstOrDefault(t => t.Sequence == track);
|
||||
|
||||
if(trk is null) return ErrorNumber.SectorNotFound;
|
||||
|
||||
if(sectorAddress < trk.StartSector || sectorAddress > trk.EndSector) return ErrorNumber.OutOfRange;
|
||||
|
||||
switch(tag)
|
||||
{
|
||||
case SectorTagType.CdTrackFlags:
|
||||
{
|
||||
var cdFlags = (CdFlags)0;
|
||||
|
||||
if(_trackFlags.TryGetValue(trk.Sequence, out byte c2dFlags))
|
||||
{
|
||||
if((c2dFlags & (byte)C2dFlag.PreEmphasis) != 0) cdFlags |= CdFlags.PreEmphasis;
|
||||
if((c2dFlags & (byte)C2dFlag.Copyright) != 0) cdFlags |= CdFlags.CopyPermitted;
|
||||
if((c2dFlags & (byte)C2dFlag.Data) != 0) cdFlags |= CdFlags.DataTrack;
|
||||
}
|
||||
else if(trk.Type != TrackType.Audio) cdFlags = CdFlags.DataTrack;
|
||||
|
||||
buffer = [(byte)cdFlags];
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
case SectorTagType.CdSectorSync:
|
||||
case SectorTagType.CdSectorHeader:
|
||||
case SectorTagType.CdSectorEdc:
|
||||
case SectorTagType.CdSectorEccP:
|
||||
case SectorTagType.CdSectorEccQ:
|
||||
case SectorTagType.CdSectorEcc:
|
||||
if(trk.Type == TrackType.Audio) return ErrorNumber.NotSupported;
|
||||
|
||||
break;
|
||||
case SectorTagType.CdSectorSubHeader:
|
||||
if(trk.Type != TrackType.CdMode2Form1 &&
|
||||
trk.Type != TrackType.CdMode2Form2 &&
|
||||
trk.Type != TrackType.CdMode2Formless)
|
||||
return ErrorNumber.NotSupported;
|
||||
|
||||
break;
|
||||
case SectorTagType.CdTrackIsrc:
|
||||
if(!_trackIsrcs.TryGetValue(trk.Sequence, out string isrc)) return ErrorNumber.NoData;
|
||||
|
||||
buffer = Encoding.ASCII.GetBytes(isrc);
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
case SectorTagType.CdSectorSubchannel:
|
||||
if(trk.SubchannelType == TrackSubchannelType.None) return ErrorNumber.NotSupported;
|
||||
|
||||
{
|
||||
ulong offsetInTrack = sectorAddress - trk.StartSector;
|
||||
int stride = trk.RawBytesPerSector + 96;
|
||||
var fileOffset = (long)(trk.FileOffset + offsetInTrack * (ulong)stride);
|
||||
|
||||
buffer = new byte[96];
|
||||
_imageStream.Seek(fileOffset + trk.RawBytesPerSector, SeekOrigin.Begin);
|
||||
_imageStream.EnsureRead(buffer, 0, 96);
|
||||
}
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
default:
|
||||
return ErrorNumber.NotSupported;
|
||||
}
|
||||
|
||||
ErrorNumber errno = ReadSectorLong(sectorAddress, track, out byte[] fullSector, out SectorStatus _);
|
||||
|
||||
if(errno != ErrorNumber.NoError) return errno;
|
||||
|
||||
switch(tag)
|
||||
{
|
||||
case SectorTagType.CdSectorSync:
|
||||
buffer = new byte[12];
|
||||
Array.Copy(fullSector, 0, buffer, 0, 12);
|
||||
|
||||
break;
|
||||
case SectorTagType.CdSectorHeader:
|
||||
buffer = new byte[4];
|
||||
Array.Copy(fullSector, 12, buffer, 0, 4);
|
||||
|
||||
break;
|
||||
case SectorTagType.CdSectorSubHeader:
|
||||
buffer = new byte[8];
|
||||
Array.Copy(fullSector, 16, buffer, 0, 8);
|
||||
|
||||
break;
|
||||
case SectorTagType.CdSectorEdc:
|
||||
buffer = new byte[4];
|
||||
|
||||
if(trk.Type == TrackType.CdMode1)
|
||||
Array.Copy(fullSector, 2064, buffer, 0, 4);
|
||||
else if(trk.Type == TrackType.CdMode2Form1)
|
||||
Array.Copy(fullSector, 2072, buffer, 0, 4);
|
||||
else
|
||||
return ErrorNumber.NotSupported;
|
||||
|
||||
break;
|
||||
case SectorTagType.CdSectorEccP:
|
||||
if(trk.Type == TrackType.CdMode2Formless) return ErrorNumber.NotSupported;
|
||||
|
||||
buffer = new byte[172];
|
||||
Array.Copy(fullSector, 2076, buffer, 0, 172);
|
||||
|
||||
break;
|
||||
case SectorTagType.CdSectorEccQ:
|
||||
if(trk.Type == TrackType.CdMode2Formless) return ErrorNumber.NotSupported;
|
||||
|
||||
buffer = new byte[104];
|
||||
Array.Copy(fullSector, 2248, buffer, 0, 104);
|
||||
|
||||
break;
|
||||
case SectorTagType.CdSectorEcc:
|
||||
if(trk.Type == TrackType.CdMode2Formless) return ErrorNumber.NotSupported;
|
||||
|
||||
buffer = new byte[276];
|
||||
Array.Copy(fullSector, 2076, buffer, 0, 276);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag,
|
||||
out byte[] buffer)
|
||||
{
|
||||
buffer = null;
|
||||
|
||||
Track trk = Tracks.FirstOrDefault(t => t.Sequence == track);
|
||||
|
||||
if(trk is null) return ErrorNumber.SectorNotFound;
|
||||
|
||||
if(sectorAddress + length - 1 > trk.EndSector) return ErrorNumber.OutOfRange;
|
||||
|
||||
if(tag == SectorTagType.CdTrackFlags) return ReadSectorTag(sectorAddress, track, tag, out buffer);
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
|
||||
for(uint i = 0; i < length; i++)
|
||||
{
|
||||
ErrorNumber errno = ReadSectorTag(sectorAddress + i, track, tag, out byte[] tagData);
|
||||
|
||||
if(errno != ErrorNumber.NoError) return errno;
|
||||
|
||||
ms.Write(tagData, 0, tagData.Length);
|
||||
}
|
||||
|
||||
buffer = ms.ToArray();
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ReadSectorTag(ulong sectorAddress, bool negative, SectorTagType tag, out byte[] buffer)
|
||||
{
|
||||
buffer = null;
|
||||
|
||||
if(negative) return ErrorNumber.NotSupported;
|
||||
|
||||
Track trk = Tracks.FirstOrDefault(t => sectorAddress >= t.StartSector && sectorAddress <= t.EndSector);
|
||||
|
||||
if(trk is null) return ErrorNumber.SectorNotFound;
|
||||
|
||||
return ReadSectorTag(sectorAddress, trk.Sequence, tag, out buffer);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ReadSectorsTag(ulong sectorAddress, bool negative, uint length, SectorTagType tag,
|
||||
out byte[] buffer)
|
||||
{
|
||||
buffer = null;
|
||||
|
||||
if(negative) return ErrorNumber.NotSupported;
|
||||
|
||||
Track trk = Tracks.FirstOrDefault(t => sectorAddress >= t.StartSector && sectorAddress <= t.EndSector);
|
||||
|
||||
if(trk is null) return ErrorNumber.SectorNotFound;
|
||||
|
||||
return ReadSectorsTag(sectorAddress, length, trk.Sequence, tag, out buffer);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ReadMediaTag(MediaTagType tag, out byte[] buffer)
|
||||
{
|
||||
buffer = null;
|
||||
|
||||
switch(tag)
|
||||
{
|
||||
case MediaTagType.CD_MCN:
|
||||
if(_mcn == null) return ErrorNumber.NoData;
|
||||
|
||||
buffer = Encoding.ASCII.GetBytes(_mcn);
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
case MediaTagType.CD_TEXT:
|
||||
if(_cdtext == null) return ErrorNumber.NoData;
|
||||
|
||||
buffer = _cdtext;
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
default:
|
||||
return ErrorNumber.NotSupported;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public List<Track> GetSessionTracks(Session session) => Tracks.Where(t => t.Session == session.Sequence).ToList();
|
||||
|
||||
/// <inheritdoc />
|
||||
public List<Track> GetSessionTracks(ushort session) => Tracks.Where(t => t.Session == session).ToList();
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
// /***************************************************************************
|
||||
// Aaru Data Preservation Suite
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// Filename : Unimplemented.cs
|
||||
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||
//
|
||||
// Component : Disc image plugins.
|
||||
//
|
||||
// --[ Description ] ----------------------------------------------------------
|
||||
//
|
||||
// Manages WinOnCD disc images.
|
||||
//
|
||||
// --[ License ] --------------------------------------------------------------
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as
|
||||
// published by the Free Software Foundation; either version 2.1 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright © 2011-2026 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using Aaru.CommonTypes.Structs;
|
||||
|
||||
namespace Aaru.Images;
|
||||
|
||||
public sealed partial class WinOnCD
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ReadMediaTag(MediaTagType tag, out byte[] buffer) => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber
|
||||
ReadSector(ulong sectorAddress, bool negative, out byte[] buffer, out SectorStatus sectorStatus) =>
|
||||
throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ReadSectorLong(ulong sectorAddress, bool negative, out byte[] buffer,
|
||||
out SectorStatus sectorStatus) => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ReadSectors(ulong sectorAddress, bool negative, uint length, out byte[] buffer,
|
||||
out SectorStatus[] sectorStatus) => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ReadSectorsLong(ulong sectorAddress, bool negative, uint length, out byte[] buffer,
|
||||
out SectorStatus[] sectorStatus) => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ReadSectorsTag(ulong sectorAddress, bool negative, uint length, SectorTagType tag,
|
||||
out byte[] buffer) => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ReadSectorTag(ulong sectorAddress, bool negative, SectorTagType tag, out byte[] buffer) =>
|
||||
throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool? VerifySector(ulong sectorAddress) => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas,
|
||||
out List<ulong> unknownLbas) => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ReadSector(ulong sectorAddress, uint track, out byte[] buffer, out SectorStatus sectorStatus) =>
|
||||
throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag, out byte[] buffer) =>
|
||||
throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ReadSectors(ulong sectorAddress, uint length, uint track, out byte[] buffer,
|
||||
out SectorStatus[] sectorStatus) => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag,
|
||||
out byte[] buffer) => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber
|
||||
ReadSectorLong(ulong sectorAddress, uint track, out byte[] buffer, out SectorStatus sectorStatus) =>
|
||||
throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber ReadSectorsLong(ulong sectorAddress, uint length, uint track, out byte[] buffer,
|
||||
out SectorStatus[] sectorStatus) => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public List<Track> GetSessionTracks(Session session) => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public List<Track> GetSessionTracks(ushort session) => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
|
||||
out List<ulong> unknownLbas) => throw new NotImplementedException();
|
||||
}
|
||||
65
Aaru.Images/WinOnCD/Verify.cs
Normal file
65
Aaru.Images/WinOnCD/Verify.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
// /***************************************************************************
|
||||
// Aaru Data Preservation Suite
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// Filename : Verify.cs
|
||||
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||
//
|
||||
// Component : Disc image plugins.
|
||||
//
|
||||
// --[ Description ] ----------------------------------------------------------
|
||||
//
|
||||
// Verifies WinOnCD disc images.
|
||||
//
|
||||
// --[ License ] --------------------------------------------------------------
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as
|
||||
// published by the Free Software Foundation; either version 2.1 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright © 2011-2026 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Aaru.Images;
|
||||
|
||||
public sealed partial class WinOnCD
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public bool? VerifySector(ulong sectorAddress) => null;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas,
|
||||
out List<ulong> unknownLbas)
|
||||
{
|
||||
failingLbas = [];
|
||||
unknownLbas = [];
|
||||
|
||||
for(ulong i = 0; i < length; i++) unknownLbas.Add(sectorAddress + i);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
|
||||
out List<ulong> unknownLbas)
|
||||
{
|
||||
failingLbas = [];
|
||||
unknownLbas = [];
|
||||
|
||||
for(ulong i = 0; i < length; i++) unknownLbas.Add(sectorAddress + i);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@
|
||||
// Copyright © 2011-2026 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
using Aaru.CommonTypes.Structs;
|
||||
@@ -40,10 +41,14 @@ namespace Aaru.Images;
|
||||
public sealed partial class WinOnCD : IOpticalMediaImage
|
||||
{
|
||||
const string MODULE_NAME = "WinOnCD plugin";
|
||||
byte[] _cdtext;
|
||||
|
||||
ImageInfo _imageInfo;
|
||||
Stream _imageStream;
|
||||
SectorBuilder _sectorBuilder;
|
||||
ImageInfo _imageInfo;
|
||||
Stream _imageStream;
|
||||
string _mcn;
|
||||
SectorBuilder _sectorBuilder;
|
||||
Dictionary<uint, byte> _trackFlags;
|
||||
Dictionary<uint, string> _trackIsrcs;
|
||||
|
||||
public WinOnCD() => _imageInfo = new ImageInfo
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user