[Aaru.Images] Reformat and cleanup.

This commit is contained in:
2023-10-03 23:34:59 +01:00
parent 6ffde343ce
commit 2cfad87955
432 changed files with 12011 additions and 8261 deletions

View File

@@ -45,25 +45,25 @@ namespace Aaru.DiscImages;
/// <summary>Implements reading A2R flux images</summary>
public sealed partial class A2R : IFluxImage, IMediaImage, IWritableImage, IWritableFluxImage
{
ImageInfo _imageInfo;
Stream _a2rStream;
IFilter _a2rFilter;
FileStream _writingStream;
A2rHeader Header;
Dictionary<string, string> Meta;
InfoChunkV2 _infoChunkV2;
InfoChunkV3 _infoChunkV3;
List<StreamCapture> _a2rCaptures;
uint _currentResolution;
const string MODULE_NAME = "A2R plugin";
List<StreamCapture> _a2rCaptures;
IFilter _a2rFilter;
Stream _a2rStream;
// Offset from the start of the current RWCP to the next capture
uint _currentCaptureOffset = 16;
uint _currentResolution;
// 53 = A2R header, INFO header, INFO data
long _currentRwcpStart = 53;
long _currentRwcpStart = 53;
ImageInfo _imageInfo;
InfoChunkV2 _infoChunkV2;
InfoChunkV3 _infoChunkV3;
FileStream _writingStream;
A2rHeader Header;
Dictionary<string, string> Meta;
public A2R()
{
public A2R() =>
_imageInfo = new ImageInfo
{
ReadableSectorTags = new List<SectorTagType>(),
@@ -87,7 +87,4 @@ public sealed partial class A2R : IFluxImage, IMediaImage, IWritableImage, IWrit
DriveSerialNumber = null,
DriveFirmwareRevision = null
};
}
const string MODULE_NAME = "A2R plugin";
}

View File

@@ -49,6 +49,11 @@ public sealed partial class A2R
0x49, 0x4E, 0x46, 0x4F // INFO
};
readonly byte[] _metaChunkSignature =
{
0x4D, 0x45, 0x54, 0x41 // META
};
readonly byte[] _rwcpChunkSignature =
{
0x52, 0x57, 0x43, 0x50 // RWCP
@@ -59,11 +64,6 @@ public sealed partial class A2R
0x53, 0x4C, 0x56, 0x44 // SLVD
};
readonly byte[] _metaChunkSignature =
{
0x4D, 0x45, 0x54, 0x41 // META
};
readonly byte[] _strmChunkSignature =
{
0x53, 0x54, 0x52, 0x4D // STRM

View File

@@ -36,15 +36,28 @@ namespace Aaru.DiscImages;
public sealed partial class A2R
{
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum A2rDriveType : byte
{
SS_525_40trk_quarterStep = 0x1, DS_35_80trk_appleCLV = 0x2, DS_525_80trk = 0x3,
DS_525_40trk = 0x4, DS_35_80trk = 0x5, DS_8 = 0x6
}
#region A2rDiskType enum
public enum A2rDiskType : byte
{
_525 = 0x01, _35 = 0x2,
_525 = 0x01,
_35 = 0x2
}
#endregion
#region A2rDriveType enum
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum A2rDriveType : byte
{
SS_525_40trk_quarterStep = 0x1,
DS_35_80trk_appleCLV = 0x2,
DS_525_80trk = 0x3,
DS_525_40trk = 0x4,
DS_35_80trk = 0x5,
DS_8 = 0x6
}
#endregion
}

View File

@@ -40,8 +40,8 @@ namespace Aaru.DiscImages;
public sealed partial class A2R
{
/// <summary>
/// Takes a Head, Track and Sub-Track representation, as well as the <c>MediaType</c>,
/// and converts it to the Track representation used by A2R.
/// Takes a Head, Track and Sub-Track representation, as well as the <c>MediaType</c>,
/// and converts it to the Track representation used by A2R.
/// </summary>
/// <param name="head">The head number</param>
/// <param name="track">The track number</param>
@@ -51,14 +51,14 @@ public sealed partial class A2R
static long HeadTrackSubToA2rLocation(uint head, ushort track, byte subTrack, MediaType mediaType)
{
if(mediaType == MediaType.Apple32SS)
return head + (track * 4) + subTrack;
return head + track * 4 + subTrack;
return head + (track * 2);
return head + track * 2;
}
/// <summary>
/// Takes a Head, Track and Sub-Track representation, as well as the <c>A2rDriveType</c>,
/// and converts it to the Track representation used by A2R.
/// Takes a Head, Track and Sub-Track representation, as well as the <c>A2rDriveType</c>,
/// and converts it to the Track representation used by A2R.
/// </summary>
/// <param name="head">The head number</param>
/// <param name="track">The track number</param>
@@ -68,22 +68,22 @@ public sealed partial class A2R
static long HeadTrackSubToA2rLocation(uint head, ushort track, byte subTrack, A2rDriveType driveType)
{
if(driveType == A2rDriveType.SS_525_40trk_quarterStep)
return head + (track * 4) + subTrack;
return head + track * 4 + subTrack;
return head + (track * 2);
return head + track * 2;
}
/// <summary>
/// Takes an A2R location and a <c>MediaType</c>, and converts it to a Head, Track and Sub-Track representation
/// used by the internal representation. The <c>MediaType</c> is needed because the track location is different
/// for different types of media sources.
/// Takes an A2R location and a <c>MediaType</c>, and converts it to a Head, Track and Sub-Track representation
/// used by the internal representation. The <c>MediaType</c> is needed because the track location is different
/// for different types of media sources.
/// </summary>
/// <param name="location">A2R format location</param>
/// <param name="mediaType"></param>
/// <param name="head">The head number</param>
/// <param name="track">The track number</param>
/// <param name="subTrack">The sub-track number</param>
static void A2rLocationToHeadTrackSub(uint location, MediaType mediaType, out uint head, out ushort track,
static void A2rLocationToHeadTrackSub(uint location, MediaType mediaType, out uint head, out ushort track,
out byte subTrack)
{
if(mediaType == MediaType.Apple32SS)
@@ -101,8 +101,8 @@ public sealed partial class A2R
}
/// <summary>
/// Takes a single number flux (uint length) and converts it to a flux in the
/// internal representation format (byte length)
/// Takes a single number flux (uint length) and converts it to a flux in the
/// internal representation format (byte length)
/// </summary>
/// <param name="ticks">The <c>uint</c> flux representation</param>
/// <returns>The <c>byte[]</c> flux representation</returns>
@@ -111,12 +111,11 @@ public sealed partial class A2R
uint over = ticks / 255;
if(over == 0)
return new[]
{
(byte)ticks
};
{
return new[] { (byte)ticks };
}
byte[] expanded = new byte[over + 1];
var expanded = new byte[over + 1];
Array.Fill(expanded, (byte)255, 0, (int)over);
expanded[^1] = (byte)(ticks % 255);
@@ -125,8 +124,8 @@ public sealed partial class A2R
}
/// <summary>
/// Takes a flux representation in the internal format (byte length) and converts it to
/// an array of single number fluxes (uint length)
/// Takes a flux representation in the internal format (byte length) and converts it to
/// an array of single number fluxes (uint length)
/// </summary>
/// <param name="flux">The <c>byte[]</c> flux representation</param>
/// <returns>The <c>uint</c> flux representation</returns>
@@ -151,9 +150,9 @@ public sealed partial class A2R
}
/// <summary>
/// A2R has two types of flux capture types; "timing" and "xtiming". The only difference is the length of the
/// capture, with "timing" being about 1¼ revolutions. This function returns <c>true</c> if the flux buffer is "timing"
/// and <c>false</c> otherwise.
/// A2R has two types of flux capture types; "timing" and "xtiming". The only difference is the length of the
/// capture, with "timing" being about 1¼ revolutions. This function returns <c>true</c> if the flux buffer is "timing"
/// and <c>false</c> otherwise.
/// </summary>
/// <param name="resolution">The resolution of the flux capture</param>
/// <param name="buffer">The flux data</param>

View File

@@ -39,6 +39,8 @@ namespace Aaru.DiscImages;
public sealed partial class A2R
{
#region IFluxImage Members
/// <inheritdoc />
public bool Identify(IFilter imageFilter)
{
@@ -48,10 +50,12 @@ public sealed partial class A2R
if(stream.Length < 8)
return false;
byte[] hdr = new byte[4];
var hdr = new byte[4];
stream.EnsureRead(hdr, 0, 4);
return _a2rV2Signature.SequenceEqual(hdr) || _a2rV3Signature.SequenceEqual(hdr);
}
#endregion
}

View File

@@ -41,44 +41,61 @@ namespace Aaru.DiscImages;
public sealed partial class A2R
{
bool IsWritingRwcps { get; set; }
#region IFluxImage Members
/// <inheritdoc />
public ImageInfo Info => _imageInfo;
/// <inheritdoc />
public string Name => Localization.A2R_Name;
/// <inheritdoc />
public Guid Id => new("7497c26a-fe44-4b50-a2e6-de50a9f3c13f");
/// <inheritdoc />
public string Author => Authors.RebeccaWallander;
/// <inheritdoc />
public string Format => "A2R";
/// <inheritdoc />
public List<DumpHardware> DumpHardware => null;
/// <inheritdoc />
public Metadata AaruMetadata => null;
#endregion
#region IWritableImage Members
/// <inheritdoc />
public IEnumerable<string> KnownExtensions => new[]
{
".a2r"
};
public IEnumerable<string> KnownExtensions => new[] { ".a2r" };
/// <inheritdoc />
public IEnumerable<MediaTagType> SupportedMediaTags => null;
/// <inheritdoc />
public IEnumerable<MediaType> SupportedMediaTypes => new[]
{
// TODO: A2R supports a lot more formats, please add more whence tested.
MediaType.DOS_35_DS_DD_9, MediaType.DOS_35_HD, MediaType.DOS_525_DS_DD_9, MediaType.DOS_525_HD,
MediaType.Apple32SS,
MediaType.Unknown
MediaType.Apple32SS, MediaType.Unknown
};
/// <inheritdoc />
public IEnumerable<(string name, Type type, string description, object @default)> SupportedOptions =>
Array.Empty<(string name, Type type, string description, object @default)>();
/// <inheritdoc />
public IEnumerable<SectorTagType> SupportedSectorTags => Array.Empty<SectorTagType>();
/// <inheritdoc />
public bool IsWriting { get; private set; }
/// <inheritdoc />
public string ErrorMessage { get; private set; }
bool IsWritingRwcps { get; set; }
#endregion
}

View File

@@ -45,6 +45,8 @@ namespace Aaru.DiscImages;
public sealed partial class A2R
{
#region IFluxImage Members
/// <inheritdoc />
public ErrorNumber Open(IFilter imageFilter)
{
@@ -53,7 +55,7 @@ public sealed partial class A2R
_a2rFilter = imageFilter;
byte[] hdr = new byte[Marshal.SizeOf<A2rHeader>()];
var hdr = new byte[Marshal.SizeOf<A2rHeader>()];
_a2rStream.EnsureRead(hdr, 0, Marshal.SizeOf<A2rHeader>());
Header = Marshal.ByteArrayToStructureLittleEndian<A2rHeader>(hdr);
@@ -61,13 +63,13 @@ public sealed partial class A2R
AaruConsole.DebugWriteLine(MODULE_NAME, "header.signature = \"{0}\"",
StringHandlers.CToString(Header.signature));
AaruConsole.DebugWriteLine(MODULE_NAME, "header.version = {0}", Header.version);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.version = {0}", Header.version);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.highBitTest = {0:X2}", Header.highBitTest);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.lineTest = {0:X2} {1:X2} {2:X2}", Header.lineTest[0],
Header.lineTest[1], Header.lineTest[2]);
byte[] infoMagic = new byte[4];
var infoMagic = new byte[4];
_a2rStream.EnsureRead(infoMagic, 0, 4);
// There must be an INFO chunk after the header (at byte 16)
@@ -80,7 +82,7 @@ public sealed partial class A2R
{
case 0x32:
{
byte[] infoChnk = new byte[Marshal.SizeOf<InfoChunkV2>()];
var infoChnk = new byte[Marshal.SizeOf<InfoChunkV2>()];
_a2rStream.EnsureRead(infoChnk, 0, Marshal.SizeOf<InfoChunkV2>());
_infoChunkV2 = Marshal.ByteArrayToStructureLittleEndian<InfoChunkV2>(infoChnk);
@@ -118,14 +120,15 @@ public sealed partial class A2R
_imageInfo.MediaType = MediaType.Apple32SS;
break;
default: return ErrorNumber.OutOfRange;
default:
return ErrorNumber.OutOfRange;
}
break;
}
case 0x33:
{
byte[] infoChk = new byte[Marshal.SizeOf<InfoChunkV3>()];
var infoChk = new byte[Marshal.SizeOf<InfoChunkV3>()];
_a2rStream.EnsureRead(infoChk, 0, Marshal.SizeOf<InfoChunkV3>());
_infoChunkV3 = Marshal.ByteArrayToStructureLittleEndian<InfoChunkV3>(infoChk);
@@ -191,7 +194,8 @@ public sealed partial class A2R
_imageInfo.Cylinders = 40;
break;
default: return ErrorNumber.OutOfRange;
default:
return ErrorNumber.OutOfRange;
}
break;
@@ -202,7 +206,7 @@ public sealed partial class A2R
while(_a2rStream.Position < _a2rStream.Length)
{
byte[] chunkHdr = new byte[Marshal.SizeOf<ChunkHeader>()];
var chunkHdr = new byte[Marshal.SizeOf<ChunkHeader>()];
_a2rStream.EnsureRead(chunkHdr, 0, Marshal.SizeOf<ChunkHeader>());
ChunkHeader chunkHeader = Marshal.ByteArrayToStructureLittleEndian<ChunkHeader>(chunkHdr);
_a2rStream.Seek(-Marshal.SizeOf<ChunkHeader>(), SeekOrigin.Current);
@@ -210,7 +214,7 @@ public sealed partial class A2R
switch(chunkHeader.chunkId)
{
case var rwcp when rwcp.SequenceEqual(_rwcpChunkSignature):
byte[] rwcpBuffer = new byte[Marshal.SizeOf<RwcpChunkHeader>()];
var rwcpBuffer = new byte[Marshal.SizeOf<RwcpChunkHeader>()];
_a2rStream.EnsureRead(rwcpBuffer, 0, Marshal.SizeOf<RwcpChunkHeader>());
RwcpChunkHeader rwcpChunk = Marshal.ByteArrayToStructureLittleEndian<RwcpChunkHeader>(rwcpBuffer);
@@ -222,11 +226,11 @@ public sealed partial class A2R
captureType = (byte)_a2rStream.ReadByte()
};
byte[] location = new byte[2];
var location = new byte[2];
_a2rStream.EnsureRead(location, 0, 2);
capture.location = BitConverter.ToUInt16(location);
A2rLocationToHeadTrackSub(capture.location, _imageInfo.MediaType, out capture.head,
A2rLocationToHeadTrackSub(capture.location, _imageInfo.MediaType, out capture.head,
out capture.track, out capture.subTrack);
if(capture.head + 1 > _imageInfo.Heads)
@@ -238,14 +242,14 @@ public sealed partial class A2R
capture.numberOfIndexSignals = (byte)_a2rStream.ReadByte();
capture.indexSignals = new uint[capture.numberOfIndexSignals];
for(int i = 0; capture.numberOfIndexSignals > i; i++)
for(var i = 0; capture.numberOfIndexSignals > i; i++)
{
byte[] index = new byte[4];
var index = new byte[4];
_a2rStream.EnsureRead(index, 0, 4);
capture.indexSignals[i] = BitConverter.ToUInt32(index);
}
byte[] dataSize = new byte[4];
var dataSize = new byte[4];
_a2rStream.EnsureRead(dataSize, 0, 4);
capture.captureDataSize = BitConverter.ToUInt32(dataSize);
@@ -264,7 +268,7 @@ public sealed partial class A2R
_a2rStream.Seek(Marshal.SizeOf<ChunkHeader>(), SeekOrigin.Current);
byte[] metadataBuffer = new byte[chunkHeader.chunkSize];
var metadataBuffer = new byte[chunkHeader.chunkSize];
_a2rStream.EnsureRead(metadataBuffer, 0, (int)chunkHeader.chunkSize);
string metaData = Encoding.UTF8.GetString(metadataBuffer);
@@ -286,9 +290,10 @@ public sealed partial class A2R
_imageInfo.MediaTitle = title;
break;
case var slvd when slvd.SequenceEqual(_slvdChunkSignature): return ErrorNumber.NotImplemented;
case var slvd when slvd.SequenceEqual(_slvdChunkSignature):
return ErrorNumber.NotImplemented;
case var strm when strm.SequenceEqual(_strmChunkSignature):
byte[] strmBuffer = new byte[Marshal.SizeOf<ChunkHeader>()];
var strmBuffer = new byte[Marshal.SizeOf<ChunkHeader>()];
_a2rStream.EnsureRead(strmBuffer, 0, Marshal.SizeOf<ChunkHeader>());
ChunkHeader strmChunk = Marshal.ByteArrayToStructureLittleEndian<ChunkHeader>(strmBuffer);
@@ -305,7 +310,7 @@ public sealed partial class A2R
numberOfIndexSignals = 1
};
A2rLocationToHeadTrackSub(capture.location, _imageInfo.MediaType, out capture.head,
A2rLocationToHeadTrackSub(capture.location, _imageInfo.MediaType, out capture.head,
out capture.track, out capture.subTrack);
if(capture.head + 1 > _imageInfo.Heads)
@@ -314,11 +319,11 @@ public sealed partial class A2R
if(capture.track + 1 > _imageInfo.Cylinders)
_imageInfo.Cylinders = (uint)(capture.track + 1);
byte[] dataSize = new byte[4];
var dataSize = new byte[4];
_a2rStream.EnsureRead(dataSize, 0, 4);
capture.captureDataSize = BitConverter.ToUInt32(dataSize);
byte[] index = new byte[4];
var index = new byte[4];
_a2rStream.EnsureRead(index, 0, 4);
capture.indexSignals[0] = BitConverter.ToUInt32(index);
@@ -349,7 +354,7 @@ public sealed partial class A2R
}
/// <inheritdoc />
public ErrorNumber ReadFluxIndexResolution(uint head, ushort track, byte subTrack, uint captureIndex,
public ErrorNumber ReadFluxIndexResolution(uint head, ushort track, byte subTrack, uint captureIndex,
out ulong resolution)
{
resolution = StreamCaptureAtIndex(head, track, subTrack, captureIndex).resolution;
@@ -358,7 +363,7 @@ public sealed partial class A2R
}
/// <inheritdoc />
public ErrorNumber ReadFluxDataResolution(uint head, ushort track, byte subTrack, uint captureIndex,
public ErrorNumber ReadFluxDataResolution(uint head, ushort track, byte subTrack, uint captureIndex,
out ulong resolution)
{
resolution = StreamCaptureAtIndex(head, track, subTrack, captureIndex).resolution;
@@ -367,7 +372,7 @@ public sealed partial class A2R
}
/// <inheritdoc />
public ErrorNumber ReadFluxResolution(uint head, ushort track, byte subTrack, uint captureIndex,
public ErrorNumber ReadFluxResolution(uint head, ushort track, byte subTrack, uint captureIndex,
out ulong indexResolution, out ulong dataResolution)
{
indexResolution = dataResolution = StreamCaptureAtIndex(head, track, subTrack, captureIndex).resolution;
@@ -376,8 +381,8 @@ public sealed partial class A2R
}
/// <inheritdoc />
public ErrorNumber ReadFluxCapture(uint head, ushort track, byte subTrack, uint captureIndex,
out ulong indexResolution, out ulong dataResolution, out byte[] indexBuffer,
public ErrorNumber ReadFluxCapture(uint head, ushort track, byte subTrack, uint captureIndex,
out ulong indexResolution, out ulong dataResolution, out byte[] indexBuffer,
out byte[] dataBuffer)
{
dataBuffer = indexBuffer = null;
@@ -399,7 +404,7 @@ public sealed partial class A2R
}
/// <inheritdoc />
public ErrorNumber ReadFluxIndexCapture(uint head, ushort track, byte subTrack, uint captureIndex,
public ErrorNumber ReadFluxIndexCapture(uint head, ushort track, byte subTrack, uint captureIndex,
out byte[] buffer)
{
buffer = null;
@@ -414,7 +419,7 @@ public sealed partial class A2R
uint previousTicks = 0;
for(int i = 0; i < capture.numberOfIndexSignals; i++)
for(var i = 0; i < capture.numberOfIndexSignals; i++)
{
uint ticks = capture.indexSignals[i] - previousTicks;
tmpBuffer.AddRange(UInt32ToFluxRepresentation(ticks));
@@ -461,6 +466,10 @@ public sealed partial class A2R
return ErrorNumber.NoError;
}
#endregion
#region IMediaImage Members
/// <inheritdoc />
public ErrorNumber ReadMediaTag(MediaTagType tag, out byte[] buffer) => throw new NotImplementedException();
@@ -486,6 +495,8 @@ public sealed partial class A2R
public ErrorNumber ReadSectorTag(ulong sectorAddress, SectorTagType tag, out byte[] buffer) =>
throw new NotImplementedException();
#endregion
StreamCapture StreamCaptureAtIndex(uint head, ushort track, byte subTrack, uint captureIndex)
{
long index = HeadTrackSubToA2rLocation(head, track, subTrack, _imageInfo.MediaType);

View File

@@ -36,6 +36,8 @@ namespace Aaru.DiscImages;
public sealed partial class A2R
{
#region Nested type: A2rHeader
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct A2rHeader
{
@@ -47,6 +49,10 @@ public sealed partial class A2R
public byte[] lineTest; // Should always be 0x0A 0x0D 0x0A
}
#endregion
#region Nested type: ChunkHeader
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ChunkHeader
{
@@ -55,6 +61,10 @@ public sealed partial class A2R
public uint chunkSize;
}
#endregion
#region Nested type: InfoChunkV2
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct InfoChunkV2
{
@@ -67,6 +77,10 @@ public sealed partial class A2R
public byte synchronized;
}
#endregion
#region Nested type: InfoChunkV3
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct InfoChunkV3
{
@@ -80,6 +94,10 @@ public sealed partial class A2R
public byte hardSectorCount;
}
#endregion
#region Nested type: RwcpChunkHeader
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct RwcpChunkHeader
{
@@ -90,6 +108,24 @@ public sealed partial class A2R
public byte[] reserved;
}
#endregion
#region Nested type: SlvdChunkHeader
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct SlvdChunkHeader
{
public ChunkHeader header;
public byte version;
public uint resolution;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)]
public byte[] reserved;
}
#endregion
#region Nested type: StreamCapture
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct StreamCapture
{
@@ -106,15 +142,9 @@ public sealed partial class A2R
public byte subTrack;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct SlvdChunkHeader
{
public ChunkHeader header;
public byte version;
public uint resolution;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)]
public byte[] reserved;
}
#endregion
#region Nested type: TrackHeader
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct TrackHeader
@@ -129,4 +159,6 @@ public sealed partial class A2R
public uint[] indexSignals;
public uint fluxDataSize;
}
#endregion
}

View File

@@ -45,9 +45,88 @@ namespace Aaru.DiscImages;
public sealed partial class A2R
{
#region IWritableFluxImage Members
/// <inheritdoc />
public ErrorNumber WriteFluxCapture(ulong indexResolution, ulong dataResolution, byte[] indexBuffer,
byte[] dataBuffer, uint head, ushort track, byte subTrack, uint captureIndex)
{
if(!IsWriting)
{
ErrorMessage = Localization.Tried_to_write_on_a_non_writable_image;
return ErrorNumber.WriteError;
}
// An RWCP chunk can only have one capture resolution. If the resolution changes we need to create a new chunk.
if(_currentResolution != dataResolution)
{
if(IsWritingRwcps)
{
CloseRwcpChunk();
_writingStream.Seek(_currentRwcpStart, SeekOrigin.Begin);
WriteRwcpHeader();
_currentRwcpStart = _writingStream.Length;
_currentCaptureOffset = 16;
}
IsWritingRwcps = true;
_currentResolution = (uint)dataResolution;
}
_writingStream.Seek(_currentRwcpStart + _currentCaptureOffset + Marshal.SizeOf<ChunkHeader>(),
SeekOrigin.Begin);
_writingStream.WriteByte(0x43);
_writingStream.WriteByte(IsCaptureTypeTiming(dataResolution, dataBuffer) ? (byte)1 : (byte)3);
_writingStream.
Write(
BitConverter.GetBytes((ushort)HeadTrackSubToA2rLocation(head, track, subTrack, _infoChunkV3.driveType)),
0, 2);
List<uint> a2rIndices = FluxRepresentationsToUInt32List(indexBuffer);
if(a2rIndices[0] == 0)
a2rIndices.RemoveAt(0);
_writingStream.WriteByte((byte)a2rIndices.Count);
long previousIndex = 0;
foreach(uint index in a2rIndices)
{
_writingStream.Write(BitConverter.GetBytes(index + previousIndex), 0, 4);
previousIndex += index;
}
_writingStream.Write(BitConverter.GetBytes(dataBuffer.Length), 0, 4);
_writingStream.Write(dataBuffer, 0, dataBuffer.Length);
_currentCaptureOffset += (uint)(9 + a2rIndices.Count * 4 + dataBuffer.Length);
return ErrorNumber.NoError;
}
/// <inheritdoc />
public ErrorNumber WriteFluxIndexCapture(ulong resolution, byte[] index, uint head, ushort track, byte subTrack,
uint captureIndex) => ErrorNumber.NoError;
/// <inheritdoc />
public ErrorNumber WriteFluxDataCapture(ulong resolution, byte[] data, uint head, ushort track, byte subTrack,
uint captureIndex) => ErrorNumber.NoError;
#endregion
#region IWritableImage Members
/// <inheritdoc />
public bool Create(string path, MediaType mediaType, Dictionary<string, string> options, ulong sectors,
uint sectorSize)
uint sectorSize)
{
try
{
@@ -69,12 +148,12 @@ public sealed partial class A2R
Header.lineTest = "\n\r\n"u8.ToArray();
_infoChunkV3.driveType = mediaType switch
{
MediaType.DOS_525_DS_DD_9 => A2rDriveType.DS_525_40trk,
MediaType.Apple32SS => A2rDriveType.SS_525_40trk_quarterStep,
MediaType.Unknown => A2rDriveType.DS_35_80trk,
_ => _infoChunkV3.driveType
};
{
MediaType.DOS_525_DS_DD_9 => A2rDriveType.DS_525_40trk,
MediaType.Apple32SS => A2rDriveType.SS_525_40trk_quarterStep,
MediaType.Unknown => A2rDriveType.DS_35_80trk,
_ => _infoChunkV3.driveType
};
return true;
}
@@ -134,7 +213,7 @@ public sealed partial class A2R
_infoChunkV3.hardSectorCount = 0;
Meta.Add("image_date", DateTime.Now.ToString("O"));
Meta.Add("title", imageInfo.MediaTitle);
Meta.Add("title", imageInfo.MediaTitle);
return true;
}
@@ -169,80 +248,10 @@ public sealed partial class A2R
/// <inheritdoc />
public bool WriteSectorsLong(byte[] data, ulong sectorAddress, uint length) => throw new NotImplementedException();
/// <inheritdoc />
public ErrorNumber WriteFluxCapture(ulong indexResolution, ulong dataResolution, byte[] indexBuffer,
byte[] dataBuffer, uint head, ushort track, byte subTrack, uint captureIndex)
{
if(!IsWriting)
{
ErrorMessage = Localization.Tried_to_write_on_a_non_writable_image;
return ErrorNumber.WriteError;
}
// An RWCP chunk can only have one capture resolution. If the resolution changes we need to create a new chunk.
if(_currentResolution != dataResolution)
{
if(IsWritingRwcps)
{
CloseRwcpChunk();
_writingStream.Seek(_currentRwcpStart, SeekOrigin.Begin);
WriteRwcpHeader();
_currentRwcpStart = _writingStream.Length;
_currentCaptureOffset = 16;
}
IsWritingRwcps = true;
_currentResolution = (uint)dataResolution;
}
_writingStream.Seek(_currentRwcpStart + _currentCaptureOffset + Marshal.SizeOf<ChunkHeader>(),
SeekOrigin.Begin);
_writingStream.WriteByte(0x43);
_writingStream.WriteByte(IsCaptureTypeTiming(dataResolution, dataBuffer) ? (byte)1 : (byte)3);
_writingStream.
Write(BitConverter.GetBytes((ushort)HeadTrackSubToA2rLocation(head, track, subTrack, _infoChunkV3.driveType)),
0, 2);
List<uint> a2rIndices = FluxRepresentationsToUInt32List(indexBuffer);
if(a2rIndices[0] == 0)
a2rIndices.RemoveAt(0);
_writingStream.WriteByte((byte)a2rIndices.Count);
long previousIndex = 0;
foreach(uint index in a2rIndices)
{
_writingStream.Write(BitConverter.GetBytes(index + previousIndex), 0, 4);
previousIndex += index;
}
_writingStream.Write(BitConverter.GetBytes(dataBuffer.Length), 0, 4);
_writingStream.Write(dataBuffer, 0, dataBuffer.Length);
_currentCaptureOffset += (uint)(9 + (a2rIndices.Count * 4) + dataBuffer.Length);
return ErrorNumber.NoError;
}
/// <inheritdoc />
public ErrorNumber WriteFluxIndexCapture(ulong resolution, byte[] index, uint head, ushort track, byte subTrack,
uint captureIndex) => ErrorNumber.NoError;
/// <inheritdoc />
public ErrorNumber WriteFluxDataCapture(ulong resolution, byte[] data, uint head, ushort track, byte subTrack,
uint captureIndex) => ErrorNumber.NoError;
#endregion
/// <summary>
/// writes the header to an RWCP chunk, up to and including the reserved bytes, to stream.
/// writes the header to an RWCP chunk, up to and including the reserved bytes, to stream.
/// </summary>
/// <returns></returns>
ErrorNumber WriteRwcpHeader()
@@ -254,15 +263,12 @@ public sealed partial class A2R
return ErrorNumber.WriteError;
}
_writingStream.Write(_rwcpChunkSignature, 0, 4);
_writingStream.Write(_rwcpChunkSignature, 0, 4);
_writingStream.Write(BitConverter.GetBytes(_currentCaptureOffset + 1), 0, 4);
_writingStream.WriteByte(1);
_writingStream.Write(BitConverter.GetBytes(_currentResolution), 0, 4);
byte[] reserved =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
byte[] reserved = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
_writingStream.Write(reserved, 0, 11);
@@ -270,7 +276,7 @@ public sealed partial class A2R
}
/// <summary>
/// Writes the entire INFO chunk to stream.
/// Writes the entire INFO chunk to stream.
/// </summary>
/// <returns></returns>
ErrorNumber WriteInfoChunk()
@@ -282,7 +288,7 @@ public sealed partial class A2R
return ErrorNumber.WriteError;
}
_writingStream.Write(_infoChunkV3.header.chunkId, 0, 4);
_writingStream.Write(_infoChunkV3.header.chunkId, 0, 4);
_writingStream.Write(BitConverter.GetBytes(_infoChunkV3.header.chunkSize), 0, 4);
_writingStream.WriteByte(_infoChunkV3.version);
_writingStream.Write(_infoChunkV3.creator, 0, 32);
@@ -295,7 +301,7 @@ public sealed partial class A2R
}
/// <summary>
/// Writes the entire META chunk to stream.
/// Writes the entire META chunk to stream.
/// </summary>
/// <returns></returns>
ErrorNumber WriteMetaChunk()
@@ -313,13 +319,13 @@ public sealed partial class A2R
Aggregate(static (concat, str) => $"{concat}\n{str}") + '\n');
_writingStream.Write(BitConverter.GetBytes((uint)metaString.Length), 0, 4);
_writingStream.Write(metaString, 0, metaString.Length);
_writingStream.Write(metaString, 0, metaString.Length);
return ErrorNumber.NoError;
}
/// <summary>
/// Writes the closing byte to an RWCP chunk signaling its end, to stream.
/// Writes the closing byte to an RWCP chunk signaling its end, to stream.
/// </summary>
/// <returns></returns>
ErrorNumber CloseRwcpChunk()

View File

@@ -35,8 +35,8 @@
<NoWarn>CS1591;CS1574</NoWarn>
</PropertyGroup>
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<InternalsVisibleTo Include="Aaru.Tests" />
<InternalsVisibleTo Include="Aaru.Tests.Devices" />
<InternalsVisibleTo Include="Aaru.Tests"/>
<InternalsVisibleTo Include="Aaru.Tests.Devices"/>
</ItemGroup>
<PropertyGroup>
<NrtRevisionFormat>$(Version)+{chash:8}</NrtRevisionFormat>
@@ -44,25 +44,25 @@
<NrtShowRevision>true</NrtShowRevision>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Claunia.Encoding" Version="1.9.2" />
<PackageReference Include="Claunia.RsrcFork" Version="1.2.0" />
<PackageReference Include="DotNetZip" Version="1.16.0" />
<PackageReference Include="plist-cil" Version="2.2.0" />
<PackageReference Include="SharpCompress" Version="0.34.0" />
<PackageReference Include="System.Text.Json" Version="8.0.0-rc.1.23419.4" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="Unclassified.NetRevisionTask" Version="0.4.3" PrivateAssets="all" />
<PackageReference Include="Claunia.Encoding" Version="1.9.2"/>
<PackageReference Include="Claunia.RsrcFork" Version="1.2.0"/>
<PackageReference Include="DotNetZip" Version="1.16.0"/>
<PackageReference Include="plist-cil" Version="2.2.0"/>
<PackageReference Include="SharpCompress" Version="0.34.0"/>
<PackageReference Include="System.Text.Json" Version="8.0.0-rc.1.23419.4"/>
<PackageReference Include="System.ValueTuple" Version="4.5.0"/>
<PackageReference Include="Unclassified.NetRevisionTask" Version="0.4.3" PrivateAssets="all"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Aaru.CommonTypes\Aaru.CommonTypes.csproj" />
<ProjectReference Include="..\Aaru.Checksums\Aaru.Checksums.csproj" />
<ProjectReference Include="..\Aaru.Compression\Aaru.Compression.csproj" />
<ProjectReference Include="..\Aaru.Database\Aaru.Database.csproj" />
<ProjectReference Include="..\Aaru.Helpers\Aaru.Helpers.csproj" />
<ProjectReference Include="..\Aaru.Console\Aaru.Console.csproj" />
<ProjectReference Include="..\Aaru.Decoders\Aaru.Decoders.csproj" />
<ProjectReference Include="..\Aaru.Filters\Aaru.Filters.csproj" />
<ProjectReference Include="..\Aaru.Settings\Aaru.Settings.csproj" />
<ProjectReference Include="..\Aaru.CommonTypes\Aaru.CommonTypes.csproj"/>
<ProjectReference Include="..\Aaru.Checksums\Aaru.Checksums.csproj"/>
<ProjectReference Include="..\Aaru.Compression\Aaru.Compression.csproj"/>
<ProjectReference Include="..\Aaru.Database\Aaru.Database.csproj"/>
<ProjectReference Include="..\Aaru.Helpers\Aaru.Helpers.csproj"/>
<ProjectReference Include="..\Aaru.Console\Aaru.Console.csproj"/>
<ProjectReference Include="..\Aaru.Decoders\Aaru.Decoders.csproj"/>
<ProjectReference Include="..\Aaru.Filters\Aaru.Filters.csproj"/>
<ProjectReference Include="..\Aaru.Settings\Aaru.Settings.csproj"/>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="..\LICENSE.LGPL">
@@ -74,6 +74,6 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Aaru.Generators\Aaru.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<ProjectReference Include="..\Aaru.Generators\Aaru.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
</ItemGroup>
</Project>

View File

@@ -2,92 +2,92 @@
xmlns:s="clr-namespace:System;assembly=mscorlib"
xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xml:space="preserve">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=aaruformat/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=alcohol120/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=anex86/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=apple2mg/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=appledos/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=applenib/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=apridisk/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=blindwrite4/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=blindwrite5/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=blu/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=byteaddressable/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=cdrdao/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=cdrwin/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=chd/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=ciscopy/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=clonecd/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=copyqm/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=copytape/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=cpcdsk/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=d88/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=dart/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=dim/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=discferret/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=discjuggler/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=diskcopy42/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=diskdupe/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=dridiskcopy/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=gdi/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=hdcopy/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=imd/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=kryoflux/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=localization/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=maxidisk/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=ndif/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=nero/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=nhdr0/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=parallels/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=partclone/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=partimage/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=qcow/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=qcow2/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=qed/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=raydim/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=rside/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=savedskf/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=supercardpro/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=t98/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=teledisk/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=udif/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=ukvfdi/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=vdi/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=vhd/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=vhdx/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=virtual98/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=vmware/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=wcdiskimage/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=zzzrawimage/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=alcohol120/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=anex86/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=apple2mg/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=appledos/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=applenib/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=apridisk/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=blindwrite4/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=blindwrite5/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=blu/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=byteaddressable/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=cdrdao/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=cdrwin/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=chd/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=ciscopy/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=clonecd/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=copyqm/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=copytape/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=cpcdsk/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=d88/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=dart/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=dim/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=discferret/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=discjuggler/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=diskcopy42/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=diskdupe/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=dridiskcopy/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=gdi/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=hdcopy/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=imd/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=kryoflux/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=localization/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=maxidisk/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=ndif/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=nero/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=nhdr0/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=parallels/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=partclone/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=partimage/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=qcow/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=qcow2/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=qed/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=raydim/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=rside/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=savedskf/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=supercardpro/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=t98/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=teledisk/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=udif/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=ukvfdi/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=vdi/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=vhd/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=vhdx/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=virtual98/@EntryIndexedValue">True</s:Boolean>
<s:Boolean
x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=vmware/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=wcdiskimage/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=zzzrawimage/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@@ -83,7 +83,8 @@ namespace Aaru.DiscImages;
/// <summary>Implements reading and writing AaruFormat media images</summary>
public sealed partial class AaruFormat : IWritableOpticalImage, IVerifiableImage, IWritableTapeImage
{
bool _alreadyWrittenZero;
const string MODULE_NAME = "Aaru Format plugin";
bool _alreadyWrittenZero;
/// <summary>Cache of uncompressed blocks.</summary>
Dictionary<ulong, byte[]> _blockCache;
/// <summary>Cache of block headers.</summary>
@@ -129,10 +130,10 @@ public sealed partial class AaruFormat : IWritableOpticalImage, IVerifiableImage
long _outMemoryDdtPosition;
bool _rewinded;
byte[] _sectorCprMai;
byte[] _sectorIed;
byte[] _sectorId;
byte[] _sectorEdc;
byte[] _sectorDecryptedTitleKey;
byte[] _sectorEdc;
byte[] _sectorId;
byte[] _sectorIed;
/// <summary>Cache for data that prefixes the user data on a sector (e.g. sync).</summary>
byte[] _sectorPrefix;
uint[] _sectorPrefixDdt;
@@ -187,6 +188,4 @@ public sealed partial class AaruFormat : IWritableOpticalImage, IVerifiableImage
DriveSerialNumber = null,
DriveFirmwareRevision = null
};
const string MODULE_NAME = "Aaru Format plugin";
}

View File

@@ -55,12 +55,12 @@ public sealed partial class AaruFormat
for(uint i = 0; i < 256; i++)
{
uint edc = i;
uint j = (uint)((i << 1) ^ ((i & 0x80) == 0x80 ? 0x11D : 0));
var j = (uint)(i << 1 ^ ((i & 0x80) == 0x80 ? 0x11D : 0));
_eccFTable[i] = (byte)j;
_eccBTable[i ^ j] = (byte)i;
for(j = 0; j < 8; j++)
edc = (edc >> 1) ^ ((edc & 1) > 0 ? 0xD8018001 : 0);
edc = edc >> 1 ^ ((edc & 1) > 0 ? 0xD8018001 : 0);
_edcTable[i] = edc;
}
@@ -93,13 +93,13 @@ public sealed partial class AaruFormat
if(!correctEccQ)
return false;
uint storedEdc = BitConverter.ToUInt32(sector, 0x810);
var storedEdc = BitConverter.ToUInt32(sector, 0x810);
uint edc = 0;
int size = 0x810;
int pos = 0;
var size = 0x810;
var pos = 0;
for(; size > 0; size--)
edc = (edc >> 8) ^ _edcTable[(edc ^ sector[pos++]) & 0xFF];
edc = edc >> 8 ^ _edcTable[(edc ^ sector[pos++]) & 0xFF];
uint calculatedEdc = edc;
@@ -111,7 +111,7 @@ public sealed partial class AaruFormat
if(!_initedEdc)
EccInit();
byte[] zeroAddress = new byte[4];
var zeroAddress = new byte[4];
bool correctEccP = CheckEcc(zeroAddress, sector, 86, 24, 2, 86, sector, 0, 0x10, 0x81C);
@@ -123,28 +123,28 @@ public sealed partial class AaruFormat
if(!correctEccQ)
return false;
uint storedEdc = BitConverter.ToUInt32(sector, 0x818);
var storedEdc = BitConverter.ToUInt32(sector, 0x818);
uint edc = 0;
int size = 0x808;
int pos = 0x10;
var size = 0x808;
var pos = 0x10;
for(; size > 0; size--)
edc = (edc >> 8) ^ _edcTable[(edc ^ sector[pos++]) & 0xFF];
edc = edc >> 8 ^ _edcTable[(edc ^ sector[pos++]) & 0xFF];
uint calculatedEdc = edc;
return calculatedEdc == storedEdc;
}
bool CheckEcc(byte[] address, byte[] data, uint majorCount, uint minorCount, uint majorMult, uint minorInc,
byte[] ecc, int addressOffset, int dataOffset, int eccOffset)
bool CheckEcc(byte[] address, byte[] data, uint majorCount, uint minorCount, uint majorMult, uint minorInc,
byte[] ecc, int addressOffset, int dataOffset, int eccOffset)
{
uint size = majorCount * minorCount;
uint major;
for(major = 0; major < majorCount; major++)
{
uint idx = ((major >> 1) * majorMult) + (major & 1);
uint idx = (major >> 1) * majorMult + (major & 1);
byte eccA = 0;
byte eccB = 0;
uint minor;
@@ -172,15 +172,15 @@ public sealed partial class AaruFormat
return true;
}
void WriteEcc(byte[] address, byte[] data, uint majorCount, uint minorCount, uint majorMult, uint minorInc,
ref byte[] ecc, int addressOffset, int dataOffset, int eccOffset)
void WriteEcc(byte[] address, byte[] data, uint majorCount, uint minorCount, uint majorMult, uint minorInc,
ref byte[] ecc, int addressOffset, int dataOffset, int eccOffset)
{
uint size = majorCount * minorCount;
uint major;
for(major = 0; major < majorCount; major++)
{
uint idx = ((major >> 1) * majorMult) + (major & 1);
uint idx = (major >> 1) * majorMult + (major & 1);
byte eccA = 0;
byte eccB = 0;
uint minor;
@@ -206,7 +206,7 @@ public sealed partial class AaruFormat
void EccWriteSector(byte[] address, byte[] data, ref byte[] ecc, int addressOffset, int dataOffset, int eccOffset)
{
WriteEcc(address, data, 86, 24, 2, 86, ref ecc, addressOffset, dataOffset, eccOffset); // P
WriteEcc(address, data, 86, 24, 2, 86, ref ecc, addressOffset, dataOffset, eccOffset); // P
WriteEcc(address, data, 52, 43, 86, 88, ref ecc, addressOffset, dataOffset, eccOffset + 0xAC); // Q
}
@@ -214,7 +214,7 @@ public sealed partial class AaruFormat
((byte)((pos + 150) / 75 / 60), (byte)((pos + 150) / 75 % 60), (byte)((pos + 150) % 75));
static void ReconstructPrefix(ref byte[] sector, // must point to a full 2352-byte sector
TrackType type, long lba)
TrackType type, long lba)
{
//
// Sync
@@ -234,9 +234,9 @@ public sealed partial class AaruFormat
(byte minute, byte second, byte frame) msf = LbaToMsf(lba);
sector[0x00C] = (byte)(((msf.minute / 10) << 4) + (msf.minute % 10));
sector[0x00D] = (byte)(((msf.second / 10) << 4) + (msf.second % 10));
sector[0x00E] = (byte)(((msf.frame / 10) << 4) + (msf.frame % 10));
sector[0x00C] = (byte)((msf.minute / 10 << 4) + msf.minute % 10);
sector[0x00D] = (byte)((msf.second / 10 << 4) + msf.second % 10);
sector[0x00E] = (byte)((msf.frame / 10 << 4) + msf.frame % 10);
switch(type)
{
@@ -264,12 +264,13 @@ public sealed partial class AaruFormat
sector[0x013] = sector[0x017];
break;
default: return;
default:
return;
}
}
void ReconstructEcc(ref byte[] sector, // must point to a full 2352-byte sector
TrackType type)
TrackType type)
{
byte[] computedEdc;
@@ -305,10 +306,11 @@ public sealed partial class AaruFormat
sector[0x92F] = computedEdc[3];
break;
default: return;
default:
return;
}
byte[] zeroAddress = new byte[4];
var zeroAddress = new byte[4];
switch(type)
{
@@ -334,7 +336,8 @@ public sealed partial class AaruFormat
EccWriteSector(zeroAddress, sector, ref sector, 0, 0x10, 0x81C);
break;
default: return;
default:
return;
}
//
@@ -350,7 +353,7 @@ public sealed partial class AaruFormat
int pos = srcOffset;
for(; size > 0; size--)
edc = (edc >> 8) ^ _edcTable[(edc ^ src[pos++]) & 0xFF];
edc = edc >> 8 ^ _edcTable[(edc ^ src[pos++]) & 0xFF];
return edc;
}

View File

@@ -43,19 +43,19 @@ public sealed partial class AaruFormat
if(interleaved == null)
return null;
int[] p = new int[interleaved.Length / 8];
int[] q = new int[interleaved.Length / 8];
int[] r = new int[interleaved.Length / 8];
int[] s = new int[interleaved.Length / 8];
int[] t = new int[interleaved.Length / 8];
int[] u = new int[interleaved.Length / 8];
int[] v = new int[interleaved.Length / 8];
int[] w = new int[interleaved.Length / 8];
var p = new int[interleaved.Length / 8];
var q = new int[interleaved.Length / 8];
var r = new int[interleaved.Length / 8];
var s = new int[interleaved.Length / 8];
var t = new int[interleaved.Length / 8];
var u = new int[interleaved.Length / 8];
var v = new int[interleaved.Length / 8];
var w = new int[interleaved.Length / 8];
var stopwatch = new Stopwatch();
stopwatch.Start();
for(int i = 0; i < interleaved.Length; i += 8)
for(var i = 0; i < interleaved.Length; i += 8)
{
p[i / 8] = interleaved[i] & 0x80;
p[i / 8] += (interleaved[i + 1] & 0x80) >> 1;
@@ -133,7 +133,7 @@ public sealed partial class AaruFormat
stopwatch.Stop();
TimeSpan deinterleave = stopwatch.Elapsed;
byte[] sequential = new byte[interleaved.Length];
var sequential = new byte[interleaved.Length];
stopwatch.Restart();
int qStart = p.Length * 1;
@@ -144,7 +144,7 @@ public sealed partial class AaruFormat
int vStart = p.Length * 6;
int wStart = p.Length * 7;
for(int i = 0; i < p.Length; i++)
for(var i = 0; i < p.Length; i++)
{
sequential[i] = (byte)p[i];
sequential[qStart + i] = (byte)q[i];
@@ -176,14 +176,14 @@ public sealed partial class AaruFormat
if(sequential == null)
return null;
int[] p = new int[sequential.Length / 8];
int[] q = new int[sequential.Length / 8];
int[] r = new int[sequential.Length / 8];
int[] s = new int[sequential.Length / 8];
int[] t = new int[sequential.Length / 8];
int[] u = new int[sequential.Length / 8];
int[] v = new int[sequential.Length / 8];
int[] w = new int[sequential.Length / 8];
var p = new int[sequential.Length / 8];
var q = new int[sequential.Length / 8];
var r = new int[sequential.Length / 8];
var s = new int[sequential.Length / 8];
var t = new int[sequential.Length / 8];
var u = new int[sequential.Length / 8];
var v = new int[sequential.Length / 8];
var w = new int[sequential.Length / 8];
int qStart = p.Length * 1;
int rStart = p.Length * 2;
@@ -196,7 +196,7 @@ public sealed partial class AaruFormat
var stopwatch = new Stopwatch();
stopwatch.Start();
for(int i = 0; i < p.Length; i++)
for(var i = 0; i < p.Length; i++)
{
p[i] = sequential[i];
q[i] = sequential[qStart + i];
@@ -211,10 +211,10 @@ public sealed partial class AaruFormat
stopwatch.Stop();
TimeSpan desequentialize = stopwatch.Elapsed;
byte[] interleaved = new byte[sequential.Length];
var interleaved = new byte[sequential.Length];
stopwatch.Restart();
for(int i = 0; i < interleaved.Length; i += 8)
for(var i = 0; i < interleaved.Length; i += 8)
{
interleaved[i] = (byte)((p[i / 8] & 0x80) == 0x80 ? 0x80 : 0);
interleaved[i + 1] += (byte)((p[i / 8] & 0x40) == 0x40 ? 0x80 : 0);

View File

@@ -36,6 +36,77 @@ namespace Aaru.DiscImages;
public sealed partial class AaruFormat
{
#region Nested type: BlockType
/// <summary>List of known blocks types</summary>
enum BlockType : uint
{
/// <summary>Block containing data</summary>
DataBlock = 0x4B4C4244,
/// <summary>Block containing a deduplication table</summary>
DeDuplicationTable = 0x2A544444,
/// <summary>Block containing the index</summary>
Index = 0x58444E49,
/// <summary>Block containing the index</summary>
Index2 = 0x32584449,
/// <summary>Block containing logical geometry</summary>
GeometryBlock = 0x4D4F4547,
/// <summary>Block containing metadata</summary>
MetadataBlock = 0x4154454D,
/// <summary>Block containing optical disc tracks</summary>
TracksBlock = 0x534B5254,
/// <summary>Block containing CICM XML metadata</summary>
CicmBlock = 0x4D434943,
/// <summary>Block containing contents checksums</summary>
ChecksumBlock = 0x4D534B43,
/// <summary>TODO: Block containing data position measurements</summary>
DataPositionMeasurementBlock = 0x2A4D5044,
/// <summary>TODO: Block containing a snapshot index</summary>
SnapshotBlock = 0x50414E53,
/// <summary>TODO: Block containing how to locate the parent image</summary>
ParentBlock = 0x544E5250,
/// <summary>Block containing an array of hardware used to create the image</summary>
DumpHardwareBlock = 0x2A504D44,
/// <summary>Block containing list of files for a tape image</summary>
TapeFileBlock = 0x454C4654,
/// <summary>Block containing list of partitions for a tape image</summary>
TapePartitionBlock = 0x54425054,
/// <summary>Block containing list of indexes for Compact Disc tracks</summary>
CompactDiscIndexesBlock = 0x58494443,
/// <summary>Block containing JSON version of Aaru Metadata</summary>
AaruMetadataJsonBlock = 0x444D534A
}
#endregion
#region Nested type: CdFixFlags
enum CdFixFlags : uint
{
NotDumped = 0x10000000,
Correct = 0x20000000,
Mode2Form1Ok = 0x30000000,
Mode2Form2Ok = 0x40000000,
Mode2Form2NoCrc = 0x50000000
}
#endregion
#region Nested type: ChecksumAlgorithm
enum ChecksumAlgorithm : byte
{
Invalid = 0,
Md5 = 1,
Sha1 = 2,
Sha256 = 3,
SpamSum = 4
}
#endregion
#region Nested type: CompressionType
/// <summary>List of known compression types</summary>
enum CompressionType : ushort
{
@@ -49,6 +120,10 @@ public sealed partial class AaruFormat
LzmaClauniaSubchannelTransform = 3
}
#endregion
#region Nested type: DataType
/// <summary>List of known data types</summary>
enum DataType : ushort
{
@@ -226,54 +301,5 @@ public sealed partial class AaruFormat
DvdSectorEdc = 85
}
/// <summary>List of known blocks types</summary>
enum BlockType : uint
{
/// <summary>Block containing data</summary>
DataBlock = 0x4B4C4244,
/// <summary>Block containing a deduplication table</summary>
DeDuplicationTable = 0x2A544444,
/// <summary>Block containing the index</summary>
Index = 0x58444E49,
/// <summary>Block containing the index</summary>
Index2 = 0x32584449,
/// <summary>Block containing logical geometry</summary>
GeometryBlock = 0x4D4F4547,
/// <summary>Block containing metadata</summary>
MetadataBlock = 0x4154454D,
/// <summary>Block containing optical disc tracks</summary>
TracksBlock = 0x534B5254,
/// <summary>Block containing CICM XML metadata</summary>
CicmBlock = 0x4D434943,
/// <summary>Block containing contents checksums</summary>
ChecksumBlock = 0x4D534B43,
/// <summary>TODO: Block containing data position measurements</summary>
DataPositionMeasurementBlock = 0x2A4D5044,
/// <summary>TODO: Block containing a snapshot index</summary>
SnapshotBlock = 0x50414E53,
/// <summary>TODO: Block containing how to locate the parent image</summary>
ParentBlock = 0x544E5250,
/// <summary>Block containing an array of hardware used to create the image</summary>
DumpHardwareBlock = 0x2A504D44,
/// <summary>Block containing list of files for a tape image</summary>
TapeFileBlock = 0x454C4654,
/// <summary>Block containing list of partitions for a tape image</summary>
TapePartitionBlock = 0x54425054,
/// <summary>Block containing list of indexes for Compact Disc tracks</summary>
CompactDiscIndexesBlock = 0x58494443,
/// <summary>Block containing JSON version of Aaru Metadata</summary>
AaruMetadataJsonBlock = 0x444D534A
}
enum ChecksumAlgorithm : byte
{
Invalid = 0, Md5 = 1, Sha1 = 2,
Sha256 = 3, SpamSum = 4
}
enum CdFixFlags : uint
{
NotDumped = 0x10000000, Correct = 0x20000000, Mode2Form1Ok = 0x30000000,
Mode2Form2Ok = 0x40000000, Mode2Form2NoCrc = 0x50000000
}
#endregion
}

View File

@@ -57,8 +57,10 @@ public sealed partial class AaruFormat
_imageInfo.DriveModel = decoded.ProductName;
if(string.IsNullOrWhiteSpace(_imageInfo.DriveFirmwareRevision))
{
_imageInfo.DriveFirmwareRevision =
$"{(decoded.ProductRevision & 0xF0) >> 4:X2}.{decoded.ProductRevision & 0x0F:X2}";
}
if(string.IsNullOrWhiteSpace(_imageInfo.DriveSerialNumber))
_imageInfo.DriveSerialNumber = $"{decoded.ProductSerialNumber}";
@@ -76,8 +78,10 @@ public sealed partial class AaruFormat
_imageInfo.DriveModel = decoded.ProductName;
if(string.IsNullOrWhiteSpace(_imageInfo.DriveFirmwareRevision))
{
_imageInfo.DriveFirmwareRevision =
$"{(decoded.ProductRevision & 0xF0) >> 4:X2}.{decoded.ProductRevision & 0x0F:X2}";
}
if(string.IsNullOrWhiteSpace(_imageInfo.DriveSerialNumber))
_imageInfo.DriveSerialNumber = $"{decoded.ProductSerialNumber}";
@@ -104,7 +108,7 @@ public sealed partial class AaruFormat
}
// Search for ATA or ATAPI IDENTIFY
if(!_mediaTags.TryGetValue(MediaTagType.ATA_IDENTIFY, out byte[] ataIdentify) &&
if(!_mediaTags.TryGetValue(MediaTagType.ATA_IDENTIFY, out byte[] ataIdentify) &&
!_mediaTags.TryGetValue(MediaTagType.ATAPI_IDENTIFY, out ataIdentify))
return;
@@ -118,6 +122,7 @@ public sealed partial class AaruFormat
string[] separated = identify.Model.Split(' ');
if(separated.Length == 1)
{
if(string.IsNullOrWhiteSpace(_imageInfo.DriveModel))
_imageInfo.DriveModel = separated[0];
else
@@ -128,6 +133,7 @@ public sealed partial class AaruFormat
if(string.IsNullOrWhiteSpace(_imageInfo.DriveModel))
_imageInfo.DriveModel = separated[^1];
}
}
if(string.IsNullOrWhiteSpace(_imageInfo.DriveFirmwareRevision))
_imageInfo.DriveFirmwareRevision = identify.FirmwareRevision;
@@ -235,8 +241,10 @@ public sealed partial class AaruFormat
case MediaType.VideoNow:
case MediaType.VideoNowColor:
case MediaType.VideoNowXp:
case MediaType.CVD: return MetadataMediaType.OpticalDisc;
default: return MetadataMediaType.BlockMedia;
case MediaType.CVD:
return MetadataMediaType.OpticalDisc;
default:
return MetadataMediaType.BlockMedia;
}
}
@@ -252,7 +260,7 @@ public sealed partial class AaruFormat
long oldPosition = _imageStream.Position;
_imageStream.Position = _outMemoryDdtPosition + Marshal.SizeOf<DdtHeader>();
_imageStream.Position += (long)(sectorAddress * sizeof(ulong));
byte[] temp = new byte[sizeof(ulong)];
var temp = new byte[sizeof(ulong)];
_imageStream.EnsureRead(temp, 0, sizeof(ulong));
_imageStream.Position = oldPosition;
entry = BitConverter.ToUInt64(temp, 0);
@@ -287,153 +295,246 @@ public sealed partial class AaruFormat
// Converts between image data type and Aaru media tag type
static MediaTagType GetMediaTagTypeForDataType(DataType type) => type switch
{
DataType.CompactDiscPartialToc => MediaTagType.CD_TOC,
DataType.CompactDiscSessionInfo => MediaTagType.CD_SessionInfo,
DataType.CompactDiscToc => MediaTagType.CD_FullTOC,
DataType.CompactDiscPma => MediaTagType.CD_PMA,
DataType.CompactDiscAtip => MediaTagType.CD_ATIP,
DataType.CompactDiscLeadInCdText => MediaTagType.CD_TEXT,
DataType.DvdPfi => MediaTagType.DVD_PFI,
DataType.DvdLeadInCmi => MediaTagType.DVD_CMI,
DataType.DvdDiscKey => MediaTagType.DVD_DiscKey,
DataType.DvdBca => MediaTagType.DVD_BCA,
DataType.DvdDmi => MediaTagType.DVD_DMI,
DataType.DvdMediaIdentifier => MediaTagType.DVD_MediaIdentifier,
DataType.DvdMediaKeyBlock => MediaTagType.DVD_MKB,
DataType.DvdRamDds => MediaTagType.DVDRAM_DDS,
DataType.DvdRamMediumStatus => MediaTagType.DVDRAM_MediumStatus,
DataType.DvdRamSpareArea => MediaTagType.DVDRAM_SpareArea,
DataType.DvdRRmd => MediaTagType.DVDR_RMD,
DataType.DvdRPrerecordedInfo => MediaTagType.DVDR_PreRecordedInfo,
DataType.DvdRMediaIdentifier => MediaTagType.DVDR_MediaIdentifier,
DataType.DvdRPfi => MediaTagType.DVDR_PFI,
DataType.DvdAdip => MediaTagType.DVD_ADIP,
DataType.HdDvdCpi => MediaTagType.HDDVD_CPI,
DataType.HdDvdMediumStatus => MediaTagType.HDDVD_MediumStatus,
DataType.DvdDlLayerCapacity => MediaTagType.DVDDL_LayerCapacity,
DataType.DvdDlMiddleZoneAddress => MediaTagType.DVDDL_MiddleZoneAddress,
DataType.DvdDlJumpIntervalSize => MediaTagType.DVDDL_JumpIntervalSize,
DataType.DvdDlManualLayerJumpLba => MediaTagType.DVDDL_ManualLayerJumpLBA,
DataType.BlurayDi => MediaTagType.BD_DI,
DataType.BlurayBca => MediaTagType.BD_BCA,
DataType.BlurayDds => MediaTagType.BD_DDS,
DataType.BlurayCartridgeStatus => MediaTagType.BD_CartridgeStatus,
DataType.BluraySpareArea => MediaTagType.BD_SpareArea,
DataType.AacsVolumeIdentifier => MediaTagType.AACS_VolumeIdentifier,
DataType.AacsSerialNumber => MediaTagType.AACS_SerialNumber,
DataType.AacsMediaIdentifier => MediaTagType.AACS_MediaIdentifier,
DataType.AacsMediaKeyBlock => MediaTagType.AACS_MKB,
DataType.AacsDataKeys => MediaTagType.AACS_DataKeys,
DataType.AacsLbaExtents => MediaTagType.AACS_LBAExtents,
DataType.CprmMediaKeyBlock => MediaTagType.AACS_CPRM_MKB,
DataType.HybridRecognizedLayers => MediaTagType.Hybrid_RecognizedLayers,
DataType.ScsiMmcWriteProtection => MediaTagType.MMC_WriteProtection,
DataType.ScsiMmcDiscInformation => MediaTagType.MMC_DiscInformation,
DataType.ScsiMmcTrackResourcesInformation => MediaTagType.MMC_TrackResourcesInformation,
DataType.ScsiMmcPowResourcesInformation => MediaTagType.MMC_POWResourcesInformation,
DataType.ScsiInquiry => MediaTagType.SCSI_INQUIRY,
DataType.ScsiModePage2A => MediaTagType.SCSI_MODEPAGE_2A,
DataType.AtaIdentify => MediaTagType.ATA_IDENTIFY,
DataType.AtapiIdentify => MediaTagType.ATAPI_IDENTIFY,
DataType.PcmciaCis => MediaTagType.PCMCIA_CIS,
DataType.SecureDigitalCid => MediaTagType.SD_CID,
DataType.SecureDigitalCsd => MediaTagType.SD_CSD,
DataType.SecureDigitalScr => MediaTagType.SD_SCR,
DataType.SecureDigitalOcr => MediaTagType.SD_OCR,
DataType.MultiMediaCardCid => MediaTagType.MMC_CID,
DataType.MultiMediaCardCsd => MediaTagType.MMC_CSD,
DataType.MultiMediaCardOcr => MediaTagType.MMC_OCR,
DataType.MultiMediaCardExtendedCsd => MediaTagType.MMC_ExtendedCSD,
DataType.XboxSecuritySector => MediaTagType.Xbox_SecuritySector,
DataType.FloppyLeadOut => MediaTagType.Floppy_LeadOut,
DataType.DvdDiscControlBlock => MediaTagType.DCB,
DataType.CompactDiscFirstTrackPregap => MediaTagType.CD_FirstTrackPregap,
DataType.CompactDiscLeadOut => MediaTagType.CD_LeadOut,
DataType.ScsiModeSense6 => MediaTagType.SCSI_MODESENSE_6,
DataType.ScsiModeSense10 => MediaTagType.SCSI_MODESENSE_10,
DataType.UsbDescriptors => MediaTagType.USB_Descriptors,
DataType.XboxDmi => MediaTagType.Xbox_DMI,
DataType.XboxPfi => MediaTagType.Xbox_PFI,
DataType.CompactDiscMediaCatalogueNumber => MediaTagType.CD_MCN,
DataType.CompactDiscLeadIn => MediaTagType.CD_LeadIn,
DataType.DvdDiscKeyDecrypted => MediaTagType.DVD_DiscKey_Decrypted,
_ => throw new ArgumentOutOfRangeException()
};
{
DataType.CompactDiscPartialToc => MediaTagType.
CD_TOC,
DataType.CompactDiscSessionInfo =>
MediaTagType.CD_SessionInfo,
DataType.CompactDiscToc => MediaTagType.
CD_FullTOC,
DataType.CompactDiscPma => MediaTagType.CD_PMA,
DataType.CompactDiscAtip => MediaTagType.
CD_ATIP,
DataType.CompactDiscLeadInCdText =>
MediaTagType.CD_TEXT,
DataType.DvdPfi => MediaTagType.DVD_PFI,
DataType.DvdLeadInCmi => MediaTagType.DVD_CMI,
DataType.DvdDiscKey =>
MediaTagType.DVD_DiscKey,
DataType.DvdBca => MediaTagType.DVD_BCA,
DataType.DvdDmi => MediaTagType.DVD_DMI,
DataType.DvdMediaIdentifier => MediaTagType.
DVD_MediaIdentifier,
DataType.DvdMediaKeyBlock => MediaTagType.
DVD_MKB,
DataType.DvdRamDds => MediaTagType.DVDRAM_DDS,
DataType.DvdRamMediumStatus => MediaTagType.
DVDRAM_MediumStatus,
DataType.DvdRamSpareArea => MediaTagType.
DVDRAM_SpareArea,
DataType.DvdRRmd => MediaTagType.DVDR_RMD,
DataType.DvdRPrerecordedInfo => MediaTagType.
DVDR_PreRecordedInfo,
DataType.DvdRMediaIdentifier => MediaTagType.
DVDR_MediaIdentifier,
DataType.DvdRPfi => MediaTagType.DVDR_PFI,
DataType.DvdAdip => MediaTagType.DVD_ADIP,
DataType.HdDvdCpi => MediaTagType.HDDVD_CPI,
DataType.HdDvdMediumStatus => MediaTagType.
HDDVD_MediumStatus,
DataType.DvdDlLayerCapacity => MediaTagType.
DVDDL_LayerCapacity,
DataType.DvdDlMiddleZoneAddress =>
MediaTagType.DVDDL_MiddleZoneAddress,
DataType.DvdDlJumpIntervalSize => MediaTagType.
DVDDL_JumpIntervalSize,
DataType.DvdDlManualLayerJumpLba =>
MediaTagType.DVDDL_ManualLayerJumpLBA,
DataType.BlurayDi => MediaTagType.BD_DI,
DataType.BlurayBca => MediaTagType.BD_BCA,
DataType.BlurayDds => MediaTagType.BD_DDS,
DataType.BlurayCartridgeStatus => MediaTagType.
BD_CartridgeStatus,
DataType.BluraySpareArea => MediaTagType.
BD_SpareArea,
DataType.AacsVolumeIdentifier => MediaTagType.
AACS_VolumeIdentifier,
DataType.AacsSerialNumber => MediaTagType.
AACS_SerialNumber,
DataType.AacsMediaIdentifier => MediaTagType.
AACS_MediaIdentifier,
DataType.AacsMediaKeyBlock => MediaTagType.
AACS_MKB,
DataType.AacsDataKeys => MediaTagType.
AACS_DataKeys,
DataType.AacsLbaExtents => MediaTagType.
AACS_LBAExtents,
DataType.CprmMediaKeyBlock => MediaTagType.
AACS_CPRM_MKB,
DataType.HybridRecognizedLayers =>
MediaTagType.Hybrid_RecognizedLayers,
DataType.ScsiMmcWriteProtection =>
MediaTagType.MMC_WriteProtection,
DataType.ScsiMmcDiscInformation =>
MediaTagType.MMC_DiscInformation,
DataType.ScsiMmcTrackResourcesInformation =>
MediaTagType.MMC_TrackResourcesInformation,
DataType.ScsiMmcPowResourcesInformation =>
MediaTagType.MMC_POWResourcesInformation,
DataType.ScsiInquiry => MediaTagType.
SCSI_INQUIRY,
DataType.ScsiModePage2A => MediaTagType.
SCSI_MODEPAGE_2A,
DataType.AtaIdentify => MediaTagType.
ATA_IDENTIFY,
DataType.AtapiIdentify => MediaTagType.
ATAPI_IDENTIFY,
DataType.PcmciaCis => MediaTagType.PCMCIA_CIS,
DataType.SecureDigitalCid => MediaTagType.
SD_CID,
DataType.SecureDigitalCsd => MediaTagType.
SD_CSD,
DataType.SecureDigitalScr => MediaTagType.
SD_SCR,
DataType.SecureDigitalOcr => MediaTagType.
SD_OCR,
DataType.MultiMediaCardCid => MediaTagType.
MMC_CID,
DataType.MultiMediaCardCsd => MediaTagType.
MMC_CSD,
DataType.MultiMediaCardOcr => MediaTagType.
MMC_OCR,
DataType.MultiMediaCardExtendedCsd =>
MediaTagType.MMC_ExtendedCSD,
DataType.XboxSecuritySector => MediaTagType.
Xbox_SecuritySector,
DataType.FloppyLeadOut => MediaTagType.
Floppy_LeadOut,
DataType.DvdDiscControlBlock => MediaTagType.
DCB,
DataType.CompactDiscFirstTrackPregap =>
MediaTagType.CD_FirstTrackPregap,
DataType.CompactDiscLeadOut => MediaTagType.
CD_LeadOut,
DataType.ScsiModeSense6 => MediaTagType.
SCSI_MODESENSE_6,
DataType.ScsiModeSense10 => MediaTagType.
SCSI_MODESENSE_10,
DataType.UsbDescriptors => MediaTagType.
USB_Descriptors,
DataType.XboxDmi => MediaTagType.Xbox_DMI,
DataType.XboxPfi => MediaTagType.Xbox_PFI,
DataType.CompactDiscMediaCatalogueNumber =>
MediaTagType.CD_MCN,
DataType.CompactDiscLeadIn => MediaTagType.
CD_LeadIn,
DataType.DvdDiscKeyDecrypted => MediaTagType.
DVD_DiscKey_Decrypted,
_ => throw new ArgumentOutOfRangeException()
};
// Converts between Aaru media tag type and image data type
static DataType GetDataTypeForMediaTag(MediaTagType tag) => tag switch
{
MediaTagType.CD_TOC => DataType.CompactDiscPartialToc,
MediaTagType.CD_SessionInfo => DataType.CompactDiscSessionInfo,
MediaTagType.CD_FullTOC => DataType.CompactDiscToc,
MediaTagType.CD_PMA => DataType.CompactDiscPma,
MediaTagType.CD_ATIP => DataType.CompactDiscAtip,
MediaTagType.CD_TEXT => DataType.CompactDiscLeadInCdText,
MediaTagType.DVD_PFI => DataType.DvdPfi,
MediaTagType.DVD_CMI => DataType.DvdLeadInCmi,
MediaTagType.DVD_DiscKey => DataType.DvdDiscKey,
MediaTagType.DVD_BCA => DataType.DvdBca,
MediaTagType.DVD_DMI => DataType.DvdDmi,
MediaTagType.DVD_MediaIdentifier => DataType.DvdMediaIdentifier,
MediaTagType.DVD_MKB => DataType.DvdMediaKeyBlock,
MediaTagType.DVDRAM_DDS => DataType.DvdRamDds,
MediaTagType.DVDRAM_MediumStatus => DataType.DvdRamMediumStatus,
MediaTagType.DVDRAM_SpareArea => DataType.DvdRamSpareArea,
MediaTagType.DVDR_RMD => DataType.DvdRRmd,
MediaTagType.DVDR_PreRecordedInfo => DataType.DvdRPrerecordedInfo,
MediaTagType.DVDR_MediaIdentifier => DataType.DvdRMediaIdentifier,
MediaTagType.DVDR_PFI => DataType.DvdRPfi,
MediaTagType.DVD_ADIP => DataType.DvdAdip,
MediaTagType.HDDVD_CPI => DataType.HdDvdCpi,
MediaTagType.HDDVD_MediumStatus => DataType.HdDvdMediumStatus,
MediaTagType.DVDDL_LayerCapacity => DataType.DvdDlLayerCapacity,
MediaTagType.DVDDL_MiddleZoneAddress => DataType.DvdDlMiddleZoneAddress,
MediaTagType.DVDDL_JumpIntervalSize => DataType.DvdDlJumpIntervalSize,
MediaTagType.DVDDL_ManualLayerJumpLBA => DataType.DvdDlManualLayerJumpLba,
MediaTagType.BD_DI => DataType.BlurayDi,
MediaTagType.BD_BCA => DataType.BlurayBca,
MediaTagType.BD_DDS => DataType.BlurayDds,
MediaTagType.BD_CartridgeStatus => DataType.BlurayCartridgeStatus,
MediaTagType.BD_SpareArea => DataType.BluraySpareArea,
MediaTagType.AACS_VolumeIdentifier => DataType.AacsVolumeIdentifier,
MediaTagType.AACS_SerialNumber => DataType.AacsSerialNumber,
MediaTagType.AACS_MediaIdentifier => DataType.AacsMediaIdentifier,
MediaTagType.AACS_MKB => DataType.AacsMediaKeyBlock,
MediaTagType.AACS_DataKeys => DataType.AacsDataKeys,
MediaTagType.AACS_LBAExtents => DataType.AacsLbaExtents,
MediaTagType.AACS_CPRM_MKB => DataType.CprmMediaKeyBlock,
MediaTagType.Hybrid_RecognizedLayers => DataType.HybridRecognizedLayers,
MediaTagType.MMC_WriteProtection => DataType.ScsiMmcWriteProtection,
MediaTagType.MMC_DiscInformation => DataType.ScsiMmcDiscInformation,
MediaTagType.MMC_TrackResourcesInformation => DataType.ScsiMmcTrackResourcesInformation,
MediaTagType.MMC_POWResourcesInformation => DataType.ScsiMmcPowResourcesInformation,
MediaTagType.SCSI_INQUIRY => DataType.ScsiInquiry,
MediaTagType.SCSI_MODEPAGE_2A => DataType.ScsiModePage2A,
MediaTagType.ATA_IDENTIFY => DataType.AtaIdentify,
MediaTagType.ATAPI_IDENTIFY => DataType.AtapiIdentify,
MediaTagType.PCMCIA_CIS => DataType.PcmciaCis,
MediaTagType.SD_CID => DataType.SecureDigitalCid,
MediaTagType.SD_CSD => DataType.SecureDigitalCsd,
MediaTagType.SD_SCR => DataType.SecureDigitalScr,
MediaTagType.SD_OCR => DataType.SecureDigitalOcr,
MediaTagType.MMC_CID => DataType.MultiMediaCardCid,
MediaTagType.MMC_CSD => DataType.MultiMediaCardCsd,
MediaTagType.MMC_OCR => DataType.MultiMediaCardOcr,
MediaTagType.MMC_ExtendedCSD => DataType.MultiMediaCardExtendedCsd,
MediaTagType.Xbox_SecuritySector => DataType.XboxSecuritySector,
MediaTagType.Floppy_LeadOut => DataType.FloppyLeadOut,
MediaTagType.DCB => DataType.DvdDiscControlBlock,
MediaTagType.CD_FirstTrackPregap => DataType.CompactDiscFirstTrackPregap,
MediaTagType.CD_LeadOut => DataType.CompactDiscLeadOut,
MediaTagType.SCSI_MODESENSE_6 => DataType.ScsiModeSense6,
MediaTagType.SCSI_MODESENSE_10 => DataType.ScsiModeSense10,
MediaTagType.USB_Descriptors => DataType.UsbDescriptors,
MediaTagType.Xbox_DMI => DataType.XboxDmi,
MediaTagType.Xbox_PFI => DataType.XboxPfi,
MediaTagType.CD_MCN => DataType.CompactDiscMediaCatalogueNumber,
MediaTagType.CD_LeadIn => DataType.CompactDiscLeadIn,
MediaTagType.DVD_DiscKey_Decrypted => DataType.DvdDiscKeyDecrypted,
_ => throw new ArgumentOutOfRangeException(nameof(tag), tag, null)
};
{
MediaTagType.CD_TOC => DataType.
CompactDiscPartialToc,
MediaTagType.CD_SessionInfo => DataType.
CompactDiscSessionInfo,
MediaTagType.CD_FullTOC => DataType.CompactDiscToc,
MediaTagType.CD_PMA => DataType.CompactDiscPma,
MediaTagType.CD_ATIP => DataType.CompactDiscAtip,
MediaTagType.CD_TEXT => DataType.
CompactDiscLeadInCdText,
MediaTagType.DVD_PFI => DataType.DvdPfi,
MediaTagType.DVD_CMI => DataType.DvdLeadInCmi,
MediaTagType.DVD_DiscKey => DataType.DvdDiscKey,
MediaTagType.DVD_BCA => DataType.DvdBca,
MediaTagType.DVD_DMI => DataType.DvdDmi,
MediaTagType.DVD_MediaIdentifier => DataType.
DvdMediaIdentifier,
MediaTagType.DVD_MKB => DataType.DvdMediaKeyBlock,
MediaTagType.DVDRAM_DDS => DataType.DvdRamDds,
MediaTagType.DVDRAM_MediumStatus => DataType.
DvdRamMediumStatus,
MediaTagType.DVDRAM_SpareArea => DataType.
DvdRamSpareArea,
MediaTagType.DVDR_RMD => DataType.DvdRRmd,
MediaTagType.DVDR_PreRecordedInfo => DataType.
DvdRPrerecordedInfo,
MediaTagType.DVDR_MediaIdentifier => DataType.
DvdRMediaIdentifier,
MediaTagType.DVDR_PFI => DataType.DvdRPfi,
MediaTagType.DVD_ADIP => DataType.DvdAdip,
MediaTagType.HDDVD_CPI => DataType.HdDvdCpi,
MediaTagType.HDDVD_MediumStatus => DataType.
HdDvdMediumStatus,
MediaTagType.DVDDL_LayerCapacity => DataType.
DvdDlLayerCapacity,
MediaTagType.DVDDL_MiddleZoneAddress => DataType.
DvdDlMiddleZoneAddress,
MediaTagType.DVDDL_JumpIntervalSize => DataType.
DvdDlJumpIntervalSize,
MediaTagType.DVDDL_ManualLayerJumpLBA => DataType.
DvdDlManualLayerJumpLba,
MediaTagType.BD_DI => DataType.BlurayDi,
MediaTagType.BD_BCA => DataType.BlurayBca,
MediaTagType.BD_DDS => DataType.BlurayDds,
MediaTagType.BD_CartridgeStatus => DataType.
BlurayCartridgeStatus,
MediaTagType.BD_SpareArea => DataType.
BluraySpareArea,
MediaTagType.AACS_VolumeIdentifier => DataType.
AacsVolumeIdentifier,
MediaTagType.AACS_SerialNumber => DataType.
AacsSerialNumber,
MediaTagType.AACS_MediaIdentifier => DataType.
AacsMediaIdentifier,
MediaTagType.AACS_MKB => DataType.AacsMediaKeyBlock,
MediaTagType.AACS_DataKeys => DataType.AacsDataKeys,
MediaTagType.AACS_LBAExtents => DataType.
AacsLbaExtents,
MediaTagType.AACS_CPRM_MKB => DataType.
CprmMediaKeyBlock,
MediaTagType.Hybrid_RecognizedLayers => DataType.
HybridRecognizedLayers,
MediaTagType.MMC_WriteProtection => DataType.
ScsiMmcWriteProtection,
MediaTagType.MMC_DiscInformation => DataType.
ScsiMmcDiscInformation,
MediaTagType.MMC_TrackResourcesInformation =>
DataType.ScsiMmcTrackResourcesInformation,
MediaTagType.MMC_POWResourcesInformation =>
DataType.ScsiMmcPowResourcesInformation,
MediaTagType.SCSI_INQUIRY => DataType.ScsiInquiry,
MediaTagType.SCSI_MODEPAGE_2A => DataType.
ScsiModePage2A,
MediaTagType.ATA_IDENTIFY => DataType.AtaIdentify,
MediaTagType.ATAPI_IDENTIFY => DataType.
AtapiIdentify,
MediaTagType.PCMCIA_CIS => DataType.PcmciaCis,
MediaTagType.SD_CID => DataType.SecureDigitalCid,
MediaTagType.SD_CSD => DataType.SecureDigitalCsd,
MediaTagType.SD_SCR => DataType.SecureDigitalScr,
MediaTagType.SD_OCR => DataType.SecureDigitalOcr,
MediaTagType.MMC_CID => DataType.MultiMediaCardCid,
MediaTagType.MMC_CSD => DataType.MultiMediaCardCsd,
MediaTagType.MMC_OCR => DataType.MultiMediaCardOcr,
MediaTagType.MMC_ExtendedCSD => DataType.
MultiMediaCardExtendedCsd,
MediaTagType.Xbox_SecuritySector => DataType.
XboxSecuritySector,
MediaTagType.Floppy_LeadOut => DataType.
FloppyLeadOut,
MediaTagType.DCB => DataType.DvdDiscControlBlock,
MediaTagType.CD_FirstTrackPregap => DataType.
CompactDiscFirstTrackPregap,
MediaTagType.CD_LeadOut => DataType.
CompactDiscLeadOut,
MediaTagType.SCSI_MODESENSE_6 => DataType.
ScsiModeSense6,
MediaTagType.SCSI_MODESENSE_10 => DataType.
ScsiModeSense10,
MediaTagType.USB_Descriptors => DataType.
UsbDescriptors,
MediaTagType.Xbox_DMI => DataType.XboxDmi,
MediaTagType.Xbox_PFI => DataType.XboxPfi,
MediaTagType.CD_MCN => DataType.
CompactDiscMediaCatalogueNumber,
MediaTagType.CD_LeadIn =>
DataType.CompactDiscLeadIn,
MediaTagType.DVD_DiscKey_Decrypted => DataType.
DvdDiscKeyDecrypted,
_ => throw new ArgumentOutOfRangeException(
nameof(tag), tag, null)
};
}

View File

@@ -38,6 +38,8 @@ namespace Aaru.DiscImages;
public sealed partial class AaruFormat
{
#region IWritableOpticalImage Members
/// <inheritdoc />
public bool Identify(IFilter imageFilter)
{
@@ -53,4 +55,6 @@ public sealed partial class AaruFormat
return _header.identifier is DIC_MAGIC or AARU_MAGIC && _header.imageMajorVersion <= AARUFMT_VERSION;
}
#endregion
}

View File

@@ -44,6 +44,8 @@ namespace Aaru.DiscImages;
public sealed partial class AaruFormat
{
#region IWritableOpticalImage Members
/// <inheritdoc />
public OpticalImageCapabilities OpticalCapabilities => OpticalImageCapabilities.CanStoreAudioTracks |
OpticalImageCapabilities.CanStoreDataTracks |
@@ -60,33 +62,47 @@ public sealed partial class AaruFormat
OpticalImageCapabilities.CanStoreNotCdTracks |
OpticalImageCapabilities.CanStoreIndexes |
OpticalImageCapabilities.CanStoreHiddenTracks;
/// <inheritdoc />
public ImageInfo Info => _imageInfo;
/// <inheritdoc />
public string Name => Localization.AaruFormat_Name;
/// <inheritdoc />
public Guid Id => new("49360069-1784-4A2F-B723-0C844D610B0A");
/// <inheritdoc />
public string Format => "Aaru";
/// <inheritdoc />
public string Author => Authors.NataliaPortillo;
/// <inheritdoc />
public List<Partition> Partitions { get; private set; }
/// <inheritdoc />
public List<Track> Tracks { get; private set; }
/// <inheritdoc />
public List<Session> Sessions { get; private set; }
/// <inheritdoc />
public List<DumpHardware> DumpHardware { get; private set; }
/// <inheritdoc />
public Metadata AaruMetadata { get; private set; }
/// <inheritdoc />
public IEnumerable<MediaTagType> SupportedMediaTags => Enum.GetValues(typeof(MediaTagType)).Cast<MediaTagType>();
/// <inheritdoc />
public IEnumerable<SectorTagType> SupportedSectorTags =>
Enum.GetValues(typeof(SectorTagType)).Cast<SectorTagType>();
/// <inheritdoc />
public IEnumerable<MediaType> SupportedMediaTypes => Enum.GetValues(typeof(MediaType)).Cast<MediaType>();
/// <inheritdoc />
public IEnumerable<(string name, Type type, string description, object @default)> SupportedOptions => new[]
{
@@ -98,20 +114,23 @@ public sealed partial class AaruFormat
("md5", typeof(bool), Localization.Calculate_and_store_MD5_of_image_user_data, false),
("sha1", typeof(bool), Localization.Calculate_and_store_SHA1_of_image_user_data, false),
("sha256", typeof(bool), Localization.Calculate_and_store_SHA256_of_image_user_data, false),
("spamsum", typeof(bool), Localization.Calculate_and_store_SpamSum_of_image_user_data, false),
("deduplicate", typeof(bool),
Localization.Store_only_unique_sectors_This_consumes_more_memory_and_is_slower_but_its_enabled_by_default,
true),
("spamsum", typeof(bool), Localization.Calculate_and_store_SpamSum_of_image_user_data, false), ("deduplicate",
typeof(bool),
Localization.
Store_only_unique_sectors_This_consumes_more_memory_and_is_slower_but_its_enabled_by_default,
true),
("compress", typeof(bool), Localization.Compress_user_data_blocks_Other_blocks_will_always_be_compressed,
(object)true)
};
/// <inheritdoc />
public IEnumerable<string> KnownExtensions => new[]
{
".dicf", ".aaru", ".aaruformat", ".aaruf", ".aif"
};
public IEnumerable<string> KnownExtensions => new[] { ".dicf", ".aaru", ".aaruformat", ".aaruf", ".aif" };
/// <inheritdoc />
public bool IsWriting { get; private set; }
/// <inheritdoc />
public string ErrorMessage { get; private set; }
#endregion
}

View File

@@ -63,6 +63,8 @@ namespace Aaru.DiscImages;
public sealed partial class AaruFormat
{
#region IWritableOpticalImage Members
/// <inheritdoc />
public ErrorNumber Open(IFilter imageFilter)
{
@@ -168,7 +170,7 @@ public sealed partial class AaruFormat
_imageInfo.ImageSize = 0;
bool foundUserDataDdt = false;
var foundUserDataDdt = false;
_mediaTags = new Dictionary<MediaTagType, byte[]>();
List<CompactDiscIndexEntry> compactDiscIndexes = null;
@@ -228,7 +230,7 @@ public sealed partial class AaruFormat
// Decompress media tag
if(blockHeader.compression is CompressionType.Lzma
or CompressionType.LzmaClauniaSubchannelTransform)
or CompressionType.LzmaClauniaSubchannelTransform)
{
if(blockHeader.compression == CompressionType.LzmaClauniaSubchannelTransform &&
entry.dataType != DataType.CdSectorSubchannel)
@@ -243,10 +245,10 @@ public sealed partial class AaruFormat
var decompressStopwatch = new Stopwatch();
decompressStopwatch.Start();
byte[] compressedTag = new byte[blockHeader.cmpLength - LZMA_PROPERTIES_LENGTH];
byte[] lzmaProperties = new byte[LZMA_PROPERTIES_LENGTH];
var compressedTag = new byte[blockHeader.cmpLength - LZMA_PROPERTIES_LENGTH];
var lzmaProperties = new byte[LZMA_PROPERTIES_LENGTH];
_imageStream.EnsureRead(lzmaProperties, 0, LZMA_PROPERTIES_LENGTH);
_imageStream.EnsureRead(compressedTag, 0, compressedTag.Length);
_imageStream.EnsureRead(compressedTag, 0, compressedTag.Length);
data = new byte[blockHeader.length];
int decompressedLength = LZMA.DecodeBuffer(compressedTag, data, lzmaProperties);
@@ -487,13 +489,13 @@ public sealed partial class AaruFormat
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Decompressing_DDT);
var ddtStopwatch = new Stopwatch();
ddtStopwatch.Start();
byte[] compressedDdt = new byte[ddtHeader.cmpLength - LZMA_PROPERTIES_LENGTH];
byte[] lzmaProperties = new byte[LZMA_PROPERTIES_LENGTH];
var compressedDdt = new byte[ddtHeader.cmpLength - LZMA_PROPERTIES_LENGTH];
var lzmaProperties = new byte[LZMA_PROPERTIES_LENGTH];
_imageStream.EnsureRead(lzmaProperties, 0, LZMA_PROPERTIES_LENGTH);
_imageStream.EnsureRead(compressedDdt, 0, compressedDdt.Length);
byte[] decompressedDdt = new byte[ddtHeader.length];
_imageStream.EnsureRead(compressedDdt, 0, compressedDdt.Length);
var decompressedDdt = new byte[ddtHeader.length];
ulong decompressedLength =
var decompressedLength =
(ulong)LZMA.DecodeBuffer(compressedDdt, decompressedDdt, lzmaProperties);
if(decompressedLength != ddtHeader.length)
@@ -531,8 +533,9 @@ public sealed partial class AaruFormat
default:
AaruConsole.
ErrorWriteLine(string.
Format(Localization.Found_unsupported_compression_algorithm_0,
(ushort)ddtHeader.compression));
Format(
Localization.Found_unsupported_compression_algorithm_0,
(ushort)ddtHeader.compression));
return ErrorNumber.NotSupported;
}
@@ -543,7 +546,7 @@ public sealed partial class AaruFormat
case DataType.CdSectorPrefixCorrected:
case DataType.CdSectorSuffixCorrected:
{
byte[] decompressedDdt = new byte[ddtHeader.length];
var decompressedDdt = new byte[ddtHeader.length];
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Memory_snapshot_0_bytes,
GC.GetTotalMemory(false));
@@ -555,12 +558,12 @@ public sealed partial class AaruFormat
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Decompressing_DDT);
var ddtStopwatch = new Stopwatch();
ddtStopwatch.Start();
byte[] compressedDdt = new byte[ddtHeader.cmpLength - LZMA_PROPERTIES_LENGTH];
byte[] lzmaProperties = new byte[LZMA_PROPERTIES_LENGTH];
var compressedDdt = new byte[ddtHeader.cmpLength - LZMA_PROPERTIES_LENGTH];
var lzmaProperties = new byte[LZMA_PROPERTIES_LENGTH];
_imageStream.EnsureRead(lzmaProperties, 0, LZMA_PROPERTIES_LENGTH);
_imageStream.EnsureRead(compressedDdt, 0, compressedDdt.Length);
_imageStream.EnsureRead(compressedDdt, 0, compressedDdt.Length);
ulong decompressedLength =
var decompressedLength =
(ulong)LZMA.DecodeBuffer(compressedDdt, decompressedDdt, lzmaProperties);
ddtStopwatch.Stop();
@@ -595,8 +598,9 @@ public sealed partial class AaruFormat
default:
AaruConsole.
ErrorWriteLine(string.
Format(Localization.Found_unsupported_compression_algorithm_0,
(ushort)ddtHeader.compression));
Format(
Localization.Found_unsupported_compression_algorithm_0,
(ushort)ddtHeader.compression));
return ErrorNumber.NotSupported;
}
@@ -668,7 +672,7 @@ public sealed partial class AaruFormat
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Found_metadata_block_at_position_0,
entry.offset);
byte[] metadata = new byte[metadataBlock.blockSize];
var metadata = new byte[metadataBlock.blockSize];
_imageStream.Position = (long)entry.offset;
_imageStream.EnsureRead(metadata, 0, metadata.Length);
@@ -917,23 +921,23 @@ public sealed partial class AaruFormat
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Memory_snapshot_0_bytes,
GC.GetTotalMemory(false));
byte[] cicmBytes = new byte[cicmBlock.length];
var cicmBytes = new byte[cicmBlock.length];
_imageStream.EnsureRead(cicmBytes, 0, cicmBytes.Length);
var cicmMs = new MemoryStream(cicmBytes);
// The converter to AaruMetadata basically overcomes this (should?)
#pragma warning disable IL2026
#pragma warning disable IL2026
var cicmXs = new XmlSerializer(typeof(CICMMetadataType));
#pragma warning restore IL2026
#pragma warning restore IL2026
try
{
var sr = new StreamReader(cicmMs);
// The converter to AaruMetadata basically overcomes this (should?)
#pragma warning disable IL2026
#pragma warning disable IL2026
AaruMetadata = (CICMMetadataType)cicmXs.Deserialize(sr);
#pragma warning restore IL2026
#pragma warning restore IL2026
sr.Close();
}
catch(XmlException ex)
@@ -967,7 +971,7 @@ public sealed partial class AaruFormat
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Memory_snapshot_0_bytes,
GC.GetTotalMemory(false));
byte[] jsonBytes = new byte[aaruMetadataBlock.length];
var jsonBytes = new byte[aaruMetadataBlock.length];
_imageStream.EnsureRead(jsonBytes, 0, jsonBytes.Length);
try
@@ -1145,7 +1149,7 @@ public sealed partial class AaruFormat
AaruConsole.DebugWriteLine(MODULE_NAME,
Localization.Found_tape_partition_block_at_position_0, entry.offset);
byte[] tapePartitionBytes = new byte[partitionHeader.length];
var tapePartitionBytes = new byte[partitionHeader.length];
_imageStream.EnsureRead(tapePartitionBytes, 0, tapePartitionBytes.Length);
Span<TapePartitionEntry> tapePartitions =
@@ -1154,12 +1158,14 @@ public sealed partial class AaruFormat
TapePartitions = new List<TapePartition>();
foreach(TapePartitionEntry tapePartition in tapePartitions)
{
TapePartitions.Add(new TapePartition
{
FirstBlock = tapePartition.FirstBlock,
LastBlock = tapePartition.LastBlock,
Number = tapePartition.Number
});
}
IsTape = true;
@@ -1178,12 +1184,13 @@ public sealed partial class AaruFormat
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Found_tape_file_block_at_position_0,
entry.offset);
byte[] tapeFileBytes = new byte[fileHeader.length];
var tapeFileBytes = new byte[fileHeader.length];
_imageStream.EnsureRead(tapeFileBytes, 0, tapeFileBytes.Length);
Span<TapeFileEntry> tapeFiles = MemoryMarshal.Cast<byte, TapeFileEntry>(tapeFileBytes);
Files = new List<TapeFile>();
foreach(TapeFileEntry file in tapeFiles)
{
Files.Add(new TapeFile
{
FirstBlock = file.FirstBlock,
@@ -1191,6 +1198,7 @@ public sealed partial class AaruFormat
Partition = file.Partition,
File = file.File
});
}
IsTape = true;
@@ -1298,12 +1306,12 @@ public sealed partial class AaruFormat
{
if(Tracks != null)
{
bool leadOutFixed = false;
bool sessionPregapFixed = false;
var leadOutFixed = false;
var sessionPregapFixed = false;
if(_mediaTags.TryGetValue(MediaTagType.CD_FullTOC, out byte[] fullToc))
{
byte[] tmp = new byte[fullToc.Length + 2];
var tmp = new byte[fullToc.Length + 2];
Array.Copy(fullToc, 0, tmp, 2, fullToc.Length);
tmp[0] = (byte)(fullToc.Length >> 8);
tmp[1] = (byte)(fullToc.Length & 0xFF);
@@ -1354,8 +1362,8 @@ public sealed partial class AaruFormat
phour = trk.PHOUR;
}
int lastSector = (phour * 3600 * 75) + (pmin * 60 * 75) + (psec * 75) + pframe - 150;
leadOutStarts?.Add(trk.SessionNumber, lastSector + 1);
int lastSector = phour * 3600 * 75 + pmin * 60 * 75 + psec * 75 + pframe - 150;
leadOutStarts?.Add(trk.SessionNumber, lastSector + 1);
}
foreach(KeyValuePair<int, long> leadOuts in leadOutStarts)
@@ -1377,6 +1385,7 @@ public sealed partial class AaruFormat
}
if(_header.imageMajorVersion <= 1)
{
foreach(Track track in Tracks)
{
if(track.Sequence <= 1)
@@ -1398,13 +1407,16 @@ public sealed partial class AaruFormat
sessionPregapFixed = true;
}
}
if(leadOutFixed)
AaruConsole.ErrorWriteLine(Localization.This_image_has_a_corrupted_track_list_convert_will_fix_it);
if(sessionPregapFixed)
{
AaruConsole.ErrorWriteLine(Localization.
This_image_has_a_corrupted_track_list_a_best_effort_has_been_tried_but_may_require_manual_editing_or_redump);
}
}
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Memory_snapshot_0_bytes,
@@ -1431,9 +1443,7 @@ public sealed partial class AaruFormat
_trackFlags = new Dictionary<byte, byte>
{
{
1, (byte)CdFlags.DataTrack
}
{ 1, (byte)CdFlags.DataTrack }
};
_trackIsrcs = new Dictionary<byte, string>();
@@ -1444,7 +1454,8 @@ public sealed partial class AaruFormat
Sessions = new List<Session>();
for(int i = 1; i <= Tracks.Max(t => t.Session); i++)
for(var i = 1; i <= Tracks.Max(t => t.Session); i++)
{
Sessions.Add(new Session
{
Sequence = (ushort)i,
@@ -1453,6 +1464,7 @@ public sealed partial class AaruFormat
StartSector = Tracks.Where(t => t.Session == i).Min(t => t.StartSector),
EndSector = Tracks.Where(t => t.Session == i).Max(t => t.EndSector)
});
}
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Memory_snapshot_0_bytes,
GC.GetTotalMemory(false));
@@ -1519,8 +1531,10 @@ public sealed partial class AaruFormat
trk.BytesPerSector = sector.Length;
trk.RawBytesPerSector =
(_sectorPrefix != null && _sectorSuffix != null) ||
(_sectorPrefixDdt != null && _sectorSuffixDdt != null) ? 2352 : sector.Length;
_sectorPrefix != null && _sectorSuffix != null ||
_sectorPrefixDdt != null && _sectorSuffixDdt != null
? 2352
: sector.Length;
if(_sectorSubchannel == null)
continue;
@@ -1539,6 +1553,7 @@ public sealed partial class AaruFormat
GC.GetTotalMemory(false));
if(compactDiscIndexes != null)
{
foreach(CompactDiscIndexEntry compactDiscIndex in compactDiscIndexes.OrderBy(i => i.Track).
ThenBy(i => i.Index))
{
@@ -1549,6 +1564,7 @@ public sealed partial class AaruFormat
track.Indexes[compactDiscIndex.Index] = compactDiscIndex.Lba;
}
}
}
else
{
@@ -1569,13 +1585,20 @@ public sealed partial class AaruFormat
return ErrorNumber.NoError;
if(_imageInfo.MediaType is MediaType.CD or MediaType.CDDA or MediaType.CDG or MediaType.CDEG or MediaType.CDI
or MediaType.CDROM or MediaType.CDROMXA or MediaType.CDPLUS or MediaType.CDMO or MediaType.CDR
or MediaType.CDRW or MediaType.CDMRW or MediaType.VCD or MediaType.SVCD or MediaType.PCD or MediaType.DTSCD
or MediaType.CDMIDI or MediaType.CDV or MediaType.CDIREADY or MediaType.FMTOWNS or MediaType.PS1CD
or MediaType.PS2CD or MediaType.MEGACD or MediaType.SATURNCD or MediaType.GDROM or MediaType.GDR
or MediaType.MilCD or MediaType.SuperCDROM2 or MediaType.JaguarCD or MediaType.ThreeDO or MediaType.PCFX
or MediaType.NeoGeoCD or MediaType.CDTV or MediaType.CD32 or MediaType.Playdia or MediaType.Pippin
or MediaType.VideoNow or MediaType.VideoNowColor or MediaType.VideoNowXp or MediaType.CVD)
or MediaType.CDROM or MediaType.CDROMXA or MediaType.CDPLUS or MediaType.CDMO
or MediaType.CDR
or MediaType.CDRW or MediaType.CDMRW or MediaType.VCD or MediaType.SVCD or MediaType.PCD
or MediaType.DTSCD
or MediaType.CDMIDI or MediaType.CDV or MediaType.CDIREADY or MediaType.FMTOWNS
or MediaType.PS1CD
or MediaType.PS2CD or MediaType.MEGACD or MediaType.SATURNCD or MediaType.GDROM
or MediaType.GDR
or MediaType.MilCD or MediaType.SuperCDROM2 or MediaType.JaguarCD or MediaType.ThreeDO
or MediaType.PCFX
or MediaType.NeoGeoCD or MediaType.CDTV or MediaType.CD32 or MediaType.Playdia
or MediaType.Pippin
or MediaType.VideoNow or MediaType.VideoNowColor or MediaType.VideoNowXp
or MediaType.CVD)
return ErrorNumber.NoError;
{
@@ -1606,7 +1629,7 @@ public sealed partial class AaruFormat
return ErrorNumber.OutOfRange;
ulong ddtEntry = GetDdtEntry(sectorAddress);
uint offsetMask = (uint)((1 << _shift) - 1);
var offsetMask = (uint)((1 << _shift) - 1);
ulong offset = ddtEntry & offsetMask;
ulong blockOffset = ddtEntry >> _shift;
@@ -1651,9 +1674,9 @@ public sealed partial class AaruFormat
break;
case CompressionType.Lzma:
byte[] compressedBlock = new byte[blockHeader.cmpLength - LZMA_PROPERTIES_LENGTH];
byte[] lzmaProperties = new byte[LZMA_PROPERTIES_LENGTH];
_imageStream.EnsureRead(lzmaProperties, 0, LZMA_PROPERTIES_LENGTH);
var compressedBlock = new byte[blockHeader.cmpLength - LZMA_PROPERTIES_LENGTH];
var lzmaProperties = new byte[LZMA_PROPERTIES_LENGTH];
_imageStream.EnsureRead(lzmaProperties, 0, LZMA_PROPERTIES_LENGTH);
_imageStream.EnsureRead(compressedBlock, 0, compressedBlock.Length);
block = new byte[blockHeader.length];
decompressedLength = (ulong)LZMA.DecodeBuffer(compressedBlock, block, lzmaProperties);
@@ -1672,7 +1695,7 @@ public sealed partial class AaruFormat
break;
case CompressionType.Flac:
byte[] flacBlock = new byte[blockHeader.cmpLength];
var flacBlock = new byte[blockHeader.cmpLength];
_imageStream.EnsureRead(flacBlock, 0, flacBlock.Length);
block = new byte[blockHeader.length];
decompressedLength = (ulong)FLAC.DecodeBuffer(flacBlock, block);
@@ -1690,7 +1713,8 @@ public sealed partial class AaruFormat
GC.GetTotalMemory(false));
break;
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
// Check if cache needs to be emptied
@@ -1729,7 +1753,8 @@ public sealed partial class AaruFormat
Track trk = Tracks.FirstOrDefault(t => t.Sequence == track);
return trk?.Sequence != track ? ErrorNumber.SectorNotFound
return trk?.Sequence != track
? ErrorNumber.SectorNotFound
: ReadSector(trk.StartSector + sectorAddress, out buffer);
}
@@ -1743,7 +1768,8 @@ public sealed partial class AaruFormat
Track trk = Tracks.FirstOrDefault(t => t.Sequence == track);
return trk?.Sequence != track ? ErrorNumber.SectorNotFound
return trk?.Sequence != track
? ErrorNumber.SectorNotFound
: ReadSectorTag(trk.StartSector + sectorAddress, tag, out buffer);
}
@@ -1812,15 +1838,13 @@ public sealed partial class AaruFormat
case SectorTagType.DvdSectorNumber:
case SectorTagType.DvdSectorIed:
case SectorTagType.DvdSectorEdc:
case SectorTagType.DvdTitleKeyDecrypted: break;
case SectorTagType.DvdTitleKeyDecrypted:
break;
case SectorTagType.CdTrackFlags:
if(!_trackFlags.TryGetValue((byte)sectorAddress, out byte flags))
return ErrorNumber.NoData;
buffer = new[]
{
flags
};
buffer = new[] { flags };
return ErrorNumber.NoError;
case SectorTagType.CdTrackIsrc:
@@ -1830,7 +1854,8 @@ public sealed partial class AaruFormat
buffer = Encoding.UTF8.GetBytes(isrc);
return ErrorNumber.NoError;
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
switch(trk.Type)
@@ -1858,7 +1883,8 @@ public sealed partial class AaruFormat
break;
}
case SectorTagType.CdSectorSubHeader: return ErrorNumber.NotSupported;
case SectorTagType.CdSectorSubHeader:
return ErrorNumber.NotSupported;
case SectorTagType.CdSectorEcc:
{
sectorOffset = 12;
@@ -1909,7 +1935,8 @@ public sealed partial class AaruFormat
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
break;
@@ -1953,7 +1980,8 @@ public sealed partial class AaruFormat
case SectorTagType.CdSectorEcc:
case SectorTagType.CdSectorEccP:
case SectorTagType.CdSectorEccQ:
case SectorTagType.CdSectorEdc: return ErrorNumber.NotSupported;
case SectorTagType.CdSectorEdc:
return ErrorNumber.NotSupported;
case SectorTagType.CdSectorSubchannel:
{
sectorOffset = 0;
@@ -1964,7 +1992,8 @@ public sealed partial class AaruFormat
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
break;
@@ -1984,7 +2013,8 @@ public sealed partial class AaruFormat
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
break;
@@ -1993,6 +2023,7 @@ public sealed partial class AaruFormat
case TrackType.Data:
{
if(_imageInfo.MediaType == MediaType.DVDROM)
{
switch(tag)
{
case SectorTagType.DvdSectorCmi:
@@ -2058,15 +2089,18 @@ public sealed partial class AaruFormat
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
}
else
return ErrorNumber.NotSupported;
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
}
else
@@ -2085,9 +2119,11 @@ public sealed partial class AaruFormat
return ErrorNumber.NoError;
}
for(int i = 0; i < length; i++)
Array.Copy(dataSource, (long)((sectorAddress * (sectorOffset + sectorSize + sectorSkip)) + sectorOffset),
for(var i = 0; i < length; i++)
{
Array.Copy(dataSource, (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip) + sectorOffset),
buffer, i * sectorSize, sectorSize);
}
return ErrorNumber.NoError;
}
@@ -2105,12 +2141,13 @@ public sealed partial class AaruFormat
if(trk?.Sequence != track)
return ErrorNumber.SectorNotFound;
return trk.StartSector + sectorAddress + length > trk.EndSector + 1 ? ErrorNumber.OutOfRange
return trk.StartSector + sectorAddress + length > trk.EndSector + 1
? ErrorNumber.OutOfRange
: ReadSectors(trk.StartSector + sectorAddress, length, out buffer);
}
/// <inheritdoc />
public ErrorNumber ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag,
public ErrorNumber ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag,
out byte[] buffer)
{
buffer = null;
@@ -2306,7 +2343,7 @@ public sealed partial class AaruFormat
else if(_mode2Subheaders != null)
{
Array.Copy(_mode2Subheaders, (int)sectorAddress * 8, buffer, 16, 8);
Array.Copy(data, 0, buffer, 24, 2328);
Array.Copy(data, 0, buffer, 24, 2328);
}
else
Array.Copy(data, 0, buffer, 16, 2336);
@@ -2323,7 +2360,8 @@ public sealed partial class AaruFormat
case MediaType.AppleSonySS:
case MediaType.AppleSonyDS:
case MediaType.AppleWidget:
case MediaType.PriamDataTower: return ReadSectorsLong(sectorAddress, 1, out buffer);
case MediaType.PriamDataTower:
return ReadSectorsLong(sectorAddress, 1, out buffer);
}
break;
@@ -2342,7 +2380,8 @@ public sealed partial class AaruFormat
Track trk = Tracks.FirstOrDefault(t => t.Sequence == track);
return trk?.Sequence != track ? ErrorNumber.SectorNotFound
return trk?.Sequence != track
? ErrorNumber.SectorNotFound
: ReadSectorLong(trk.StartSector + sectorAddress, out buffer);
}
@@ -2373,7 +2412,8 @@ public sealed partial class AaruFormat
{
// These types only contain user data
case TrackType.Audio:
case TrackType.Data: return ReadSectors(sectorAddress, length, out buffer);
case TrackType.Data:
return ReadSectors(sectorAddress, length, out buffer);
// Join prefix (sync, header) with user data with suffix (edc, ecc p, ecc q)
case TrackType.CdMode1:
@@ -2505,7 +2545,7 @@ public sealed partial class AaruFormat
for(uint i = 0; i < length; i++)
{
Array.Copy(_sectorSubchannel, (int)((sectorAddress + i) * tagSize), buffer,
(int)((i * sectorSize) + 512), tagSize);
(int)(i * sectorSize + 512), tagSize);
Array.Copy(data, (int)((sectorAddress + i) * 512), buffer, (int)(i * 512), 512);
}
@@ -2541,4 +2581,6 @@ public sealed partial class AaruFormat
/// <inheritdoc />
public List<Track> GetSessionTracks(ushort session) => Tracks.Where(t => t.Sequence == session).ToList();
#endregion
}

View File

@@ -38,6 +38,8 @@ namespace Aaru.DiscImages;
public sealed partial class AaruFormat
{
#region Nested type: AaruHeader
/// <summary>Header, at start of file</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode)]
struct AaruHeader
@@ -65,6 +67,131 @@ public sealed partial class AaruFormat
public long lastWrittenTime;
}
#endregion
#region Nested type: AaruMetadataJsonBlock
/// <summary>Aaru Metadata JSON block</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AaruMetadataJsonBlock
{
/// <summary>Identifier, <see cref="BlockType.AaruMetadataJsonBlock" /></summary>
public BlockType identifier;
public uint length;
}
#endregion
#region Nested type: BlockHeader
/// <summary>Block header, precedes block data</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct BlockHeader
{
/// <summary>Identifier, <see cref="BlockType.DataBlock" /></summary>
public BlockType identifier;
/// <summary>Type of data contained by this block</summary>
public DataType type;
/// <summary>Compression algorithm used to compress the block</summary>
public CompressionType compression;
/// <summary>Size in bytes of each sector contained in this block</summary>
public uint sectorSize;
/// <summary>Compressed length for the block</summary>
public uint cmpLength;
/// <summary>Uncompressed length for the block</summary>
public uint length;
/// <summary>CRC64-ECMA of the compressed block</summary>
public ulong cmpCrc64;
/// <summary>CRC64-ECMA of the uncompressed block</summary>
public ulong crc64;
}
#endregion
#region Nested type: ChecksumEntry
/// <summary>Checksum entry, followed by checksum data itself</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct ChecksumEntry
{
/// <summary>Checksum algorithm</summary>
public ChecksumAlgorithm type;
/// <summary>Length in bytes of checksum that follows this structure</summary>
public uint length;
}
#endregion
#region Nested type: ChecksumHeader
/// <summary>
/// Checksum block, contains a checksum of all user data sectors (except for optical discs that is 2352 bytes raw
/// sector if available
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct ChecksumHeader
{
/// <summary>Identifier, <see cref="BlockType.ChecksumBlock" /></summary>
public BlockType identifier;
/// <summary>Length in bytes of the block</summary>
public uint length;
/// <summary>How many checksums follow</summary>
public byte entries;
}
#endregion
#region Nested type: CicmMetadataBlock
/// <summary>CICM Metadata XML block</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct CicmMetadataBlock
{
/// <summary>Identifier, <see cref="BlockType.CicmBlock" /></summary>
public readonly BlockType identifier;
public readonly uint length;
}
#endregion
#region Nested type: CompactDiscIndexEntry
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct CompactDiscIndexEntry
{
/// <summary>How many entries follow this header</summary>
public ushort Track;
/// <summary>Size of the whole block, not including this header, in bytes</summary>
public ushort Index;
/// <summary>CRC64-ECMA of the block</summary>
public int Lba;
}
#endregion
#region Nested type: CompactDiscIndexesHeader
/// <summary>
/// Compact Disc track indexes block, contains a cache of all Compact Disc indexes to not need to interpret
/// subchannel
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct CompactDiscIndexesHeader
{
/// <summary>Identifier, <see cref="BlockType.CompactDiscIndexesBlock" /></summary>
public BlockType identifier;
/// <summary>How many entries follow this header</summary>
public ushort entries;
/// <summary>Size of the whole block, not including this header, in bytes</summary>
public readonly ulong length;
/// <summary>CRC64-ECMA of the block</summary>
public ulong crc64;
}
#endregion
#region Nested type: DdtHeader
/// <summary>Header for a deduplication table. Table follows it</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct DdtHeader
@@ -89,30 +216,71 @@ public sealed partial class AaruFormat
public readonly ulong crc64;
}
/// <summary>Header for the index, followed by entries</summary>
#endregion
#region Nested type: DumpHardwareEntry
/// <summary>Dump hardware entry, contains length of strings that follow, in the same order as the length, this structure</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct IndexHeader
struct DumpHardwareEntry
{
/// <summary>Identifier, <see cref="BlockType.Index" /></summary>
/// <summary>Length of UTF-8 manufacturer string</summary>
public uint manufacturerLength;
/// <summary>Length of UTF-8 model string</summary>
public uint modelLength;
/// <summary>Length of UTF-8 revision string</summary>
public uint revisionLength;
/// <summary>Length of UTF-8 firmware version string</summary>
public uint firmwareLength;
/// <summary>Length of UTF-8 serial string</summary>
public uint serialLength;
/// <summary>Length of UTF-8 software name string</summary>
public uint softwareNameLength;
/// <summary>Length of UTF-8 software version string</summary>
public uint softwareVersionLength;
/// <summary>Length of UTF-8 software operating system string</summary>
public uint softwareOperatingSystemLength;
/// <summary>How many extents are after the strings</summary>
public uint extents;
}
#endregion
#region Nested type: DumpHardwareHeader
/// <summary>Dump hardware block, contains a list of hardware used to dump the media on this image</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct DumpHardwareHeader
{
/// <summary>Identifier, <see cref="BlockType.DumpHardwareBlock" /></summary>
public BlockType identifier;
/// <summary>How many entries follow this header</summary>
public ushort entries;
/// <summary>CRC64-ECMA of the index</summary>
/// <summary>Size of the whole block, not including this header, in bytes</summary>
public uint length;
/// <summary>CRC64-ECMA of the block</summary>
public ulong crc64;
}
/// <summary>Header for the index, followed by entries</summary>
#endregion
#region Nested type: GeometryBlock
/// <summary>Geometry block, contains physical geometry information</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct IndexHeader2
struct GeometryBlock
{
/// <summary>Identifier, <see cref="BlockType.Index2" /></summary>
/// <summary>Identifier, <see cref="BlockType.GeometryBlock" /></summary>
public BlockType identifier;
/// <summary>How many entries follow this header</summary>
public ulong entries;
/// <summary>CRC64-ECMA of the index</summary>
public ulong crc64;
public uint cylinders;
public uint heads;
public uint sectorsPerTrack;
}
#endregion
#region Nested type: IndexEntry
/// <summary>Index entry</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct IndexEntry
@@ -125,39 +293,42 @@ public sealed partial class AaruFormat
public ulong offset;
}
/// <summary>Block header, precedes block data</summary>
#endregion
#region Nested type: IndexHeader
/// <summary>Header for the index, followed by entries</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct BlockHeader
struct IndexHeader
{
/// <summary>Identifier, <see cref="BlockType.DataBlock" /></summary>
/// <summary>Identifier, <see cref="BlockType.Index" /></summary>
public BlockType identifier;
/// <summary>Type of data contained by this block</summary>
public DataType type;
/// <summary>Compression algorithm used to compress the block</summary>
public CompressionType compression;
/// <summary>Size in bytes of each sector contained in this block</summary>
public uint sectorSize;
/// <summary>Compressed length for the block</summary>
public uint cmpLength;
/// <summary>Uncompressed length for the block</summary>
public uint length;
/// <summary>CRC64-ECMA of the compressed block</summary>
public ulong cmpCrc64;
/// <summary>CRC64-ECMA of the uncompressed block</summary>
/// <summary>How many entries follow this header</summary>
public ushort entries;
/// <summary>CRC64-ECMA of the index</summary>
public ulong crc64;
}
/// <summary>Geometry block, contains physical geometry information</summary>
#endregion
#region Nested type: IndexHeader2
/// <summary>Header for the index, followed by entries</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct GeometryBlock
struct IndexHeader2
{
/// <summary>Identifier, <see cref="BlockType.GeometryBlock" /></summary>
/// <summary>Identifier, <see cref="BlockType.Index2" /></summary>
public BlockType identifier;
public uint cylinders;
public uint heads;
public uint sectorsPerTrack;
/// <summary>How many entries follow this header</summary>
public ulong entries;
/// <summary>CRC64-ECMA of the index</summary>
public ulong crc64;
}
#endregion
#region Nested type: MetadataBlock
/// <summary>Metadata block, contains metadata</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct MetadataBlock
@@ -220,18 +391,80 @@ public sealed partial class AaruFormat
public uint driveFirmwareRevisionLength;
}
/// <summary>Contains list of optical disc tracks</summary>
#endregion
#region Nested type: TapeFileEntry
/// <summary>Tape file entry</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct TracksHeader
struct TapeFileEntry
{
/// <summary>Identifier, <see cref="BlockType.TracksBlock" /></summary>
/// <summary>File number</summary>
public uint File;
/// <summary>Partition number</summary>
public readonly byte Partition;
/// <summary>First block, inclusive, of the file</summary>
public ulong FirstBlock;
/// <summary>Last block, inclusive, of the file</summary>
public ulong LastBlock;
}
#endregion
#region Nested type: TapeFileHeader
/// <summary>Tape file block, contains a list of all files in a tape</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct TapeFileHeader
{
/// <summary>Identifier, <see cref="BlockType.TapeFileBlock" /></summary>
public BlockType identifier;
/// <summary>How many entries follow this header</summary>
public ushort entries;
public uint entries;
/// <summary>Size of the whole block, not including this header, in bytes</summary>
public ulong length;
/// <summary>CRC64-ECMA of the block</summary>
public ulong crc64;
}
#endregion
#region Nested type: TapePartitionEntry
/// <summary>Tape partition entry</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct TapePartitionEntry
{
/// <summary>Partition number</summary>
public byte Number;
/// <summary>First block, inclusive, of the partition</summary>
public ulong FirstBlock;
/// <summary>Last block, inclusive, of the partition</summary>
public ulong LastBlock;
}
#endregion
#region Nested type: TapePartitionHeader
/// <summary>Tape partition block, contains a list of all partitions in a tape</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct TapePartitionHeader
{
/// <summary>Identifier, <see cref="BlockType.TapePartitionBlock" /></summary>
public BlockType identifier;
/// <summary>How many entries follow this header</summary>
public byte entries;
/// <summary>Size of the whole block, not including this header, in bytes</summary>
public ulong length;
/// <summary>CRC64-ECMA of the block</summary>
public ulong crc64;
}
#endregion
#region Nested type: TrackEntry
/// <summary>Optical disc track</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
struct TrackEntry
@@ -255,166 +488,21 @@ public sealed partial class AaruFormat
public byte flags;
}
/// <summary>CICM Metadata XML block</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct CicmMetadataBlock
{
/// <summary>Identifier, <see cref="BlockType.CicmBlock" /></summary>
public readonly BlockType identifier;
public readonly uint length;
}
#endregion
/// <summary>Aaru Metadata JSON block</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AaruMetadataJsonBlock
{
/// <summary>Identifier, <see cref="BlockType.AaruMetadataJsonBlock" /></summary>
public BlockType identifier;
public uint length;
}
#region Nested type: TracksHeader
/// <summary>Dump hardware block, contains a list of hardware used to dump the media on this image</summary>
/// <summary>Contains list of optical disc tracks</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct DumpHardwareHeader
struct TracksHeader
{
/// <summary>Identifier, <see cref="BlockType.DumpHardwareBlock" /></summary>
/// <summary>Identifier, <see cref="BlockType.TracksBlock" /></summary>
public BlockType identifier;
/// <summary>How many entries follow this header</summary>
public ushort entries;
/// <summary>Size of the whole block, not including this header, in bytes</summary>
public uint length;
/// <summary>CRC64-ECMA of the block</summary>
public ulong crc64;
}
/// <summary>Dump hardware entry, contains length of strings that follow, in the same order as the length, this structure</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct DumpHardwareEntry
{
/// <summary>Length of UTF-8 manufacturer string</summary>
public uint manufacturerLength;
/// <summary>Length of UTF-8 model string</summary>
public uint modelLength;
/// <summary>Length of UTF-8 revision string</summary>
public uint revisionLength;
/// <summary>Length of UTF-8 firmware version string</summary>
public uint firmwareLength;
/// <summary>Length of UTF-8 serial string</summary>
public uint serialLength;
/// <summary>Length of UTF-8 software name string</summary>
public uint softwareNameLength;
/// <summary>Length of UTF-8 software version string</summary>
public uint softwareVersionLength;
/// <summary>Length of UTF-8 software operating system string</summary>
public uint softwareOperatingSystemLength;
/// <summary>How many extents are after the strings</summary>
public uint extents;
}
/// <summary>
/// Checksum block, contains a checksum of all user data sectors (except for optical discs that is 2352 bytes raw
/// sector if available
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct ChecksumHeader
{
/// <summary>Identifier, <see cref="BlockType.ChecksumBlock" /></summary>
public BlockType identifier;
/// <summary>Length in bytes of the block</summary>
public uint length;
/// <summary>How many checksums follow</summary>
public byte entries;
}
/// <summary>Checksum entry, followed by checksum data itself</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct ChecksumEntry
{
/// <summary>Checksum algorithm</summary>
public ChecksumAlgorithm type;
/// <summary>Length in bytes of checksum that follows this structure</summary>
public uint length;
}
/// <summary>Tape file block, contains a list of all files in a tape</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct TapeFileHeader
{
/// <summary>Identifier, <see cref="BlockType.TapeFileBlock" /></summary>
public BlockType identifier;
/// <summary>How many entries follow this header</summary>
public uint entries;
/// <summary>Size of the whole block, not including this header, in bytes</summary>
public ulong length;
/// <summary>CRC64-ECMA of the block</summary>
public ulong crc64;
}
/// <summary>Tape file entry</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct TapeFileEntry
{
/// <summary>File number</summary>
public uint File;
/// <summary>Partition number</summary>
public readonly byte Partition;
/// <summary>First block, inclusive, of the file</summary>
public ulong FirstBlock;
/// <summary>Last block, inclusive, of the file</summary>
public ulong LastBlock;
}
/// <summary>Tape partition block, contains a list of all partitions in a tape</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct TapePartitionHeader
{
/// <summary>Identifier, <see cref="BlockType.TapePartitionBlock" /></summary>
public BlockType identifier;
/// <summary>How many entries follow this header</summary>
public byte entries;
/// <summary>Size of the whole block, not including this header, in bytes</summary>
public ulong length;
/// <summary>CRC64-ECMA of the block</summary>
public ulong crc64;
}
/// <summary>Tape partition entry</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct TapePartitionEntry
{
/// <summary>Partition number</summary>
public byte Number;
/// <summary>First block, inclusive, of the partition</summary>
public ulong FirstBlock;
/// <summary>Last block, inclusive, of the partition</summary>
public ulong LastBlock;
}
/// <summary>
/// Compact Disc track indexes block, contains a cache of all Compact Disc indexes to not need to interpret
/// subchannel
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct CompactDiscIndexesHeader
{
/// <summary>Identifier, <see cref="BlockType.CompactDiscIndexesBlock" /></summary>
public BlockType identifier;
/// <summary>How many entries follow this header</summary>
public ushort entries;
/// <summary>Size of the whole block, not including this header, in bytes</summary>
public readonly ulong length;
/// <summary>CRC64-ECMA of the block</summary>
public ulong crc64;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct CompactDiscIndexEntry
{
/// <summary>How many entries follow this header</summary>
public ushort Track;
/// <summary>Size of the whole block, not including this header, in bytes</summary>
public ushort Index;
/// <summary>CRC64-ECMA of the block</summary>
public int Lba;
}
#endregion
}

View File

@@ -38,10 +38,14 @@ namespace Aaru.DiscImages;
public sealed partial class AaruFormat
{
#region IWritableTapeImage Members
/// <inheritdoc />
public List<TapeFile> Files { get; private set; }
/// <inheritdoc />
public List<TapePartition> TapePartitions { get; private set; }
/// <inheritdoc />
public bool IsTape { get; private set; }
@@ -81,4 +85,6 @@ public sealed partial class AaruFormat
return IsTape = true;
}
#endregion
}

View File

@@ -41,6 +41,8 @@ namespace Aaru.DiscImages;
public sealed partial class AaruFormat
{
#region IVerifiableImage Members
/// <inheritdoc />
public bool? VerifyMediaImage()
{
@@ -209,6 +211,10 @@ public sealed partial class AaruFormat
return true;
}
#endregion
#region IWritableOpticalImage Members
/// <inheritdoc />
public bool? VerifySector(ulong sectorAddress)
{
@@ -221,7 +227,7 @@ public sealed partial class AaruFormat
}
/// <inheritdoc />
public bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas,
public bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
@@ -241,12 +247,12 @@ public sealed partial class AaruFormat
if(errno != ErrorNumber.NoError)
return null;
int bps = (int)(buffer.Length / length);
byte[] sector = new byte[bps];
var bps = (int)(buffer.Length / length);
var sector = new byte[bps];
failingLbas = new List<ulong>();
unknownLbas = new List<ulong>();
for(int i = 0; i < length; i++)
for(var i = 0; i < length; i++)
{
Array.Copy(buffer, i * bps, sector, 0, bps);
bool? sectorStatus = CdChecksums.CheckCdSector(sector);
@@ -271,7 +277,7 @@ public sealed partial class AaruFormat
}
/// <inheritdoc />
public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
{
// Right now only CompactDisc sectors are verifiable
@@ -294,10 +300,10 @@ public sealed partial class AaruFormat
if(errno != ErrorNumber.NoError)
return null;
int bps = (int)(buffer.Length / length);
byte[] sector = new byte[bps];
var bps = (int)(buffer.Length / length);
var sector = new byte[bps];
for(int i = 0; i < length; i++)
for(var i = 0; i < length; i++)
{
Array.Copy(buffer, i * bps, sector, 0, bps);
bool? sectorStatus = CdChecksums.CheckCdSector(sector);
@@ -320,4 +326,6 @@ public sealed partial class AaruFormat
return failingLbas.Count <= 0;
}
#endregion
}

File diff suppressed because it is too large Load Diff

View File

@@ -42,6 +42,7 @@ namespace Aaru.DiscImages;
/// <summary>Implements reading and writing Alcohol 120% disk images</summary>
public sealed partial class Alcohol120 : IWritableOpticalImage
{
const string MODULE_NAME = "Alcohol 120% plugin";
Footer _alcFooter;
IFilter _alcImage;
Dictionary<int, Session> _alcSessions;
@@ -84,6 +85,4 @@ public sealed partial class Alcohol120 : IWritableOpticalImage
DriveSerialNumber = null,
DriveFirmwareRevision = null
};
const string MODULE_NAME = "Alcohol 120% plugin";
}

View File

@@ -36,24 +36,47 @@ namespace Aaru.DiscImages;
public sealed partial class Alcohol120
{
#region Nested type: MediumType
[SuppressMessage("ReSharper", "InconsistentNaming")]
enum MediumType : ushort
{
CD = 0x00, CDR = 0x01, CDRW = 0x02,
DVD = 0x10, DVDR = 0x12
CD = 0x00,
CDR = 0x01,
CDRW = 0x02,
DVD = 0x10,
DVDR = 0x12
}
#endregion
#region Nested type: SubchannelMode
enum SubchannelMode : byte
{
None = 0x00,
Interleaved = 0x08
}
#endregion
#region Nested type: TrackMode
[SuppressMessage("ReSharper", "InconsistentNaming")]
enum TrackMode : byte
{
NoData = 0x00, DVD = 0x02, Audio = 0xA9,
AudioAlt = 0xE9, Mode1 = 0xAA, Mode1Alt = 0xEA,
Mode2 = 0xAB, Mode2F1 = 0xEC, Mode2F2 = 0xED,
Mode2F1Alt = 0xAC, Mode2F2Alt = 0xAD
NoData = 0x00,
DVD = 0x02,
Audio = 0xA9,
AudioAlt = 0xE9,
Mode1 = 0xAA,
Mode1Alt = 0xEA,
Mode2 = 0xAB,
Mode2F1 = 0xEC,
Mode2F2 = 0xED,
Mode2F1Alt = 0xAC,
Mode2F2Alt = 0xAD
}
enum SubchannelMode : byte
{
None = 0x00, Interleaved = 0x08
}
#endregion
}

View File

@@ -44,14 +44,20 @@ public sealed partial class Alcohol120
case TrackMode.Mode1:
case TrackMode.Mode1Alt:
case TrackMode.Mode2F1:
case TrackMode.Mode2F1Alt: return 2048;
case TrackMode.Mode2F1Alt:
return 2048;
case TrackMode.Mode2F2:
case TrackMode.Mode2F2Alt: return 2324;
case TrackMode.Mode2: return 2336;
case TrackMode.Mode2F2Alt:
return 2324;
case TrackMode.Mode2:
return 2336;
case TrackMode.Audio:
case TrackMode.AudioAlt: return 2352;
case TrackMode.DVD: return 2048;
default: return 0;
case TrackMode.AudioAlt:
return 2352;
case TrackMode.DVD:
return 2048;
default:
return 0;
}
}
@@ -60,27 +66,33 @@ public sealed partial class Alcohol120
switch(trackType)
{
case TrackMode.Mode1:
case TrackMode.Mode1Alt: return TrackType.CdMode1;
case TrackMode.Mode1Alt:
return TrackType.CdMode1;
case TrackMode.Mode2F1:
case TrackMode.Mode2F1Alt: return TrackType.CdMode2Form1;
case TrackMode.Mode2F1Alt:
return TrackType.CdMode2Form1;
case TrackMode.Mode2F2:
case TrackMode.Mode2F2Alt: return TrackType.CdMode2Form2;
case TrackMode.Mode2: return TrackType.CdMode2Formless;
case TrackMode.Mode2F2Alt:
return TrackType.CdMode2Form2;
case TrackMode.Mode2:
return TrackType.CdMode2Formless;
case TrackMode.Audio:
case TrackMode.AudioAlt: return TrackType.Audio;
default: return TrackType.Data;
case TrackMode.AudioAlt:
return TrackType.Audio;
default:
return TrackType.Data;
}
}
static MediaType MediumTypeToMediaType(MediumType discType) => discType switch
{
MediumType.CD => MediaType.CD,
MediumType.CDR => MediaType.CDR,
MediumType.CDRW => MediaType.CDRW,
MediumType.DVD => MediaType.DVDROM,
MediumType.DVDR => MediaType.DVDR,
_ => MediaType.Unknown
};
{
MediumType.CD => MediaType.CD,
MediumType.CDR => MediaType.CDR,
MediumType.CDRW => MediaType.CDRW,
MediumType.DVD => MediaType.DVDROM,
MediumType.DVDR => MediaType.DVDR,
_ => MediaType.Unknown
};
static MediumType MediaTypeToMediumType(MediaType type)
{
@@ -119,30 +131,35 @@ public sealed partial class Alcohol120
case MediaType.VideoNow:
case MediaType.VideoNowColor:
case MediaType.VideoNowXp:
case MediaType.CVD: return MediumType.CD;
case MediaType.CDR: return MediumType.CDR;
case MediaType.CVD:
return MediumType.CD;
case MediaType.CDR:
return MediumType.CDR;
case MediaType.CDRW:
case MediaType.CDMRW: return MediumType.CDRW;
case MediaType.CDMRW:
return MediumType.CDRW;
case MediaType.DVDR:
case MediaType.DVDRW:
case MediaType.DVDPR:
case MediaType.DVDRDL:
case MediaType.DVDRWDL:
case MediaType.DVDPRDL:
case MediaType.DVDPRWDL: return MediumType.DVDR;
default: return MediumType.DVD;
case MediaType.DVDPRWDL:
return MediumType.DVDR;
default:
return MediumType.DVD;
}
}
static TrackMode TrackTypeToTrackMode(TrackType type) => type switch
{
TrackType.Audio => TrackMode.Audio,
TrackType.CdMode1 => TrackMode.Mode1,
TrackType.CdMode2Formless => TrackMode.Mode2,
TrackType.CdMode2Form1 => TrackMode.Mode2F1,
TrackType.CdMode2Form2 => TrackMode.Mode2F2,
_ => TrackMode.DVD
};
{
TrackType.Audio => TrackMode.Audio,
TrackType.CdMode1 => TrackMode.Mode1,
TrackType.CdMode2Formless => TrackMode.Mode2,
TrackType.CdMode2Form1 => TrackMode.Mode2F1,
TrackType.CdMode2Form2 => TrackMode.Mode2F2,
_ => TrackMode.DVD
};
static (byte minute, byte second, byte frame) LbaToMsf(ulong sector) =>
((byte)((sector + 150) / 75 / 60), (byte)((sector + 150) / 75 % 60), (byte)((sector + 150) % 75));

View File

@@ -39,6 +39,8 @@ namespace Aaru.DiscImages;
public sealed partial class Alcohol120
{
#region IWritableOpticalImage Members
/// <inheritdoc />
public bool Identify(IFilter imageFilter)
{
@@ -48,10 +50,12 @@ public sealed partial class Alcohol120
if(stream.Length < 88)
return false;
byte[] hdr = new byte[88];
var hdr = new byte[88];
stream.EnsureRead(hdr, 0, 88);
Header header = Marshal.ByteArrayToStructureLittleEndian<Header>(hdr);
return header.signature.SequenceEqual(_alcoholSignature) && header.version[0] <= MAXIMUM_SUPPORTED_VERSION;
}
#endregion
}

View File

@@ -43,6 +43,8 @@ namespace Aaru.DiscImages;
public sealed partial class Alcohol120
{
#region IWritableOpticalImage Members
/// <inheritdoc />
public OpticalImageCapabilities OpticalCapabilities => OpticalImageCapabilities.CanStoreAudioTracks |
OpticalImageCapabilities.CanStoreDataTracks |
@@ -56,12 +58,16 @@ public sealed partial class Alcohol120
OpticalImageCapabilities.CanStoreRawData |
OpticalImageCapabilities.CanStoreCookedData |
OpticalImageCapabilities.CanStoreMultipleTracks;
/// <inheritdoc />
public ImageInfo Info => _imageInfo;
/// <inheritdoc />
public string Name => Localization.Alcohol120_Name;
/// <inheritdoc />
public Guid Id => new("A78FBEBA-0307-4915-BDE3-B8A3B57F843F");
/// <inheritdoc />
public string Author => Authors.NataliaPortillo;
@@ -153,6 +159,7 @@ public sealed partial class Alcohol120
/// <inheritdoc />
public List<DumpHardware> DumpHardware => null;
/// <inheritdoc />
public Metadata AaruMetadata => null;
@@ -161,40 +168,46 @@ public sealed partial class Alcohol120
{
MediaTagType.CD_FullTOC, MediaTagType.DVD_BCA, MediaTagType.DVD_DMI, MediaTagType.DVD_PFI
};
/// <inheritdoc />
public IEnumerable<SectorTagType> SupportedSectorTags => new[]
{
SectorTagType.CdSectorEcc, SectorTagType.CdSectorEccP, SectorTagType.CdSectorEccQ, SectorTagType.CdSectorEdc,
SectorTagType.CdSectorHeader, SectorTagType.CdSectorSubHeader, SectorTagType.CdSectorSync,
SectorTagType.CdTrackFlags, SectorTagType.CdSectorSubchannel
SectorTagType.CdSectorEcc, SectorTagType.CdSectorEccP, SectorTagType.CdSectorEccQ,
SectorTagType.CdSectorEdc, SectorTagType.CdSectorHeader, SectorTagType.CdSectorSubHeader,
SectorTagType.CdSectorSync, SectorTagType.CdTrackFlags, SectorTagType.CdSectorSubchannel
};
/// <inheritdoc />
public IEnumerable<MediaType> SupportedMediaTypes => new[]
{
MediaType.BDR, MediaType.BDRE, MediaType.BDREXL, MediaType.BDROM, MediaType.UHDBD, MediaType.BDRXL,
MediaType.CBHD, MediaType.CD, MediaType.CDDA, MediaType.CDEG, MediaType.CDG, MediaType.CDI, MediaType.CDMIDI,
MediaType.CDMRW, MediaType.CDPLUS, MediaType.CDR, MediaType.CDROM, MediaType.CDROMXA, MediaType.CDRW,
MediaType.CDV, MediaType.DVDDownload, MediaType.DVDPR, MediaType.DVDPRDL, MediaType.DVDPRW, MediaType.DVDPRWDL,
MediaType.DVDR, MediaType.DVDRAM, MediaType.DVDRDL, MediaType.DVDROM, MediaType.DVDRW, MediaType.DVDRWDL,
MediaType.EVD, MediaType.FDDVD, MediaType.DTSCD, MediaType.FVD, MediaType.HDDVDR, MediaType.HDDVDRAM,
MediaType.HDDVDRDL, MediaType.HDDVDROM, MediaType.HDDVDRW, MediaType.HDDVDRWDL, MediaType.HDVMD, MediaType.HVD,
MediaType.JaguarCD, MediaType.MEGACD, MediaType.PS1CD, MediaType.PS2CD, MediaType.PS2DVD, MediaType.PS3BD,
MediaType.PS3DVD, MediaType.PS4BD, MediaType.PS5BD, MediaType.SuperCDROM2, MediaType.SVCD, MediaType.SVOD,
MediaType.SATURNCD, MediaType.ThreeDO, MediaType.UDO, MediaType.UDO2, MediaType.UDO2_WORM, MediaType.UMD,
MediaType.VCD, MediaType.VCDHD, MediaType.NeoGeoCD, MediaType.PCFX, MediaType.CDTV, MediaType.CD32,
MediaType.Nuon, MediaType.Playdia, MediaType.Pippin, MediaType.FMTOWNS, MediaType.MilCD, MediaType.VideoNow,
MediaType.VideoNowColor, MediaType.VideoNowXp, MediaType.CVD, MediaType.PCD
MediaType.CBHD, MediaType.CD, MediaType.CDDA, MediaType.CDEG, MediaType.CDG, MediaType.CDI,
MediaType.CDMIDI, MediaType.CDMRW, MediaType.CDPLUS, MediaType.CDR, MediaType.CDROM, MediaType.CDROMXA,
MediaType.CDRW, MediaType.CDV, MediaType.DVDDownload, MediaType.DVDPR, MediaType.DVDPRDL, MediaType.DVDPRW,
MediaType.DVDPRWDL, MediaType.DVDR, MediaType.DVDRAM, MediaType.DVDRDL, MediaType.DVDROM, MediaType.DVDRW,
MediaType.DVDRWDL, MediaType.EVD, MediaType.FDDVD, MediaType.DTSCD, MediaType.FVD, MediaType.HDDVDR,
MediaType.HDDVDRAM, MediaType.HDDVDRDL, MediaType.HDDVDROM, MediaType.HDDVDRW, MediaType.HDDVDRWDL,
MediaType.HDVMD, MediaType.HVD, MediaType.JaguarCD, MediaType.MEGACD, MediaType.PS1CD, MediaType.PS2CD,
MediaType.PS2DVD, MediaType.PS3BD, MediaType.PS3DVD, MediaType.PS4BD, MediaType.PS5BD,
MediaType.SuperCDROM2, MediaType.SVCD, MediaType.SVOD, MediaType.SATURNCD, MediaType.ThreeDO, MediaType.UDO,
MediaType.UDO2, MediaType.UDO2_WORM, MediaType.UMD, MediaType.VCD, MediaType.VCDHD, MediaType.NeoGeoCD,
MediaType.PCFX, MediaType.CDTV, MediaType.CD32, MediaType.Nuon, MediaType.Playdia, MediaType.Pippin,
MediaType.FMTOWNS, MediaType.MilCD, MediaType.VideoNow, MediaType.VideoNowColor, MediaType.VideoNowXp,
MediaType.CVD, MediaType.PCD
};
/// <inheritdoc />
public IEnumerable<(string name, Type type, string description, object @default)> SupportedOptions =>
Array.Empty<(string name, Type type, string description, object @default)>();
/// <inheritdoc />
public IEnumerable<string> KnownExtensions => new[]
{
".mds"
};
public IEnumerable<string> KnownExtensions => new[] { ".mds" };
/// <inheritdoc />
public bool IsWriting { get; private set; }
/// <inheritdoc />
public string ErrorMessage { get; private set; }
#endregion
}

View File

@@ -48,6 +48,8 @@ namespace Aaru.DiscImages;
public sealed partial class Alcohol120
{
#region IWritableOpticalImage Members
/// <inheritdoc />
public ErrorNumber Open(IFilter imageFilter)
{
@@ -58,7 +60,7 @@ public sealed partial class Alcohol120
return ErrorNumber.InvalidArgument;
_isDvd = false;
byte[] hdr = new byte[88];
var hdr = new byte[88];
stream.EnsureRead(hdr, 0, 88);
_header = Marshal.ByteArrayToStructureLittleEndian<Header>(hdr);
@@ -68,33 +70,41 @@ public sealed partial class Alcohol120
AaruConsole.DebugWriteLine(MODULE_NAME, "header.version = {0}.{1}", _header.version[0],
_header.version[1]);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.type = {0}", _header.type);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.type = {0}", _header.type);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.sessions = {0}", _header.sessions);
for(int i = 0; i < _header.unknown1.Length; i++)
for(var i = 0; i < _header.unknown1.Length; i++)
{
AaruConsole.DebugWriteLine(MODULE_NAME, "header.unknown1[{1}] = 0x{0:X4}", _header.unknown1[i],
i);
}
AaruConsole.DebugWriteLine(MODULE_NAME, "header.bcaLength = {0}", _header.bcaLength);
for(int i = 0; i < _header.unknown2.Length; i++)
for(var i = 0; i < _header.unknown2.Length; i++)
{
AaruConsole.DebugWriteLine(MODULE_NAME, "header.unknown2[{1}] = 0x{0:X8}", _header.unknown2[i],
i);
}
AaruConsole.DebugWriteLine(MODULE_NAME, "header.bcaOffset = {0}", _header.bcaOffset);
for(int i = 0; i < _header.unknown3.Length; i++)
for(var i = 0; i < _header.unknown3.Length; i++)
{
AaruConsole.DebugWriteLine(MODULE_NAME, "header.unknown3[{1}] = 0x{0:X8}", _header.unknown3[i],
i);
}
AaruConsole.DebugWriteLine(MODULE_NAME, "header.structuresOffset = {0}", _header.structuresOffset);
for(int i = 0; i < _header.unknown4.Length; i++)
for(var i = 0; i < _header.unknown4.Length; i++)
{
AaruConsole.DebugWriteLine(MODULE_NAME, "header.unknown4[{1}] = 0x{0:X8}", _header.unknown4[i],
i);
}
AaruConsole.DebugWriteLine(MODULE_NAME, "header.sessionOffset = {0}", _header.sessionOffset);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.dpmOffset = {0}", _header.dpmOffset);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.dpmOffset = {0}", _header.dpmOffset);
if(_header.version[0] > MAXIMUM_SUPPORTED_VERSION)
return ErrorNumber.NotSupported;
@@ -102,9 +112,9 @@ public sealed partial class Alcohol120
stream.Seek(_header.sessionOffset, SeekOrigin.Begin);
_alcSessions = new Dictionary<int, Session>();
for(int i = 0; i < _header.sessions; i++)
for(var i = 0; i < _header.sessions; i++)
{
byte[] sesHdr = new byte[24];
var sesHdr = new byte[24];
stream.EnsureRead(sesHdr, 0, 24);
Session session = Marshal.SpanToStructureLittleEndian<Session>(sesHdr);
@@ -133,7 +143,7 @@ public sealed partial class Alcohol120
}
long footerOff = 0;
bool oldIncorrectImage = false;
var oldIncorrectImage = false;
_alcTracks = new Dictionary<int, Track>();
_alcToc = new Dictionary<int, Dictionary<int, Track>>();
@@ -144,9 +154,9 @@ public sealed partial class Alcohol120
stream.Seek(session.trackOffset, SeekOrigin.Begin);
Dictionary<int, Track> sesToc = new();
for(int i = 0; i < session.allBlocks; i++)
for(var i = 0; i < session.allBlocks; i++)
{
byte[] trkHdr = new byte[80];
var trkHdr = new byte[80];
stream.EnsureRead(trkHdr, 0, 80);
Track track = Marshal.ByteArrayToStructureLittleEndian<Track>(trkHdr);
@@ -250,10 +260,11 @@ public sealed partial class Alcohol120
_alcTrackExtras = new Dictionary<int, TrackExtra>();
foreach(Track track in _alcTracks.Values)
{
if(track.extraOffset > 0 &&
!_isDvd)
{
byte[] extHdr = new byte[8];
var extHdr = new byte[8];
stream.Seek(track.extraOffset, SeekOrigin.Begin);
stream.EnsureRead(extHdr, 0, 8);
TrackExtra extra = Marshal.SpanToStructureLittleEndian<TrackExtra>(extHdr);
@@ -281,33 +292,36 @@ public sealed partial class Alcohol120
_alcTrackExtras.Add(track.point, extra);
}
}
if(footerOff > 0)
{
byte[] footer = new byte[16];
var footer = new byte[16];
stream.Seek(footerOff, SeekOrigin.Begin);
stream.EnsureRead(footer, 0, 16);
_alcFooter = Marshal.SpanToStructureLittleEndian<Footer>(footer);
AaruConsole.DebugWriteLine(MODULE_NAME, "footer.filenameOffset = {0}", _alcFooter.filenameOffset);
AaruConsole.DebugWriteLine(MODULE_NAME, "footer.widechar = {0}", _alcFooter.widechar);
AaruConsole.DebugWriteLine(MODULE_NAME, "footer.widechar = {0}", _alcFooter.widechar);
AaruConsole.DebugWriteLine(MODULE_NAME, "footer.unknown1 = 0x{0:X8}", _alcFooter.unknown1);
AaruConsole.DebugWriteLine(MODULE_NAME, "footer.unknown2 = 0x{0:X8}", _alcFooter.unknown2);
}
string alcFile = "*.mdf";
var alcFile = "*.mdf";
if(_alcFooter.filenameOffset > 0)
{
stream.Seek(_alcFooter.filenameOffset, SeekOrigin.Begin);
byte[] filename = _header.dpmOffset == 0 ? new byte[stream.Length - stream.Position]
: new byte[_header.dpmOffset - stream.Position];
byte[] filename = _header.dpmOffset == 0
? new byte[stream.Length - stream.Position]
: new byte[_header.dpmOffset - stream.Position];
stream.EnsureRead(filename, 0, filename.Length);
alcFile = _alcFooter.widechar == 1 ? StringHandlers.CToString(filename, Encoding.Unicode, true)
alcFile = _alcFooter.widechar == 1
? StringHandlers.CToString(filename, Encoding.Unicode, true)
: StringHandlers.CToString(filename, Encoding.Default);
AaruConsole.DebugWriteLine(MODULE_NAME, "footer.filename = {0}", alcFile);
@@ -332,6 +346,7 @@ public sealed partial class Alcohol120
int readBytes = stream.EnsureRead(_bca, 0, _bca.Length);
if(readBytes == _bca.Length)
{
switch(_header.type)
{
case MediumType.DVD:
@@ -340,6 +355,7 @@ public sealed partial class Alcohol120
break;
}
}
}
_imageInfo.MediaType = MediumTypeToMediaType(_header.type);
@@ -379,14 +395,14 @@ public sealed partial class Alcohol120
// TODO: Second layer
if(_header.structuresOffset > 0)
{
byte[] structures = new byte[4100];
var structures = new byte[4100];
stream.Seek(_header.structuresOffset, SeekOrigin.Begin);
stream.EnsureRead(structures, 0, 4100);
_dmi = new byte[2052];
_pfi = new byte[2052];
// TODO: CMI
Array.Copy(structures, 4, _dmi, 4, 2048);
Array.Copy(structures, 4, _dmi, 4, 2048);
Array.Copy(structures, 0x804, _pfi, 4, 2048);
_pfi[0] = 0x08;
@@ -401,29 +417,35 @@ public sealed partial class Alcohol120
if(pfi0.HasValue)
{
_imageInfo.MediaType = pfi0.Value.DiskCategory switch
{
DiskCategory.DVDPR => MediaType.DVDPR,
DiskCategory.DVDPRDL => MediaType.DVDPRDL,
DiskCategory.DVDPRW => MediaType.DVDPRW,
DiskCategory.DVDPRWDL => MediaType.DVDPRWDL,
DiskCategory.DVDR => pfi0.Value.PartVersion >= 6 ? MediaType.DVDRDL : MediaType.DVDR,
DiskCategory.DVDRAM => MediaType.DVDRAM,
DiskCategory.DVDRW => pfi0.Value.PartVersion >= 15 ? MediaType.DVDRWDL : MediaType.DVDRW,
DiskCategory.HDDVDR => MediaType.HDDVDR,
DiskCategory.HDDVDRAM => MediaType.HDDVDRAM,
DiskCategory.HDDVDROM => MediaType.HDDVDROM,
DiskCategory.HDDVDRW => MediaType.HDDVDRW,
DiskCategory.Nintendo => pfi0.Value.DiscSize == DVDSize.Eighty ? MediaType.GOD : MediaType.WOD,
DiskCategory.UMD => MediaType.UMD,
_ => MediaType.DVDROM
};
{
DiskCategory.DVDPR => MediaType.DVDPR,
DiskCategory.DVDPRDL => MediaType.DVDPRDL,
DiskCategory.DVDPRW => MediaType.DVDPRW,
DiskCategory.DVDPRWDL => MediaType.DVDPRWDL,
DiskCategory.DVDR => pfi0.Value.PartVersion >= 6
? MediaType.DVDRDL
: MediaType.DVDR,
DiskCategory.DVDRAM => MediaType.DVDRAM,
DiskCategory.DVDRW => pfi0.Value.PartVersion >= 15
? MediaType.DVDRWDL
: MediaType.DVDRW,
DiskCategory.HDDVDR => MediaType.HDDVDR,
DiskCategory.HDDVDRAM => MediaType.HDDVDRAM,
DiskCategory.HDDVDROM => MediaType.HDDVDROM,
DiskCategory.HDDVDRW => MediaType.HDDVDRW,
DiskCategory.Nintendo => pfi0.Value.DiscSize == DVDSize.Eighty
? MediaType.GOD
: MediaType.WOD,
DiskCategory.UMD => MediaType.UMD,
_ => MediaType.DVDROM
};
if(DMI.IsXbox(_dmi))
_imageInfo.MediaType = MediaType.XGD;
else if(DMI.IsXbox360(_dmi))
_imageInfo.MediaType = MediaType.XGD2;
byte[] tmp = new byte[2048];
var tmp = new byte[2048];
Array.Copy(_dmi, 4, tmp, 0, 2048);
_dmi = tmp;
tmp = new byte[2048];
@@ -437,11 +459,11 @@ public sealed partial class Alcohol120
}
else if(_header.type == MediumType.CD)
{
bool data = false;
bool mode2 = false;
bool firstAudio = false;
bool firstData = false;
bool audio = false;
var data = false;
var mode2 = false;
var firstAudio = false;
var firstData = false;
var audio = false;
foreach(Track alcoholTrack in _alcTracks.Values)
{
@@ -480,7 +502,7 @@ public sealed partial class Alcohol120
Sessions.Count > 1 &&
mode2)
_imageInfo.MediaType = MediaType.CDPLUS;
else if((firstData && audio) || mode2)
else if(firstData && audio || mode2)
_imageInfo.MediaType = MediaType.CDROMXA;
else if(!audio)
_imageInfo.MediaType = MediaType.CDROM;
@@ -598,7 +620,7 @@ public sealed partial class Alcohol120
foreach(Partition partition in Partitions)
{
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Partition_sequence_0, partition.Sequence);
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Partition_sequence_0, partition.Sequence);
AaruConsole.DebugWriteLine(MODULE_NAME, "\t" + Localization.Partition_name_0, partition.Name);
AaruConsole.DebugWriteLine(MODULE_NAME, "\t" + Localization.Partition_description_0,
@@ -646,10 +668,7 @@ public sealed partial class Alcohol120
byte lastSession = 0;
var tocMs = new MemoryStream();
tocMs.Write(new byte[]
{
0, 0
}, 0, 2); // Reserved for TOC session numbers
tocMs.Write(new byte[] { 0, 0 }, 0, 2); // Reserved for TOC session numbers
foreach(KeyValuePair<int, Dictionary<int, Track>> sessionToc in _alcToc)
{
@@ -691,8 +710,10 @@ public sealed partial class Alcohol120
AaruConsole.VerboseWriteLine(Localization.Alcohol_120_image_describes_a_disc_of_type_0, _imageInfo.MediaType);
if(oldIncorrectImage)
{
AaruConsole.WriteLine(Localization.
Incorrect_Alcohol_120_image_created_by_an_old_version_of_Aaru_Convert_image_to_correct_it);
}
return ErrorNumber.NoError;
}
@@ -724,7 +745,8 @@ public sealed partial class Alcohol120
return buffer != null ? ErrorNumber.NoError : ErrorNumber.NoData;
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
}
@@ -749,7 +771,9 @@ public sealed partial class Alcohol120
buffer = null;
foreach(KeyValuePair<uint, ulong> kvp in _offsetMap)
{
if(sectorAddress >= kvp.Value)
{
foreach(Track track in _alcTracks.Values)
{
if(track.point != kvp.Key ||
@@ -761,6 +785,8 @@ public sealed partial class Alcohol120
return ReadSectors(sectorAddress - kvp.Value, length, kvp.Key, out buffer);
}
}
}
return ErrorNumber.SectorNotFound;
}
@@ -771,7 +797,9 @@ public sealed partial class Alcohol120
buffer = null;
foreach(KeyValuePair<uint, ulong> kvp in _offsetMap)
{
if(sectorAddress >= kvp.Value)
{
foreach(Track track in _alcTracks.Values)
{
if(track.point != kvp.Key ||
@@ -783,6 +811,8 @@ public sealed partial class Alcohol120
return ReadSectorsTag(sectorAddress - kvp.Value, length, kvp.Key, tag, out buffer);
}
}
}
return ErrorNumber.SectorNotFound;
}
@@ -802,7 +832,7 @@ public sealed partial class Alcohol120
uint sectorOffset;
uint sectorSize;
uint sectorSkip;
bool mode2 = false;
var mode2 = false;
switch(alcTrack.mode)
{
@@ -849,7 +879,8 @@ public sealed partial class Alcohol120
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
switch(alcTrack.subMode)
@@ -862,7 +893,8 @@ public sealed partial class Alcohol120
sectorSkip += 96;
break;
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
buffer = new byte[sectorSize * length];
@@ -877,7 +909,7 @@ public sealed partial class Alcohol120
}
uint pregapBytes = alcExtra.pregap * (sectorOffset + sectorSize + sectorSkip);
long fileOffset = (long)alcTrack.startOffset;
var fileOffset = (long)alcTrack.startOffset;
if(alcTrack.startOffset >= pregapBytes)
fileOffset = (long)(alcTrack.startOffset - pregapBytes);
@@ -894,9 +926,9 @@ public sealed partial class Alcohol120
buffer = br.ReadBytes((int)((sectorSize + sectorSkip) * length));
for(int i = 0; i < length; i++)
for(var i = 0; i < length; i++)
{
byte[] sector = new byte[sectorSize];
var sector = new byte[sectorSize];
Array.Copy(buffer, (sectorSize + sectorSkip) * i, sector, 0, sectorSize);
sector = Sector.GetUserDataFromMode2(sector);
mode2Ms.Write(sector, 0, sector.Length);
@@ -908,19 +940,21 @@ public sealed partial class Alcohol120
sectorSkip == 0)
buffer = br.ReadBytes((int)(sectorSize * length));
else
for(int i = 0; i < length; i++)
{
for(var i = 0; i < length; i++)
{
br.BaseStream.Seek(sectorOffset, SeekOrigin.Current);
byte[] sector = br.ReadBytes((int)sectorSize);
br.BaseStream.Seek(sectorSkip, SeekOrigin.Current);
Array.Copy(sector, 0, buffer, i * sectorSize, sectorSize);
}
}
return ErrorNumber.NoError;
}
/// <inheritdoc />
public ErrorNumber ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag,
public ErrorNumber ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag,
out byte[] buffer)
{
buffer = null;
@@ -951,15 +985,14 @@ public sealed partial class Alcohol120
case SectorTagType.CdSectorHeader:
case SectorTagType.CdSectorSubchannel:
case SectorTagType.CdSectorSubHeader:
case SectorTagType.CdSectorSync: break;
case SectorTagType.CdSectorSync:
break;
case SectorTagType.CdTrackFlags:
buffer = new[]
{
(byte)(alcTrack.adrCtl & 0x0F)
};
buffer = new[] { (byte)(alcTrack.adrCtl & 0x0F) };
return ErrorNumber.NoError;
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
switch(alcTrack.mode)
@@ -986,7 +1019,8 @@ public sealed partial class Alcohol120
break;
}
case SectorTagType.CdSectorSubHeader: return ErrorNumber.NotSupported;
case SectorTagType.CdSectorSubHeader:
return ErrorNumber.NotSupported;
case SectorTagType.CdSectorEcc:
{
sectorOffset = 2076;
@@ -1034,13 +1068,15 @@ public sealed partial class Alcohol120
sectorSkip = 0;
break;
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
break;
@@ -1052,7 +1088,8 @@ public sealed partial class Alcohol120
case SectorTagType.CdSectorHeader:
case SectorTagType.CdSectorEcc:
case SectorTagType.CdSectorEccP:
case SectorTagType.CdSectorEccQ: return ErrorNumber.NotSupported;
case SectorTagType.CdSectorEccQ:
return ErrorNumber.NotSupported;
case SectorTagType.CdSectorSubHeader:
{
sectorOffset = 0;
@@ -1082,13 +1119,15 @@ public sealed partial class Alcohol120
sectorSkip = 0;
break;
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
break;
@@ -1172,13 +1211,15 @@ public sealed partial class Alcohol120
sectorSkip = 0;
break;
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
break;
@@ -1233,13 +1274,15 @@ public sealed partial class Alcohol120
sectorSkip = 0;
break;
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
break;
@@ -1259,19 +1302,22 @@ public sealed partial class Alcohol120
sectorSkip = 0;
break;
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
switch(alcTrack.subMode)
@@ -1285,7 +1331,8 @@ public sealed partial class Alcohol120
sectorSkip += 96;
break;
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
buffer = new byte[sectorSize * length];
@@ -1300,7 +1347,7 @@ public sealed partial class Alcohol120
}
uint pregapBytes = alcExtra.pregap * (sectorOffset + sectorSize + sectorSkip);
long fileOffset = (long)alcTrack.startOffset;
var fileOffset = (long)alcTrack.startOffset;
if(alcTrack.startOffset >= pregapBytes)
fileOffset = (long)(alcTrack.startOffset - pregapBytes);
@@ -1315,13 +1362,15 @@ public sealed partial class Alcohol120
sectorSkip == 0)
buffer = br.ReadBytes((int)(sectorSize * length));
else
for(int i = 0; i < length; i++)
{
for(var i = 0; i < length; i++)
{
br.BaseStream.Seek(sectorOffset, SeekOrigin.Current);
byte[] sector = br.ReadBytes((int)sectorSize);
br.BaseStream.Seek(sectorSkip, SeekOrigin.Current);
Array.Copy(sector, 0, buffer, i * sectorSize, sectorSize);
}
}
return ErrorNumber.NoError;
}
@@ -1340,7 +1389,9 @@ public sealed partial class Alcohol120
buffer = null;
foreach(KeyValuePair<uint, ulong> kvp in _offsetMap)
{
if(sectorAddress >= kvp.Value)
{
foreach(Track alcTrack in _alcTracks.Values)
{
if(alcTrack.point != kvp.Key ||
@@ -1352,6 +1403,8 @@ public sealed partial class Alcohol120
return ReadSectorsLong(sectorAddress - kvp.Value, length, kvp.Key, out buffer);
}
}
}
return ErrorNumber.SectorNotFound;
}
@@ -1392,7 +1445,8 @@ public sealed partial class Alcohol120
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
if(alcTrack.subMode == SubchannelMode.Interleaved)
@@ -1410,7 +1464,7 @@ public sealed partial class Alcohol120
}
uint pregapBytes = alcExtra.pregap * (sectorSize + sectorSkip);
long fileOffset = (long)alcTrack.startOffset;
var fileOffset = (long)alcTrack.startOffset;
if(alcTrack.startOffset >= pregapBytes)
fileOffset = (long)(alcTrack.startOffset - pregapBytes);
@@ -1423,7 +1477,8 @@ public sealed partial class Alcohol120
if(sectorSkip == 0)
buffer = br.ReadBytes((int)(sectorSize * length));
else
for(int i = 0; i < length; i++)
{
for(var i = 0; i < length; i++)
{
br.BaseStream.Seek(sectorOffset, SeekOrigin.Current);
byte[] sector = br.ReadBytes((int)sectorSize);
@@ -1431,6 +1486,7 @@ public sealed partial class Alcohol120
Array.Copy(sector, 0, buffer, i * sectorSize, sectorSize);
}
}
return ErrorNumber.NoError;
}
@@ -1447,7 +1503,8 @@ public sealed partial class Alcohol120
foreach(Track alcTrack in _alcTracks.Values)
{
ushort sessionNo =
(from ses in Sessions where alcTrack.point >= ses.StartTrack || alcTrack.point <= ses.EndTrack
(from ses in Sessions
where alcTrack.point >= ses.StartTrack || alcTrack.point <= ses.EndTrack
select ses.Sequence).FirstOrDefault();
if(!_alcTrackExtras.TryGetValue(alcTrack.point, out TrackExtra alcExtra) ||
@@ -1495,4 +1552,6 @@ public sealed partial class Alcohol120
return tracks;
}
#endregion
}

View File

@@ -36,6 +36,21 @@ namespace Aaru.DiscImages;
public sealed partial class Alcohol120
{
#region Nested type: Footer
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct Footer
{
public uint filenameOffset;
public uint widechar;
public readonly uint unknown1;
public readonly uint unknown2;
}
#endregion
#region Nested type: Header
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct Header
{
@@ -60,6 +75,10 @@ public sealed partial class Alcohol120
public readonly uint dpmOffset;
}
#endregion
#region Nested type: Session
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct Session
{
@@ -74,6 +93,10 @@ public sealed partial class Alcohol120
public uint trackOffset;
}
#endregion
#region Nested type: Track
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct Track
{
@@ -101,6 +124,10 @@ public sealed partial class Alcohol120
public byte[] unknown2;
}
#endregion
#region Nested type: TrackExtra
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct TrackExtra
{
@@ -108,12 +135,5 @@ public sealed partial class Alcohol120
public uint sectors;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct Footer
{
public uint filenameOffset;
public uint widechar;
public readonly uint unknown1;
public readonly uint unknown2;
}
#endregion
}

View File

@@ -39,6 +39,8 @@ namespace Aaru.DiscImages;
public sealed partial class Alcohol120
{
#region IWritableOpticalImage Members
/// <inheritdoc />
public bool? VerifySector(ulong sectorAddress)
{
@@ -48,7 +50,7 @@ public sealed partial class Alcohol120
}
/// <inheritdoc />
public bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas,
public bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
@@ -58,10 +60,10 @@ public sealed partial class Alcohol120
if(errno != ErrorNumber.NoError)
return null;
int bps = (int)(buffer.Length / length);
byte[] sector = new byte[bps];
var bps = (int)(buffer.Length / length);
var sector = new byte[bps];
for(int i = 0; i < length; i++)
for(var i = 0; i < length; i++)
{
Array.Copy(buffer, i * bps, sector, 0, bps);
bool? sectorStatus = CdChecksums.CheckCdSector(sector);
@@ -86,7 +88,7 @@ public sealed partial class Alcohol120
}
/// <inheritdoc />
public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
@@ -96,10 +98,10 @@ public sealed partial class Alcohol120
if(errno != ErrorNumber.NoError)
return null;
int bps = (int)(buffer.Length / length);
byte[] sector = new byte[bps];
var bps = (int)(buffer.Length / length);
var sector = new byte[bps];
for(int i = 0; i < length; i++)
for(var i = 0; i < length; i++)
{
Array.Copy(buffer, i * bps, sector, 0, bps);
bool? sectorStatus = CdChecksums.CheckCdSector(sector);
@@ -122,4 +124,6 @@ public sealed partial class Alcohol120
return failingLbas.Count <= 0;
}
#endregion
}

View File

@@ -47,9 +47,11 @@ namespace Aaru.DiscImages;
public sealed partial class Alcohol120
{
#region IWritableOpticalImage Members
/// <inheritdoc />
public bool Create(string path, MediaType mediaType, Dictionary<string, string> options, ulong sectors,
uint sectorSize)
uint sectorSize)
{
if(!SupportedMediaTypes.Contains(mediaType))
{
@@ -71,8 +73,10 @@ public sealed partial class Alcohol120
_imageStream =
new
FileStream(Path.Combine(Path.GetDirectoryName(path) ?? "", Path.GetFileNameWithoutExtension(path)) + ".mdf",
FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
FileStream(
Path.Combine(Path.GetDirectoryName(path) ?? "", Path.GetFileNameWithoutExtension(path)) +
".mdf",
FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
}
catch(IOException e)
{
@@ -248,7 +252,7 @@ public sealed partial class Alcohol120
}
_imageStream.
Seek((long)(track.FileOffset + ((sectorAddress - track.StartSector) * (ulong)track.RawBytesPerSector)),
Seek((long)(track.FileOffset + (sectorAddress - track.StartSector) * (ulong)track.RawBytesPerSector),
SeekOrigin.Begin);
_imageStream.Write(data, 0, data.Length);
@@ -308,8 +312,9 @@ public sealed partial class Alcohol120
{
case TrackSubchannelType.None:
_imageStream.
Seek((long)(track.FileOffset + ((sectorAddress - track.StartSector) * (ulong)track.RawBytesPerSector)),
SeekOrigin.Begin);
Seek(
(long)(track.FileOffset + (sectorAddress - track.StartSector) * (ulong)track.RawBytesPerSector),
SeekOrigin.Begin);
_imageStream.Write(data, 0, data.Length);
@@ -319,8 +324,10 @@ public sealed partial class Alcohol120
case TrackSubchannelType.Raw:
case TrackSubchannelType.RawInterleaved:
_imageStream.
Seek((long)(track.FileOffset + ((sectorAddress - track.StartSector) * (ulong)(track.RawBytesPerSector + 96))),
SeekOrigin.Begin);
Seek(
(long)(track.FileOffset +
(sectorAddress - track.StartSector) * (ulong)(track.RawBytesPerSector + 96)),
SeekOrigin.Begin);
for(uint i = 0; i < length; i++)
{
@@ -365,11 +372,13 @@ public sealed partial class Alcohol120
return false;
}
uint subchannelSize = (uint)(track.SubchannelType != TrackSubchannelType.None ? 96 : 0);
var subchannelSize = (uint)(track.SubchannelType != TrackSubchannelType.None ? 96 : 0);
_imageStream.
Seek((long)(track.FileOffset + ((sectorAddress - track.StartSector) * (ulong)(track.RawBytesPerSector + subchannelSize))),
SeekOrigin.Begin);
Seek(
(long)(track.FileOffset + (sectorAddress - track.StartSector) *
(ulong)(track.RawBytesPerSector + subchannelSize)),
SeekOrigin.Begin);
_imageStream.Write(data, 0, data.Length);
@@ -410,13 +419,15 @@ public sealed partial class Alcohol120
return false;
}
uint subchannelSize = (uint)(track.SubchannelType != TrackSubchannelType.None ? 96 : 0);
var subchannelSize = (uint)(track.SubchannelType != TrackSubchannelType.None ? 96 : 0);
for(uint i = 0; i < length; i++)
{
_imageStream.
Seek((long)(track.FileOffset + ((i + sectorAddress - track.StartSector) * (ulong)(track.RawBytesPerSector + subchannelSize))),
SeekOrigin.Begin);
Seek(
(long)(track.FileOffset + (i + sectorAddress - track.StartSector) *
(ulong)(track.RawBytesPerSector + subchannelSize)),
SeekOrigin.Begin);
_imageStream.Write(data, (int)(i * track.RawBytesPerSector), track.RawBytesPerSector);
}
@@ -435,7 +446,7 @@ public sealed partial class Alcohol120
{
CommonTypes.Structs.Track[] tmpTracks = tracks.OrderBy(t => t.Sequence).ToArray();
for(int i = 1; i < tmpTracks.Length; i++)
for(var i = 1; i < tmpTracks.Length; i++)
{
CommonTypes.Structs.Track firstTrackInSession =
tracks.FirstOrDefault(t => t.Session == tmpTracks[i].Session);
@@ -508,11 +519,8 @@ public sealed partial class Alcohol120
var header = new Header
{
signature = _alcoholSignature,
version = new byte[]
{
1, 5
},
signature = _alcoholSignature,
version = new byte[] { 1, 5 },
type = MediaTypeToMediumType(_imageInfo.MediaType),
sessions = sessions,
structuresOffset = (uint)(_pfi == null ? 0 : 96),
@@ -531,7 +539,7 @@ public sealed partial class Alcohol120
_alcToc = new Dictionary<int, Dictionary<int, Track>>();
_writingTracks = _writingTracks.OrderBy(t => t.Session).ThenBy(t => t.Sequence).ToList();
_alcTrackExtras = new Dictionary<int, TrackExtra>();
long currentTrackOffset = header.sessionOffset + (Marshal.SizeOf<Session>() * sessions);
long currentTrackOffset = header.sessionOffset + Marshal.SizeOf<Session>() * sessions;
byte[] tmpToc = null;
@@ -547,9 +555,10 @@ public sealed partial class Alcohol120
FullTOC.CDFullTOC? decodedToc = FullTOC.Decode(tmpToc);
long currentExtraOffset = currentTrackOffset;
int extraCount = 0;
var extraCount = 0;
for(int i = 1; i <= sessions; i++)
for(var i = 1; i <= sessions; i++)
{
if(decodedToc.HasValue)
{
extraCount += decodedToc.Value.TrackDescriptors.Count(t => t.SessionNumber == i);
@@ -572,8 +581,9 @@ public sealed partial class Alcohol120
currentExtraOffset += Marshal.SizeOf<Track>() * 2;
extraCount += 2;
}
}
long footerOffset = currentExtraOffset + (Marshal.SizeOf<TrackExtra>() * extraCount);
long footerOffset = currentExtraOffset + Marshal.SizeOf<TrackExtra>() * extraCount;
if(_bca != null)
{
@@ -615,7 +625,8 @@ public sealed partial class Alcohol120
_alcToc.Add(1, _alcTracks);
}
else
for(int i = 1; i <= sessions; i++)
{
for(var i = 1; i <= sessions; i++)
{
CommonTypes.Structs.Track firstTrack = _writingTracks.First(t => t.Session == i);
CommonTypes.Structs.Track lastTrack = _writingTracks.Last(t => t.Session == i);
@@ -637,7 +648,7 @@ public sealed partial class Alcohol120
Dictionary<int, Track> thisSessionTracks = new();
_trackFlags.TryGetValue((byte)firstTrack.Sequence, out byte firstTrackControl);
_trackFlags.TryGetValue((byte)lastTrack.Sequence, out byte lastTrackControl);
_trackFlags.TryGetValue((byte)lastTrack.Sequence, out byte lastTrackControl);
if(firstTrackControl == 0 &&
firstTrack.Type != TrackType.Audio)
@@ -651,6 +662,7 @@ public sealed partial class Alcohol120
if(decodedToc?.TrackDescriptors.Any(t => t.SessionNumber == i && t.POINT is >= 0xA0 and <= 0xAF) ==
true)
{
foreach(FullTOC.TrackDataDescriptor tocTrk in
decodedToc.Value.TrackDescriptors.Where(t => t.SessionNumber == i &&
t.POINT is >= 0xA0 and <= 0xAF))
@@ -676,6 +688,7 @@ public sealed partial class Alcohol120
currentTrackOffset += Marshal.SizeOf<Track>();
currentExtraOffset += Marshal.SizeOf<TrackExtra>();
}
}
else
{
thisSessionTracks.Add(0xA0, new Track
@@ -689,8 +702,8 @@ public sealed partial class Alcohol120
psec = (byte)(_imageInfo.MediaType == MediaType.CDI
? 0x10
: _writingTracks.Any(t => t.Type is TrackType.CdMode2Form1
or TrackType.CdMode2Form2
or TrackType.CdMode2Formless)
or TrackType.CdMode2Form2
or TrackType.CdMode2Formless)
? 0x20
: 0),
extraOffset = (uint)currentExtraOffset
@@ -766,14 +779,15 @@ public sealed partial class Alcohol120
alcTrk.mode = TrackTypeToTrackMode(track.Type);
alcTrk.subMode = track.SubchannelType != TrackSubchannelType.None ? SubchannelMode.Interleaved
alcTrk.subMode = track.SubchannelType != TrackSubchannelType.None
? SubchannelMode.Interleaved
: SubchannelMode.None;
alcTrk.sectorSize = (ushort)(track.RawBytesPerSector +
(track.SubchannelType != TrackSubchannelType.None ? 96 : 0));
alcTrk.startLba = (uint)(track.StartSector + track.Pregap);
alcTrk.startOffset = track.FileOffset + (alcTrk.sectorSize * track.Pregap);
alcTrk.startOffset = track.FileOffset + alcTrk.sectorSize * track.Pregap;
alcTrk.files = 1;
alcTrk.extraOffset = (uint)currentExtraOffset;
alcTrk.footerOffset = (uint)footerOffset;
@@ -788,8 +802,8 @@ public sealed partial class Alcohol120
// Daemon Tools expect it to be like this
alcTrk.unknown = new byte[]
{
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00
};
alcTrk.unknown2 = new byte[24];
@@ -824,6 +838,7 @@ public sealed partial class Alcohol120
}
if(decodedToc?.TrackDescriptors.Any(t => t.SessionNumber == i && t.POINT >= 0xB0) == true)
{
foreach(FullTOC.TrackDataDescriptor tocTrk in
decodedToc.Value.TrackDescriptors.Where(t => t.SessionNumber == i && t.POINT >= 0xB0))
{
@@ -848,6 +863,7 @@ public sealed partial class Alcohol120
currentExtraOffset += Marshal.SizeOf<TrackExtra>();
currentTrackOffset += Marshal.SizeOf<Track>();
}
}
else if(i < sessions)
{
(byte minute, byte second, byte frame) leadoutAmsf =
@@ -887,6 +903,7 @@ public sealed partial class Alcohol120
_alcToc.Add(i, thisSessionTracks);
}
}
_alcFooter = new Footer
{
@@ -898,8 +915,8 @@ public sealed partial class Alcohol120
// Write header
_descriptorStream.Seek(0, SeekOrigin.Begin);
byte[] block = new byte[Marshal.SizeOf<Header>()];
nint blockPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(Marshal.SizeOf<Header>());
var block = new byte[Marshal.SizeOf<Header>()];
nint blockPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(Marshal.SizeOf<Header>());
System.Runtime.InteropServices.Marshal.StructureToPtr(header, blockPtr, true);
System.Runtime.InteropServices.Marshal.Copy(blockPtr, block, 0, block.Length);
System.Runtime.InteropServices.Marshal.FreeHGlobal(blockPtr);
@@ -919,10 +936,7 @@ public sealed partial class Alcohol120
break;
case 2048:
_descriptorStream.Write(new byte[]
{
0x08, 0x02, 0x00, 0x00
}, 0, 4);
_descriptorStream.Write(new byte[] { 0x08, 0x02, 0x00, 0x00 }, 0, 4);
_descriptorStream.Write(_dmi, 0, 2048);
@@ -1013,10 +1027,7 @@ public sealed partial class Alcohol120
_descriptorStream.Write(filename, 0, filename.Length);
// Write filename null termination
_descriptorStream.Write(new byte[]
{
0, 0
}, 0, 2);
_descriptorStream.Write(new byte[] { 0, 0 }, 0, 2);
_descriptorStream.Flush();
_descriptorStream.Close();
@@ -1094,8 +1105,11 @@ public sealed partial class Alcohol120
}
_imageStream.
Seek((long)(track.FileOffset + ((sectorAddress - track.StartSector) * (ulong)(track.RawBytesPerSector + 96))) + track.RawBytesPerSector,
SeekOrigin.Begin);
Seek(
(long)(track.FileOffset +
(sectorAddress - track.StartSector) * (ulong)(track.RawBytesPerSector + 96)) +
track.RawBytesPerSector,
SeekOrigin.Begin);
_imageStream.Write(data, 0, data.Length);
@@ -1130,7 +1144,8 @@ public sealed partial class Alcohol120
switch(tag)
{
case SectorTagType.CdTrackFlags: return WriteSectorTag(data, sectorAddress, tag);
case SectorTagType.CdTrackFlags:
return WriteSectorTag(data, sectorAddress, tag);
case SectorTagType.CdSectorSubchannel:
{
if(track.SubchannelType == 0)
@@ -1152,8 +1167,10 @@ public sealed partial class Alcohol120
for(uint i = 0; i < length; i++)
{
_imageStream.
Seek((long)(track.FileOffset + ((i + sectorAddress - track.StartSector) * (ulong)(track.RawBytesPerSector + 96))) + track.RawBytesPerSector,
SeekOrigin.Begin);
Seek(
(long)(track.FileOffset + (i + sectorAddress - track.StartSector) *
(ulong)(track.RawBytesPerSector + 96)) + track.RawBytesPerSector,
SeekOrigin.Begin);
_imageStream.Write(data, (int)(i * 96), 96);
}
@@ -1172,4 +1189,6 @@ public sealed partial class Alcohol120
/// <inheritdoc />
public bool SetMetadata(Metadata metadata) => false;
#endregion
}

View File

@@ -42,10 +42,11 @@ namespace Aaru.DiscImages;
/// <summary>Implements reading and writing Anex-86 disk images</summary>
public sealed partial class Anex86 : IWritableImage
{
IFilter _anexImageFilter;
Header _header;
ImageInfo _imageInfo;
FileStream _writingStream;
const string MODULE_NAME = "Anex86 plugin";
IFilter _anexImageFilter;
Header _header;
ImageInfo _imageInfo;
FileStream _writingStream;
public Anex86() => _imageInfo = new ImageInfo
{
@@ -70,6 +71,4 @@ public sealed partial class Anex86 : IWritableImage
DriveSerialNumber = null,
DriveFirmwareRevision = null
};
const string MODULE_NAME = "Anex86 plugin";
}

View File

@@ -39,6 +39,8 @@ namespace Aaru.DiscImages;
public sealed partial class Anex86
{
#region IWritableImage Members
/// <inheritdoc />
public bool Identify(IFilter imageFilter)
{
@@ -48,21 +50,23 @@ public sealed partial class Anex86
if(stream.Length < Marshal.SizeOf<Header>())
return false;
byte[] hdrB = new byte[Marshal.SizeOf<Header>()];
var hdrB = new byte[Marshal.SizeOf<Header>()];
stream.EnsureRead(hdrB, 0, hdrB.Length);
_header = Marshal.SpanToStructureLittleEndian<Header>(hdrB);
AaruConsole.DebugWriteLine(MODULE_NAME, "fdihdr.unknown = {0}", _header.unknown);
AaruConsole.DebugWriteLine(MODULE_NAME, "fdihdr.hddtype = {0}", _header.hddtype);
AaruConsole.DebugWriteLine(MODULE_NAME, "fdihdr.hdrSize = {0}", _header.hdrSize);
AaruConsole.DebugWriteLine(MODULE_NAME, "fdihdr.dskSize = {0}", _header.dskSize);
AaruConsole.DebugWriteLine(MODULE_NAME, "fdihdr.bps = {0}", _header.bps);
AaruConsole.DebugWriteLine(MODULE_NAME, "fdihdr.spt = {0}", _header.spt);
AaruConsole.DebugWriteLine(MODULE_NAME, "fdihdr.heads = {0}", _header.heads);
AaruConsole.DebugWriteLine(MODULE_NAME, "fdihdr.unknown = {0}", _header.unknown);
AaruConsole.DebugWriteLine(MODULE_NAME, "fdihdr.hddtype = {0}", _header.hddtype);
AaruConsole.DebugWriteLine(MODULE_NAME, "fdihdr.hdrSize = {0}", _header.hdrSize);
AaruConsole.DebugWriteLine(MODULE_NAME, "fdihdr.dskSize = {0}", _header.dskSize);
AaruConsole.DebugWriteLine(MODULE_NAME, "fdihdr.bps = {0}", _header.bps);
AaruConsole.DebugWriteLine(MODULE_NAME, "fdihdr.spt = {0}", _header.spt);
AaruConsole.DebugWriteLine(MODULE_NAME, "fdihdr.heads = {0}", _header.heads);
AaruConsole.DebugWriteLine(MODULE_NAME, "fdihdr.cylinders = {0}", _header.cylinders);
return stream.Length == _header.hdrSize + _header.dskSize &&
_header.dskSize == _header.bps * _header.spt * _header.heads * _header.cylinders;
}
#endregion
}

View File

@@ -41,25 +41,32 @@ namespace Aaru.DiscImages;
public sealed partial class Anex86
{
#region IWritableImage Members
/// <inheritdoc />
public ImageInfo Info => _imageInfo;
/// <inheritdoc />
public string Name => Localization.Anex86_Name;
/// <inheritdoc />
public Guid Id => new("0410003E-6E7B-40E6-9328-BA5651ADF6B7");
/// <inheritdoc />
public string Author => Authors.NataliaPortillo;
/// <inheritdoc />
public string Format => "Anex86 disk image";
/// <inheritdoc />
public List<DumpHardware> DumpHardware => null;
/// <inheritdoc />
public Metadata AaruMetadata => null;
/// <inheritdoc />
public IEnumerable<MediaTagType> SupportedMediaTags => Array.Empty<MediaTagType>();
/// <inheritdoc />
public IEnumerable<SectorTagType> SupportedSectorTags => Array.Empty<SectorTagType>();
@@ -76,21 +83,24 @@ public sealed partial class Anex86
MediaType.ACORN_35_DS_DD, MediaType.DOS_35_DS_DD_8, MediaType.DOS_35_DS_DD_9, MediaType.ACORN_35_DS_HD,
MediaType.DOS_525_HD, MediaType.ACORN_525_DS_DD, MediaType.DOS_35_HD, MediaType.XDF_525, MediaType.DMF,
MediaType.XDF_35, MediaType.DOS_35_ED, MediaType.FDFORMAT_35_DD, MediaType.FDFORMAT_525_HD,
MediaType.FDFORMAT_35_HD, MediaType.NEC_35_TD, MediaType.Unknown, MediaType.GENERIC_HDD, MediaType.FlashDrive,
MediaType.CompactFlash, MediaType.CompactFlashType2, MediaType.PCCardTypeI, MediaType.PCCardTypeII,
MediaType.PCCardTypeIII, MediaType.PCCardTypeIV, MediaType.MetaFloppy_Mod_I, MediaType.MetaFloppy_Mod_II
};
/// <inheritdoc />
public IEnumerable<(string name, Type type, string description, object @default)> SupportedOptions =>
Array.Empty<(string name, Type type, string description, object @default)>();
/// <inheritdoc />
public IEnumerable<string> KnownExtensions => new[]
{
".fdi", ".hdi"
MediaType.FDFORMAT_35_HD, MediaType.NEC_35_TD, MediaType.Unknown, MediaType.GENERIC_HDD,
MediaType.FlashDrive, MediaType.CompactFlash, MediaType.CompactFlashType2, MediaType.PCCardTypeI,
MediaType.PCCardTypeII, MediaType.PCCardTypeIII, MediaType.PCCardTypeIV, MediaType.MetaFloppy_Mod_I,
MediaType.MetaFloppy_Mod_II
};
/// <inheritdoc />
public IEnumerable<(string name, Type type, string description, object @default)> SupportedOptions =>
Array.Empty<(string name, Type type, string description, object @default)>();
/// <inheritdoc />
public IEnumerable<string> KnownExtensions => new[] { ".fdi", ".hdi" };
/// <inheritdoc />
public bool IsWriting { get; private set; }
/// <inheritdoc />
public string ErrorMessage { get; private set; }
#endregion
}

View File

@@ -41,6 +41,8 @@ namespace Aaru.DiscImages;
public sealed partial class Anex86
{
#region IWritableImage Members
/// <inheritdoc />
public ErrorNumber Open(IFilter imageFilter)
{
@@ -50,7 +52,7 @@ public sealed partial class Anex86
if(stream.Length < Marshal.SizeOf<Header>())
return ErrorNumber.InvalidArgument;
byte[] hdrB = new byte[Marshal.SizeOf<Header>()];
var hdrB = new byte[Marshal.SizeOf<Header>()];
stream.EnsureRead(hdrB, 0, hdrB.Length);
_header = Marshal.SpanToStructureLittleEndian<Header>(hdrB);
@@ -98,10 +100,12 @@ public sealed partial class Anex86
Stream stream = _anexImageFilter.GetDataForkStream();
stream.Seek((long)((ulong)_header.hdrSize + (sectorAddress * _imageInfo.SectorSize)), SeekOrigin.Begin);
stream.Seek((long)((ulong)_header.hdrSize + sectorAddress * _imageInfo.SectorSize), SeekOrigin.Begin);
stream.EnsureRead(buffer, 0, (int)(length * _imageInfo.SectorSize));
return ErrorNumber.NoError;
}
#endregion
}

View File

@@ -36,6 +36,8 @@ namespace Aaru.DiscImages;
public sealed partial class Anex86
{
#region Nested type: Header
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct Header
{
@@ -48,4 +50,6 @@ public sealed partial class Anex86
public int heads;
public int cylinders;
}
#endregion
}

View File

@@ -36,6 +36,8 @@ namespace Aaru.DiscImages;
public sealed partial class Anex86
{
#region IWritableImage Members
/// <inheritdoc />
public ErrorNumber ReadMediaTag(MediaTagType tag, out byte[] buffer)
{
@@ -75,4 +77,6 @@ public sealed partial class Anex86
return ErrorNumber.NotSupported;
}
#endregion
}

View File

@@ -44,9 +44,11 @@ namespace Aaru.DiscImages;
public sealed partial class Anex86
{
#region IWritableImage Members
/// <inheritdoc />
public bool Create(string path, MediaType mediaType, Dictionary<string, string> options, ulong sectors,
uint sectorSize)
uint sectorSize)
{
if(sectorSize == 0)
{
@@ -133,7 +135,7 @@ public sealed partial class Anex86
return false;
}
_writingStream.Seek((long)(4096 + (sectorAddress * _imageInfo.SectorSize)), SeekOrigin.Begin);
_writingStream.Seek((long)(4096 + sectorAddress * _imageInfo.SectorSize), SeekOrigin.Begin);
_writingStream.Write(data, 0, data.Length);
ErrorMessage = "";
@@ -165,7 +167,7 @@ public sealed partial class Anex86
return false;
}
_writingStream.Seek((long)(4096 + (sectorAddress * _imageInfo.SectorSize)), SeekOrigin.Begin);
_writingStream.Seek((long)(4096 + sectorAddress * _imageInfo.SectorSize), SeekOrigin.Begin);
_writingStream.Write(data, 0, data.Length);
ErrorMessage = "";
@@ -200,8 +202,8 @@ public sealed partial class Anex86
}
if(_imageInfo.MediaType is MediaType.Unknown or MediaType.GENERIC_HDD or MediaType.FlashDrive
or MediaType.CompactFlash or MediaType.CompactFlashType2 or MediaType.PCCardTypeI
or MediaType.PCCardTypeII or MediaType.PCCardTypeIII or MediaType.PCCardTypeIV &&
or MediaType.CompactFlash or MediaType.CompactFlashType2 or MediaType.PCCardTypeI
or MediaType.PCCardTypeII or MediaType.PCCardTypeIII or MediaType.PCCardTypeIV &&
_header.cylinders == 0)
{
_header.cylinders = (int)(_imageInfo.Sectors / 8 / 33);
@@ -226,7 +228,7 @@ public sealed partial class Anex86
}
}
byte[] hdr = new byte[Marshal.SizeOf<Header>()];
var hdr = new byte[Marshal.SizeOf<Header>()];
MemoryMarshal.Write(hdr, in _header);
_writingStream.Seek(0, SeekOrigin.Begin);
@@ -296,4 +298,6 @@ public sealed partial class Anex86
/// <inheritdoc />
public bool SetMetadata(Metadata metadata) => false;
#endregion
}

View File

@@ -42,11 +42,12 @@ namespace Aaru.DiscImages;
/// <summary>Implements reading and writing XGD emulator disk images</summary>
public sealed partial class Apple2Mg : IWritableImage
{
IFilter _a2MgImageFilter;
byte[] _decodedImage;
Header _imageHeader;
ImageInfo _imageInfo;
FileStream _writingStream;
const string MODULE_NAME = "2MG plugin";
IFilter _a2MgImageFilter;
byte[] _decodedImage;
Header _imageHeader;
ImageInfo _imageInfo;
FileStream _writingStream;
public Apple2Mg() => _imageInfo = new ImageInfo
{
@@ -71,6 +72,4 @@ public sealed partial class Apple2Mg : IWritableImage
DriveSerialNumber = null,
DriveFirmwareRevision = null
};
const string MODULE_NAME = "2MG plugin";
}

View File

@@ -58,15 +58,9 @@ public sealed partial class Apple2Mg
/// <summary>Disk image created by Aaru, "aaru"</summary>
const uint CREATOR_AARU = 0x75726161;
const uint LOCKED_DISK = 0x80000000;
const uint VALID_VOLUME_NUMBER = 0x00000100;
const uint VOLUME_NUMBER_MASK = 0x000000FF;
readonly int[] _deinterleave =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
};
readonly int[] _interleave =
{
0, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 15
};
const uint LOCKED_DISK = 0x80000000;
const uint VALID_VOLUME_NUMBER = 0x00000100;
const uint VOLUME_NUMBER_MASK = 0x000000FF;
readonly int[] _deinterleave = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
readonly int[] _interleave = { 0, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 15 };
}

View File

@@ -34,8 +34,14 @@ namespace Aaru.DiscImages;
public sealed partial class Apple2Mg
{
#region Nested type: SectorOrder
enum SectorOrder : uint
{
Dos = 0, ProDos = 1, Nibbles = 2
Dos = 0,
ProDos = 1,
Nibbles = 2
}
#endregion
}

View File

@@ -37,14 +37,14 @@ namespace Aaru.DiscImages;
public sealed partial class Apple2Mg
{
MediaType GetMediaType() => _imageInfo.Sectors switch
{
455 => MediaType.Apple32SS,
910 => MediaType.Apple32DS,
560 => MediaType.Apple33SS,
1120 => MediaType.Apple33DS,
800 => MediaType.AppleSonySS,
1600 => MediaType.AppleSonyDS,
2880 => MediaType.DOS_35_HD,
_ => MediaType.Unknown
};
{
455 => MediaType.Apple32SS,
910 => MediaType.Apple32DS,
560 => MediaType.Apple33SS,
1120 => MediaType.Apple33DS,
800 => MediaType.AppleSonySS,
1600 => MediaType.AppleSonyDS,
2880 => MediaType.DOS_35_HD,
_ => MediaType.Unknown
};
}

View File

@@ -38,6 +38,8 @@ namespace Aaru.DiscImages;
public sealed partial class Apple2Mg
{
#region IWritableImage Members
/// <inheritdoc />
public bool Identify(IFilter imageFilter)
{
@@ -47,7 +49,7 @@ public sealed partial class Apple2Mg
if(stream.Length < 65)
return false;
byte[] header = new byte[64];
var header = new byte[64];
stream.EnsureRead(header, 0, 64);
Header hdr = Marshal.SpanToStructureLittleEndian<Header>(header);
@@ -76,4 +78,6 @@ public sealed partial class Apple2Mg
return hdr.CreatorSpecificOffset + hdr.CreatorSpecificSize <= stream.Length;
}
#endregion
}

View File

@@ -41,27 +41,35 @@ namespace Aaru.DiscImages;
public sealed partial class Apple2Mg
{
#region IWritableImage Members
/// <inheritdoc />
public ImageInfo Info => _imageInfo;
/// <inheritdoc />
public string Name => Localization.Apple2Mg_Name;
/// <inheritdoc />
public Guid Id => new("CBAF8824-BA5F-415F-953A-19A03519B2D1");
/// <inheritdoc />
public string Author => Authors.NataliaPortillo;
/// <inheritdoc />
public string Format => "Apple 2IMG";
/// <inheritdoc />
public List<DumpHardware> DumpHardware => null;
/// <inheritdoc />
public Metadata AaruMetadata => null;
/// <inheritdoc />
public IEnumerable<MediaTagType> SupportedMediaTags => Array.Empty<MediaTagType>();
/// <inheritdoc />
public IEnumerable<SectorTagType> SupportedSectorTags => Array.Empty<SectorTagType>();
/// <inheritdoc />
public IEnumerable<MediaType> SupportedMediaTypes => new[]
{
@@ -70,16 +78,19 @@ public sealed partial class Apple2Mg
MediaType.CompactFlashType2, MediaType.PCCardTypeI, MediaType.PCCardTypeII, MediaType.PCCardTypeIII,
MediaType.PCCardTypeIV
};
/// <inheritdoc />
public IEnumerable<(string name, Type type, string description, object @default)> SupportedOptions =>
Array.Empty<(string name, Type type, string description, object @default)>();
/// <inheritdoc />
public IEnumerable<string> KnownExtensions => new[]
{
".2mg"
};
public IEnumerable<string> KnownExtensions => new[] { ".2mg" };
/// <inheritdoc />
public bool IsWriting { get; private set; }
/// <inheritdoc />
public string ErrorMessage { get; private set; }
#endregion
}

View File

@@ -44,6 +44,8 @@ namespace Aaru.DiscImages;
public sealed partial class Apple2Mg
{
#region IWritableImage Members
/// <inheritdoc />
public ErrorNumber Open(IFilter imageFilter)
{
@@ -52,12 +54,12 @@ public sealed partial class Apple2Mg
_imageHeader = new Header();
byte[] header = new byte[64];
var header = new byte[64];
stream.EnsureRead(header, 0, 64);
byte[] magic = new byte[4];
byte[] creator = new byte[4];
var magic = new byte[4];
var creator = new byte[4];
Array.Copy(header, 0, magic, 0, 4);
Array.Copy(header, 0, magic, 0, 4);
Array.Copy(header, 4, creator, 0, 4);
_imageHeader = Marshal.SpanToStructureLittleEndian<Header>(header);
@@ -74,13 +76,13 @@ public sealed partial class Apple2Mg
AaruConsole.DebugWriteLine(MODULE_NAME, "ImageHeader.creator = \"{0}\"", Encoding.ASCII.GetString(creator));
AaruConsole.DebugWriteLine(MODULE_NAME, "ImageHeader.headerSize = {0}", _imageHeader.HeaderSize);
AaruConsole.DebugWriteLine(MODULE_NAME, "ImageHeader.version = {0}", _imageHeader.Version);
AaruConsole.DebugWriteLine(MODULE_NAME, "ImageHeader.imageFormat = {0}", _imageHeader.ImageFormat);
AaruConsole.DebugWriteLine(MODULE_NAME, "ImageHeader.flags = 0x{0:X8}", _imageHeader.Flags);
AaruConsole.DebugWriteLine(MODULE_NAME, "ImageHeader.blocks = {0}", _imageHeader.Blocks);
AaruConsole.DebugWriteLine(MODULE_NAME, "ImageHeader.headerSize = {0}", _imageHeader.HeaderSize);
AaruConsole.DebugWriteLine(MODULE_NAME, "ImageHeader.version = {0}", _imageHeader.Version);
AaruConsole.DebugWriteLine(MODULE_NAME, "ImageHeader.imageFormat = {0}", _imageHeader.ImageFormat);
AaruConsole.DebugWriteLine(MODULE_NAME, "ImageHeader.flags = 0x{0:X8}", _imageHeader.Flags);
AaruConsole.DebugWriteLine(MODULE_NAME, "ImageHeader.blocks = {0}", _imageHeader.Blocks);
AaruConsole.DebugWriteLine(MODULE_NAME, "ImageHeader.dataOffset = 0x{0:X8}", _imageHeader.DataOffset);
AaruConsole.DebugWriteLine(MODULE_NAME, "ImageHeader.dataSize = {0}", _imageHeader.DataSize);
AaruConsole.DebugWriteLine(MODULE_NAME, "ImageHeader.dataSize = {0}", _imageHeader.DataSize);
AaruConsole.DebugWriteLine(MODULE_NAME, "ImageHeader.commentOffset = 0x{0:X8}", _imageHeader.CommentOffset);
@@ -140,11 +142,13 @@ public sealed partial class Apple2Mg
? _interleave
: _deinterleave;
for(int t = 0; t < 35; t++)
for(var t = 0; t < 35; t++)
{
for(int s = 0; s < 16; s++)
Array.Copy(tmp, (t * 16 * 256) + (s * 256), _decodedImage, (t * 16 * 256) + (offsets[s] * 256),
for(var s = 0; s < 16; s++)
{
Array.Copy(tmp, t * 16 * 256 + s * 256, _decodedImage, t * 16 * 256 + offsets[s] * 256,
256);
}
}
_imageInfo.Sectors = 560;
@@ -158,11 +162,13 @@ public sealed partial class Apple2Mg
_decodedImage = new byte[_imageHeader.DataSize];
offsets = _interleave;
for(int t = 0; t < 200; t++)
for(var t = 0; t < 200; t++)
{
for(int s = 0; s < 16; s++)
Array.Copy(tmp, (t * 16 * 256) + (s * 256), _decodedImage, (t * 16 * 256) + (offsets[s] * 256),
for(var s = 0; s < 16; s++)
{
Array.Copy(tmp, t * 16 * 256 + s * 256, _decodedImage, t * 16 * 256 + offsets[s] * 256,
256);
}
}
_imageInfo.Sectors = 1600;
@@ -180,18 +186,19 @@ public sealed partial class Apple2Mg
_imageInfo.ImageSize = _imageHeader.DataSize;
_imageInfo.Application = _imageHeader.Creator switch
{
CREATOR_ASIMOV => "ASIMOV2",
CREATOR_BERNIE => "Bernie ][ the Rescue",
CREATOR_CATAKIG => "Catakig",
CREATOR_SHEPPY => "Sheppy's ImageMaker",
CREATOR_SWEET => "Sweet16",
CREATOR_XGS => "XGS",
CREATOR_CIDER => "CiderPress",
CREATOR_DIC => "DiscImageChef",
CREATOR_AARU => "Aaru",
_ => string.Format(Localization.Unknown_creator_code_0, Encoding.ASCII.GetString(creator))
};
{
CREATOR_ASIMOV => "ASIMOV2",
CREATOR_BERNIE => "Bernie ][ the Rescue",
CREATOR_CATAKIG => "Catakig",
CREATOR_SHEPPY => "Sheppy's ImageMaker",
CREATOR_SWEET => "Sweet16",
CREATOR_XGS => "XGS",
CREATOR_CIDER => "CiderPress",
CREATOR_DIC => "DiscImageChef",
CREATOR_AARU => "Aaru",
_ => string.Format(Localization.Unknown_creator_code_0,
Encoding.ASCII.GetString(creator))
};
_imageInfo.Version = _imageHeader.Version.ToString();
@@ -200,7 +207,7 @@ public sealed partial class Apple2Mg
{
stream.Seek(_imageHeader.CommentOffset, SeekOrigin.Begin);
byte[] comments = new byte[_imageHeader.CommentSize];
var comments = new byte[_imageHeader.CommentSize];
stream.EnsureRead(comments, 0, (int)_imageHeader.CommentSize);
_imageInfo.Comments = Encoding.ASCII.GetString(comments);
}
@@ -289,17 +296,21 @@ public sealed partial class Apple2Mg
buffer = new byte[length * _imageInfo.SectorSize];
if(_decodedImage != null)
{
Array.Copy(_decodedImage, (long)(sectorAddress * _imageInfo.SectorSize), buffer, 0,
length * _imageInfo.SectorSize);
}
else
{
Stream stream = _a2MgImageFilter.GetDataForkStream();
stream.Seek((long)(_imageHeader.DataOffset + (sectorAddress * _imageInfo.SectorSize)), SeekOrigin.Begin);
stream.Seek((long)(_imageHeader.DataOffset + sectorAddress * _imageInfo.SectorSize), SeekOrigin.Begin);
stream.EnsureRead(buffer, 0, (int)(length * _imageInfo.SectorSize));
}
return ErrorNumber.NoError;
}
#endregion
}

View File

@@ -37,7 +37,10 @@ namespace Aaru.DiscImages;
public sealed partial class Apple2Mg
{
[SuppressMessage("ReSharper", "NotAccessedField.Local"), StructLayout(LayoutKind.Sequential, Pack = 1)]
#region Nested type: Header
[SuppressMessage("ReSharper", "NotAccessedField.Local")]
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct Header
{
/// <summary>Offset 0x00, magic</summary>
@@ -75,4 +78,6 @@ public sealed partial class Apple2Mg
/// <summary>Offset 0x3C, reserved, should be zero</summary>
public readonly uint Reserved4;
}
#endregion
}

View File

@@ -36,6 +36,8 @@ namespace Aaru.DiscImages;
public sealed partial class Apple2Mg
{
#region IWritableImage Members
/// <inheritdoc />
public ErrorNumber ReadMediaTag(MediaTagType tag, out byte[] buffer)
{
@@ -75,4 +77,6 @@ public sealed partial class Apple2Mg
return ErrorNumber.NotSupported;
}
#endregion
}

View File

@@ -44,18 +44,22 @@ namespace Aaru.DiscImages;
public sealed partial class Apple2Mg
{
#region IWritableImage Members
/// <inheritdoc />
public bool Create(string path, MediaType mediaType, Dictionary<string, string> options, ulong sectors,
uint sectorSize)
uint sectorSize)
{
if(sectorSize != 512)
{
if(sectorSize != 256 ||
(mediaType != MediaType.Apple32SS && mediaType != MediaType.Apple33SS))
mediaType != MediaType.Apple32SS && mediaType != MediaType.Apple33SS)
{
ErrorMessage = Localization.Unsupported_sector_size;
return false;
}
}
if(!SupportedMediaTypes.Contains(mediaType))
{
@@ -127,7 +131,7 @@ public sealed partial class Apple2Mg
return false;
}
_writingStream.Seek((long)(0x40 + (sectorAddress * _imageInfo.SectorSize)), SeekOrigin.Begin);
_writingStream.Seek((long)(0x40 + sectorAddress * _imageInfo.SectorSize), SeekOrigin.Begin);
_writingStream.Write(data, 0, data.Length);
ErrorMessage = "";
@@ -159,7 +163,7 @@ public sealed partial class Apple2Mg
return false;
}
_writingStream.Seek((long)(0x40 + (sectorAddress * _imageInfo.SectorSize)), SeekOrigin.Begin);
_writingStream.Seek((long)(0x40 + sectorAddress * _imageInfo.SectorSize), SeekOrigin.Begin);
_writingStream.Write(data, 0, data.Length);
ErrorMessage = "";
@@ -193,8 +197,8 @@ public sealed partial class Apple2Mg
return false;
}
_writingStream.Seek(0x40 + (17 * 16 * 256), SeekOrigin.Begin);
byte[] tmp = new byte[256];
_writingStream.Seek(0x40 + 17 * 16 * 256, SeekOrigin.Begin);
var tmp = new byte[256];
_writingStream.EnsureRead(tmp, 0, tmp.Length);
bool isDos = tmp[0x01] == 17 && tmp[0x02] < 16 && tmp[0x27] <= 122 && tmp[0x34] == 35 && tmp[0x35] == 16 &&
@@ -206,7 +210,8 @@ public sealed partial class Apple2Mg
Creator = CREATOR_AARU,
DataOffset = 0x40,
DataSize = (uint)(_imageInfo.Sectors * _imageInfo.SectorSize),
Flags = (uint)(_imageInfo.LastMediaSequence != 0 ? VALID_VOLUME_NUMBER + (_imageInfo.MediaSequence & 0xFF)
Flags = (uint)(_imageInfo.LastMediaSequence != 0
? VALID_VOLUME_NUMBER + (_imageInfo.MediaSequence & 0xFF)
: 0),
HeaderSize = 0x40,
ImageFormat = isDos ? SectorOrder.Dos : SectorOrder.ProDos,
@@ -224,8 +229,8 @@ public sealed partial class Apple2Mg
_writingStream.WriteByte(0);
}
byte[] hdr = new byte[Marshal.SizeOf<Header>()];
nint hdrPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(Marshal.SizeOf<Header>());
var hdr = new byte[Marshal.SizeOf<Header>()];
nint hdrPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(Marshal.SizeOf<Header>());
System.Runtime.InteropServices.Marshal.StructureToPtr(_imageHeader, hdrPtr, true);
System.Runtime.InteropServices.Marshal.Copy(hdrPtr, hdr, 0, hdr.Length);
System.Runtime.InteropServices.Marshal.FreeHGlobal(hdrPtr);
@@ -276,4 +281,6 @@ public sealed partial class Apple2Mg
/// <inheritdoc />
public bool SetMetadata(Metadata metadata) => false;
#endregion
}

View File

@@ -34,12 +34,6 @@ namespace Aaru.DiscImages;
public sealed partial class AppleDos
{
readonly int[] _deinterleave =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
};
readonly int[] _interleave =
{
0, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 15
};
readonly int[] _deinterleave = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
readonly int[] _interleave = { 0, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 15 };
}

View File

@@ -37,6 +37,8 @@ namespace Aaru.DiscImages;
public sealed partial class AppleDos
{
#region IWritableImage Members
/// <inheritdoc />
public bool Identify(IFilter imageFilter)
{
@@ -44,4 +46,6 @@ public sealed partial class AppleDos
return imageFilter.DataForkLength == 143360 && _extension is ".po" or ".do";
}
#endregion
}

View File

@@ -41,42 +41,52 @@ namespace Aaru.DiscImages;
public sealed partial class AppleDos
{
#region IWritableImage Members
/// <inheritdoc />
public ImageInfo Info => _imageInfo;
/// <inheritdoc />
public string Name => Localization.AppleDos_Name;
/// <inheritdoc />
public Guid Id => new("A5828AC0-62C9-4304-81D4-EFD4AAE47360");
/// <inheritdoc />
public string Author => Authors.NataliaPortillo;
/// <inheritdoc />
public string Format => _extension == ".po" ? "Apple ][ Interleaved Disk Image (ProDOS order)"
public string Format => _extension == ".po"
? "Apple ][ Interleaved Disk Image (ProDOS order)"
: "Apple ][ Interleaved Disk Image (DOS order)";
/// <inheritdoc />
public List<DumpHardware> DumpHardware => null;
/// <inheritdoc />
public Metadata AaruMetadata => null;
/// <inheritdoc />
public IEnumerable<MediaTagType> SupportedMediaTags => Array.Empty<MediaTagType>();
/// <inheritdoc />
public IEnumerable<SectorTagType> SupportedSectorTags => Array.Empty<SectorTagType>();
/// <inheritdoc />
public IEnumerable<MediaType> SupportedMediaTypes => new[]
{
MediaType.Apple33SS
};
public IEnumerable<MediaType> SupportedMediaTypes => new[] { MediaType.Apple33SS };
/// <inheritdoc />
public IEnumerable<(string name, Type type, string description, object @default)> SupportedOptions =>
Array.Empty<(string name, Type type, string description, object @default)>();
/// <inheritdoc />
public IEnumerable<string> KnownExtensions => new[]
{
".do", ".po"
};
public IEnumerable<string> KnownExtensions => new[] { ".do", ".po" };
/// <inheritdoc />
public bool IsWriting { get; private set; }
/// <inheritdoc />
public string ErrorMessage { get; private set; }
#endregion
}

View File

@@ -41,13 +41,15 @@ namespace Aaru.DiscImages;
public sealed partial class AppleDos
{
#region IWritableImage Members
/// <inheritdoc />
public ErrorNumber Open(IFilter imageFilter)
{
Stream stream = imageFilter.GetDataForkStream();
stream.Seek(0, SeekOrigin.Begin);
byte[] tmp = new byte[imageFilter.DataForkLength];
var tmp = new byte[imageFilter.DataForkLength];
stream.EnsureRead(tmp, 0, tmp.Length);
_extension = Path.GetExtension(imageFilter.Filename)?.ToLower();
@@ -71,11 +73,13 @@ public sealed partial class AppleDos
? _interleave
: _deinterleave;
for(int t = 0; t < 35; t++)
for(var t = 0; t < 35; t++)
{
for(int s = 0; s < 16; s++)
Array.Copy(tmp, (t * 16 * 256) + (s * 256), _deinterleaved, (t * 16 * 256) + (offsets[s] * 256),
for(var s = 0; s < 16; s++)
{
Array.Copy(tmp, t * 16 * 256 + s * 256, _deinterleaved, t * 16 * 256 + offsets[s] * 256,
256);
}
}
}
@@ -114,4 +118,6 @@ public sealed partial class AppleDos
return ErrorNumber.NoError;
}
#endregion
}

View File

@@ -36,6 +36,8 @@ namespace Aaru.DiscImages;
public sealed partial class AppleDos
{
#region IWritableImage Members
/// <inheritdoc />
public ErrorNumber ReadSectorTag(ulong sectorAddress, SectorTagType tag, out byte[] buffer)
{
@@ -75,4 +77,6 @@ public sealed partial class AppleDos
return ErrorNumber.NotSupported;
}
#endregion
}

View File

@@ -42,9 +42,11 @@ namespace Aaru.DiscImages;
public sealed partial class AppleDos
{
#region IWritableImage Members
/// <inheritdoc />
public bool Create(string path, MediaType mediaType, Dictionary<string, string> options, ulong sectors,
uint sectorSize)
uint sectorSize)
{
if(sectorSize != 256)
{
@@ -61,8 +63,8 @@ public sealed partial class AppleDos
return false;
}
if((mediaType == MediaType.Apple32SS && sectors != 455) ||
(mediaType == MediaType.Apple33SS && sectors != 560))
if(mediaType == MediaType.Apple32SS && sectors != 455 ||
mediaType == MediaType.Apple33SS && sectors != 560)
{
ErrorMessage = Localization.Incorrect_number_of_sectors_for_media;
@@ -189,10 +191,12 @@ public sealed partial class AppleDos
? _interleave
: _deinterleave;
for(int t = 0; t < 35; t++)
for(int s = 0; s < 16; s++)
Array.Copy(_deinterleaved, (t * 16 * 256) + (offsets[s] * 256), tmp, (t * 16 * 256) + (s * 256),
256);
for(var t = 0; t < 35; t++)
for(var s = 0; s < 16; s++)
{
Array.Copy(_deinterleaved, t * 16 * 256 + offsets[s] * 256, tmp, t * 16 * 256 + s * 256,
256);
}
}
_writingStream.Seek(0, SeekOrigin.Begin);
@@ -234,4 +238,6 @@ public sealed partial class AppleDos
/// <inheritdoc />
public bool SetMetadata(Metadata metadata) => false;
#endregion
}

View File

@@ -42,6 +42,7 @@ namespace Aaru.DiscImages;
/// <summary>Implements reading nibbelized Apple II disk images</summary>
public sealed partial class AppleNib : IMediaImage
{
const string MODULE_NAME = "Apple NIB Plugin";
Dictionary<ulong, byte[]> _addressFields;
Dictionary<ulong, byte[]> _cookedSectors;
ImageInfo _imageInfo;
@@ -70,6 +71,4 @@ public sealed partial class AppleNib : IMediaImage
DriveSerialNumber = null,
DriveFirmwareRevision = null
};
const string MODULE_NAME = "Apple NIB Plugin";
}

View File

@@ -37,39 +37,15 @@ namespace Aaru.DiscImages;
[SuppressMessage("ReSharper", "UnusedMember.Local")]
public sealed partial class AppleNib
{
readonly byte[] _apple3Sign =
{
0x8D, 0xD0, 0x03, 0x4C, 0xC7, 0xA4
};
readonly byte[] _cpmSign =
{
0xA2, 0x55, 0xA9, 0x00, 0x9D, 0x00, 0x0D, 0xCA
};
readonly byte[] _dosSign =
{
0xA2, 0x02, 0x8E, 0x52
};
readonly ulong[] _dosSkewing =
{
0, 7, 14, 6, 13, 5, 12, 4, 11, 3, 10, 2, 9, 1, 8, 15
};
readonly byte[] _driString = "COPYRIGHT (C) 1979, DIGITAL RESEARCH"u8.ToArray();
readonly byte[] _pascalSign =
{
0x08, 0xA5, 0x0F, 0x29
};
readonly byte[] _pascalString = "SYSTE.APPLE"u8.ToArray();
readonly byte[] _pascal2Sign =
{
0xFF, 0xA2, 0x00, 0x8E
};
readonly byte[] _prodosString = "PRODOS"u8.ToArray();
readonly ulong[] _proDosSkewing =
{
0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15
};
readonly byte[] _sosSign =
{
0xC9, 0x20, 0xF0, 0x3E
};
readonly byte[] _apple3Sign = { 0x8D, 0xD0, 0x03, 0x4C, 0xC7, 0xA4 };
readonly byte[] _cpmSign = { 0xA2, 0x55, 0xA9, 0x00, 0x9D, 0x00, 0x0D, 0xCA };
readonly byte[] _dosSign = { 0xA2, 0x02, 0x8E, 0x52 };
readonly ulong[] _dosSkewing = { 0, 7, 14, 6, 13, 5, 12, 4, 11, 3, 10, 2, 9, 1, 8, 15 };
readonly byte[] _driString = "COPYRIGHT (C) 1979, DIGITAL RESEARCH"u8.ToArray();
readonly byte[] _pascal2Sign = { 0xFF, 0xA2, 0x00, 0x8E };
readonly byte[] _pascalSign = { 0x08, 0xA5, 0x0F, 0x29 };
readonly byte[] _pascalString = "SYSTE.APPLE"u8.ToArray();
readonly ulong[] _proDosSkewing = { 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 };
readonly byte[] _prodosString = "PRODOS"u8.ToArray();
readonly byte[] _sosSign = { 0xC9, 0x20, 0xF0, 0x3E };
}

View File

@@ -39,6 +39,8 @@ namespace Aaru.DiscImages;
public sealed partial class AppleNib
{
#region IMediaImage Members
/// <inheritdoc />
public bool Identify(IFilter imageFilter)
{
@@ -48,9 +50,11 @@ public sealed partial class AppleNib
if(stream.Length < 512)
return false;
byte[] test = new byte[512];
var test = new byte[512];
stream.EnsureRead(test, 0, 512);
return Apple2.IsApple2GCR(test);
}
#endregion
}

View File

@@ -39,19 +39,28 @@ namespace Aaru.DiscImages;
public sealed partial class AppleNib
{
#region IMediaImage Members
/// <inheritdoc />
public ImageInfo Info => _imageInfo;
/// <inheritdoc />
public string Name => Localization.AppleNib_Name;
/// <inheritdoc />
public Guid Id => new("AE171AE8-6747-49CC-B861-9D450B7CD42E");
/// <inheritdoc />
public string Author => Authors.NataliaPortillo;
/// <inheritdoc />
public string Format => "Apple nibbles";
/// <inheritdoc />
public List<DumpHardware> DumpHardware => null;
/// <inheritdoc />
public Metadata AaruMetadata => null;
#endregion
}

View File

@@ -44,6 +44,8 @@ namespace Aaru.DiscImages;
public sealed partial class AppleNib
{
#region IMediaImage Members
/// <inheritdoc />
public ErrorNumber Open(IFilter imageFilter)
{
@@ -53,7 +55,7 @@ public sealed partial class AppleNib
if(stream.Length < 512)
return ErrorNumber.InvalidArgument;
byte[] buffer = new byte[stream.Length];
var buffer = new byte[stream.Length];
stream.EnsureRead(buffer, 0, buffer.Length);
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Decoding_whole_image);
@@ -62,10 +64,10 @@ public sealed partial class AppleNib
Dictionary<ulong, Apple2.RawSector> rawSectors = new();
int spt = 0;
bool allTracksEqual = true;
var spt = 0;
var allTracksEqual = true;
for(int i = 1; i < tracks.Count; i++)
for(var i = 1; i < tracks.Count; i++)
allTracksEqual &= tracks[i - 1].sectors.Length == tracks[i].sectors.Length;
if(allTracksEqual)
@@ -76,11 +78,12 @@ public sealed partial class AppleNib
// Detect ProDOS skewed disks
if(skewed)
{
foreach(bool isDos in from sector in tracks[17].sectors
where sector.addressField.sector.SequenceEqual(new byte[]
{
170, 170
}) select Apple2.DecodeSector(sector) into sector0 where sector0 != null
where sector.addressField.sector.SequenceEqual(new byte[] { 170, 170 })
select Apple2.DecodeSector(sector)
into sector0
where sector0 != null
select sector0[0x01] == 17 && sector0[0x02] < 16 && sector0[0x27] <= 122 &&
sector0[0x34] == 35 && sector0[0x35] == 16 && sector0[0x36] == 0 &&
sector0[0x37] == 1)
@@ -89,16 +92,20 @@ public sealed partial class AppleNib
skewing = _dosSkewing;
AaruConsole.DebugWriteLine(MODULE_NAME,
skewing.SequenceEqual(_dosSkewing) ? Localization.Using_DOS_skewing
skewing.SequenceEqual(_dosSkewing)
? Localization.Using_DOS_skewing
: Localization.Using_ProDOS_skewing);
}
}
for(int i = 0; i < tracks.Count; i++)
for(var i = 0; i < tracks.Count; i++)
{
foreach(Apple2.RawSector sector in tracks[i].sectors)
{
if(skewed && spt != 0)
{
ulong sectorNo = (ulong)((((sector.addressField.sector[0] & 0x55) << 1) |
(sector.addressField.sector[1] & 0x55)) & 0xFF);
var sectorNo = (ulong)(((sector.addressField.sector[0] & 0x55) << 1 |
sector.addressField.sector[1] & 0x55) & 0xFF);
AaruConsole.DebugWriteLine(MODULE_NAME,
Localization.Hardware_sector_0_of_track_1_goes_to_logical_sector_2,
@@ -112,6 +119,8 @@ public sealed partial class AppleNib
rawSectors.Add(_imageInfo.Sectors, sector);
_imageInfo.Sectors++;
}
}
}
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Got_0_sectors, _imageInfo.Sectors);
@@ -137,11 +146,11 @@ public sealed partial class AppleNib
_imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.Filename);
_imageInfo.MediaType = _imageInfo.Sectors switch
{
455 => MediaType.Apple32SS,
560 => MediaType.Apple33SS,
_ => MediaType.Unknown
};
{
455 => MediaType.Apple32SS,
560 => MediaType.Apple33SS,
_ => MediaType.Unknown
};
_imageInfo.SectorSize = 256;
_imageInfo.MetadataMediaType = MetadataMediaType.BlockMedia;
@@ -288,4 +297,6 @@ public sealed partial class AppleNib
return ErrorNumber.NoError;
}
#endregion
}

View File

@@ -36,6 +36,8 @@ namespace Aaru.DiscImages;
public sealed partial class AppleNib
{
#region IMediaImage Members
/// <inheritdoc />
public ErrorNumber ReadMediaTag(MediaTagType tag, out byte[] buffer)
{
@@ -43,4 +45,6 @@ public sealed partial class AppleNib
return ErrorNumber.NotSupported;
}
#endregion
}

View File

@@ -43,7 +43,8 @@ namespace Aaru.DiscImages;
/// <summary>Implements reading and writing Apridisk disk images</summary>
public sealed partial class Apridisk : IWritableImage
{
ImageInfo _imageInfo;
const string MODULE_NAME = "Apridisk plugin";
ImageInfo _imageInfo;
// Cylinder by head, sector data matrix
byte[][][][] _sectorsData;
@@ -72,6 +73,4 @@ public sealed partial class Apridisk : IWritableImage
DriveSerialNumber = null,
DriveFirmwareRevision = null
};
const string MODULE_NAME = "Apridisk plugin";
}

View File

@@ -39,7 +39,7 @@ public sealed partial class Apridisk
{
static uint Decompress(byte[] compressed, out byte[] decompressed)
{
int readp = 0;
var readp = 0;
int cLen = compressed.Length;
var buffer = new MemoryStream();
@@ -47,10 +47,10 @@ public sealed partial class Apridisk
while(cLen >= 3)
{
ushort blklen = BitConverter.ToUInt16(compressed, readp);
var blklen = BitConverter.ToUInt16(compressed, readp);
readp += 2;
for(int i = 0; i < blklen; i++)
for(var i = 0; i < blklen; i++)
buffer.WriteByte(compressed[readp]);
uLen += blklen;

View File

@@ -34,14 +34,25 @@ namespace Aaru.DiscImages;
public sealed partial class Apridisk
{
enum RecordType : uint
{
Deleted = 0xE31D0000, Sector = 0xE31D0001, Comment = 0xE31D0002,
Creator = 0xE31D0003
}
#region Nested type: CompressType
enum CompressType : ushort
{
Uncompresed = 0x9E90, Compressed = 0x3E5A
Uncompresed = 0x9E90,
Compressed = 0x3E5A
}
#endregion
#region Nested type: RecordType
enum RecordType : uint
{
Deleted = 0xE31D0000,
Sector = 0xE31D0001,
Comment = 0xE31D0002,
Creator = 0xE31D0003
}
#endregion
}

View File

@@ -36,9 +36,9 @@ public sealed partial class Apridisk
{
(ushort cylinder, byte head, byte sector) LbaToChs(ulong lba)
{
ushort cylinder = (ushort)(lba / (_imageInfo.Heads * _imageInfo.SectorsPerTrack));
byte head = (byte)(lba / _imageInfo.SectorsPerTrack % _imageInfo.Heads);
byte sector = (byte)((lba % _imageInfo.SectorsPerTrack) + 1);
var cylinder = (ushort)(lba / (_imageInfo.Heads * _imageInfo.SectorsPerTrack));
var head = (byte)(lba / _imageInfo.SectorsPerTrack % _imageInfo.Heads);
var sector = (byte)(lba % _imageInfo.SectorsPerTrack + 1);
return (cylinder, head, sector);
}

View File

@@ -39,6 +39,8 @@ namespace Aaru.DiscImages;
public sealed partial class Apridisk
{
#region IWritableImage Members
/// <inheritdoc />
public bool Identify(IFilter imageFilter)
{
@@ -48,9 +50,11 @@ public sealed partial class Apridisk
if(stream.Length < _signature.Length)
return false;
byte[] sigB = new byte[_signature.Length];
var sigB = new byte[_signature.Length];
stream.EnsureRead(sigB, 0, _signature.Length);
return sigB.SequenceEqual(_signature);
}
#endregion
}

View File

@@ -41,25 +41,32 @@ namespace Aaru.DiscImages;
public sealed partial class Apridisk
{
#region IWritableImage Members
/// <inheritdoc />
public ImageInfo Info => _imageInfo;
/// <inheritdoc />
public string Name => Localization.Apridisk_Name;
/// <inheritdoc />
public Guid Id => new("43408CF3-6DB3-449F-A779-2B0E497C5B14");
/// <inheritdoc />
public string Author => Authors.NataliaPortillo;
/// <inheritdoc />
public string Format => "ACT Apricot disk image";
/// <inheritdoc />
public List<DumpHardware> DumpHardware => null;
/// <inheritdoc />
public Metadata AaruMetadata => null;
/// <inheritdoc />
public IEnumerable<MediaTagType> SupportedMediaTags => Array.Empty<MediaTagType>();
/// <inheritdoc />
public IEnumerable<SectorTagType> SupportedSectorTags => Array.Empty<SectorTagType>();
@@ -69,24 +76,27 @@ public sealed partial class Apridisk
{
MediaType.ACORN_35_DS_DD, MediaType.ACORN_35_DS_HD, MediaType.Apricot_35, MediaType.ATARI_35_DS_DD,
MediaType.ATARI_35_DS_DD_11, MediaType.ATARI_35_SS_DD, MediaType.ATARI_35_SS_DD_11, MediaType.DMF,
MediaType.DMF_82, MediaType.DOS_35_DS_DD_8, MediaType.DOS_35_DS_DD_9, MediaType.DOS_35_ED, MediaType.DOS_35_HD,
MediaType.DOS_35_SS_DD_8, MediaType.DOS_35_SS_DD_9, MediaType.DOS_525_DS_DD_8, MediaType.DOS_525_DS_DD_9,
MediaType.DOS_525_HD, MediaType.DOS_525_SS_DD_8, MediaType.DOS_525_SS_DD_9, MediaType.FDFORMAT_35_DD,
MediaType.FDFORMAT_35_HD, MediaType.FDFORMAT_525_DD, MediaType.FDFORMAT_525_HD, MediaType.RX50,
MediaType.XDF_35, MediaType.XDF_525, MediaType.MetaFloppy_Mod_I, MediaType.MetaFloppy_Mod_II
MediaType.DMF_82, MediaType.DOS_35_DS_DD_8, MediaType.DOS_35_DS_DD_9, MediaType.DOS_35_ED,
MediaType.DOS_35_HD, MediaType.DOS_35_SS_DD_8, MediaType.DOS_35_SS_DD_9, MediaType.DOS_525_DS_DD_8,
MediaType.DOS_525_DS_DD_9, MediaType.DOS_525_HD, MediaType.DOS_525_SS_DD_8, MediaType.DOS_525_SS_DD_9,
MediaType.FDFORMAT_35_DD, MediaType.FDFORMAT_35_HD, MediaType.FDFORMAT_525_DD, MediaType.FDFORMAT_525_HD,
MediaType.RX50, MediaType.XDF_35, MediaType.XDF_525, MediaType.MetaFloppy_Mod_I, MediaType.MetaFloppy_Mod_II
};
/// <inheritdoc />
public IEnumerable<(string name, Type type, string description, object @default)> SupportedOptions => new[]
{
("compress", typeof(bool), Localization.Enable_Apridisk_compression, (object)false)
};
/// <inheritdoc />
public IEnumerable<string> KnownExtensions => new[]
{
".dsk"
};
public IEnumerable<string> KnownExtensions => new[] { ".dsk" };
/// <inheritdoc />
public bool IsWriting { get; private set; }
/// <inheritdoc />
public string ErrorMessage { get; private set; }
#endregion
}

View File

@@ -41,6 +41,8 @@ namespace Aaru.DiscImages;
public sealed partial class Apridisk
{
#region IWritableImage Members
/// <inheritdoc />
public ErrorNumber Open(IFilter imageFilter)
{
@@ -58,7 +60,7 @@ public sealed partial class Apridisk
// Count cylinders
while(stream.Position < stream.Length)
{
byte[] recB = new byte[recordSize];
var recB = new byte[recordSize];
stream.EnsureRead(recB, 0, recordSize);
Record record = Marshal.SpanToStructureLittleEndian<Record>(recB);
@@ -78,7 +80,7 @@ public sealed partial class Apridisk
stream.Position);
stream.Seek(record.headerSize - recordSize, SeekOrigin.Current);
byte[] commentB = new byte[record.dataSize];
var commentB = new byte[record.dataSize];
stream.EnsureRead(commentB, 0, commentB.Length);
_imageInfo.Comments = StringHandlers.CToString(commentB);
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Comment_0, _imageInfo.Comments);
@@ -89,7 +91,7 @@ public sealed partial class Apridisk
stream.Position);
stream.Seek(record.headerSize - recordSize, SeekOrigin.Current);
byte[] creatorB = new byte[record.dataSize];
var creatorB = new byte[record.dataSize];
stream.EnsureRead(creatorB, 0, creatorB.Length);
_imageInfo.Creator = StringHandlers.CToString(creatorB);
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Creator_0, _imageInfo.Creator);
@@ -120,7 +122,8 @@ public sealed partial class Apridisk
stream.Seek(record.headerSize - recordSize + record.dataSize, SeekOrigin.Current);
break;
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
}
@@ -134,7 +137,7 @@ public sealed partial class Apridisk
_sectorsData = new byte[totalCylinders][][][];
// Total sectors per track
uint[][] spts = new uint[totalCylinders][];
var spts = new uint[totalCylinders][];
_imageInfo.Cylinders = (ushort)totalCylinders;
_imageInfo.Heads = (byte)totalHeads;
@@ -144,12 +147,12 @@ public sealed partial class Apridisk
totalCylinders, totalHeads, maxSector);
// Create heads
for(int i = 0; i < totalCylinders; i++)
for(var i = 0; i < totalCylinders; i++)
{
_sectorsData[i] = new byte[totalHeads][][];
spts[i] = new uint[totalHeads];
for(int j = 0; j < totalHeads; j++)
for(var j = 0; j < totalHeads; j++)
_sectorsData[i][j] = new byte[maxSector + 1][];
}
@@ -162,7 +165,7 @@ public sealed partial class Apridisk
while(stream.Position < stream.Length)
{
byte[] recB = new byte[recordSize];
var recB = new byte[recordSize];
stream.EnsureRead(recB, 0, recordSize);
Record record = Marshal.SpanToStructureLittleEndian<Record>(recB);
@@ -180,7 +183,7 @@ public sealed partial class Apridisk
case RecordType.Sector:
stream.Seek(record.headerSize - recordSize, SeekOrigin.Current);
byte[] data = new byte[record.dataSize];
var data = new byte[record.dataSize];
stream.EnsureRead(data, 0, data.Length);
spts[record.cylinder][record.head]++;
@@ -209,8 +212,10 @@ public sealed partial class Apridisk
for(ushort cyl = 0; cyl < _imageInfo.Cylinders; cyl++)
{
for(ushort head = 0; head < _imageInfo.Heads; head++)
{
if(spts[cyl][head] < spt)
spt = spts[cyl][head];
}
}
_imageInfo.SectorsPerTrack = spt;
@@ -279,4 +284,6 @@ public sealed partial class Apridisk
return ErrorNumber.NoError;
}
#endregion
}

View File

@@ -36,6 +36,8 @@ namespace Aaru.DiscImages;
public sealed partial class Apridisk
{
#region Nested type: Record
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct Record
{
@@ -47,4 +49,6 @@ public sealed partial class Apridisk
public byte sector;
public ushort cylinder;
}
#endregion
}

View File

@@ -36,6 +36,8 @@ namespace Aaru.DiscImages;
public sealed partial class Apridisk
{
#region IWritableImage Members
/// <inheritdoc />
public ErrorNumber ReadMediaTag(MediaTagType tag, out byte[] buffer)
{
@@ -75,4 +77,6 @@ public sealed partial class Apridisk
return ErrorNumber.NotSupported;
}
#endregion
}

View File

@@ -45,9 +45,11 @@ namespace Aaru.DiscImages;
public sealed partial class Apridisk
{
#region IWritableImage Members
/// <inheritdoc />
public bool Create(string path, MediaType mediaType, Dictionary<string, string> options, ulong sectors,
uint sectorSize)
uint sectorSize)
{
if(!SupportedMediaTypes.Contains(mediaType))
{
@@ -176,7 +178,7 @@ public sealed partial class Apridisk
_writingStream.Seek(0, SeekOrigin.Begin);
_writingStream.Write(_signature, 0, _signature.Length);
byte[] hdr = new byte[Marshal.SizeOf<Record>()];
var hdr = new byte[Marshal.SizeOf<Record>()];
for(ushort c = 0; c < _imageInfo.Cylinders; c++)
{
@@ -201,7 +203,7 @@ public sealed partial class Apridisk
MemoryMarshal.Write(hdr, in record);
_writingStream.Write(hdr, 0, hdr.Length);
_writingStream.Write(hdr, 0, hdr.Length);
_writingStream.Write(_sectorsData[c][h][s], 0, _sectorsData[c][h][s].Length);
}
}
@@ -224,7 +226,7 @@ public sealed partial class Apridisk
MemoryMarshal.Write(hdr, in creatorRecord);
_writingStream.Write(hdr, 0, hdr.Length);
_writingStream.Write(hdr, 0, hdr.Length);
_writingStream.Write(creatorBytes, 0, creatorBytes.Length);
_writingStream.WriteByte(0); // Termination
}
@@ -246,7 +248,7 @@ public sealed partial class Apridisk
MemoryMarshal.Write(hdr, in commentRecord);
_writingStream.Write(hdr, 0, hdr.Length);
_writingStream.Write(hdr, 0, hdr.Length);
_writingStream.Write(commentBytes, 0, commentBytes.Length);
_writingStream.WriteByte(0); // Termination
}
@@ -331,4 +333,6 @@ public sealed partial class Apridisk
/// <inheritdoc />
public bool SetMetadata(Metadata metadata) => false;
#endregion
}

View File

@@ -42,11 +42,12 @@ namespace Aaru.DiscImages;
/// <summary>Implements reading Basic Lisa Utility disk images</summary>
public sealed partial class Blu : IWritableImage, IVerifiableSectorsImage
{
IFilter _bluImageFilter;
int _bptag;
BluHeader _imageHeader;
ImageInfo _imageInfo;
FileStream _writingStream;
const string MODULE_NAME = "BLU plugin";
IFilter _bluImageFilter;
int _bptag;
BluHeader _imageHeader;
ImageInfo _imageInfo;
FileStream _writingStream;
public Blu() => _imageInfo = new ImageInfo
{
@@ -72,6 +73,8 @@ public sealed partial class Blu : IWritableImage, IVerifiableSectorsImage
DriveFirmwareRevision = null
};
#region Nested type: BluHeader
struct BluHeader
{
public byte[] DeviceName;
@@ -80,5 +83,5 @@ public sealed partial class Blu : IWritableImage, IVerifiableSectorsImage
public ushort BytesPerBlock;
}
const string MODULE_NAME = "BLU plugin";
#endregion
}

View File

@@ -39,6 +39,8 @@ namespace Aaru.DiscImages;
public sealed partial class Blu
{
#region IWritableImage Members
/// <inheritdoc />
public bool Identify(IFilter imageFilter)
{
@@ -48,7 +50,7 @@ public sealed partial class Blu
if(stream.Length < 0x200)
return false;
byte[] header = new byte[0x17];
var header = new byte[0x17];
stream.EnsureRead(header, 0, 0x17);
var tmpHdr = new BluHeader
@@ -61,10 +63,14 @@ public sealed partial class Blu
tmpHdr.DeviceBlocks = BigEndianBitConverter.ToUInt32(header, 0x11) & 0x00FFFFFF;
tmpHdr.BytesPerBlock = BigEndianBitConverter.ToUInt16(header, 0x15);
for(int i = 0; i < 0xD; i++)
for(var i = 0; i < 0xD; i++)
{
if(tmpHdr.DeviceName[i] < 0x20)
return false;
}
return (tmpHdr.BytesPerBlock & 0xFE00) == 0x200;
}
#endregion
}

View File

@@ -41,27 +41,35 @@ namespace Aaru.DiscImages;
public sealed partial class Blu
{
#region IWritableImage Members
/// <inheritdoc />
public ImageInfo Info => _imageInfo;
/// <inheritdoc />
public string Name => Localization.Blu_Name;
/// <inheritdoc />
public Guid Id => new("A153E2F8-4235-432D-9A7F-20807B0BCD74");
/// <inheritdoc />
public string Author => Authors.NataliaPortillo;
/// <inheritdoc />
public string Format => "Basic Lisa Utility";
/// <inheritdoc />
public List<DumpHardware> DumpHardware => null;
/// <inheritdoc />
public Metadata AaruMetadata => null;
/// <inheritdoc />
public IEnumerable<MediaTagType> SupportedMediaTags => Array.Empty<MediaTagType>();
/// <inheritdoc />
public IEnumerable<SectorTagType> SupportedSectorTags => new[]
{
SectorTagType.AppleSectorTag
};
public IEnumerable<SectorTagType> SupportedSectorTags => new[] { SectorTagType.AppleSectorTag };
/// <inheritdoc />
public IEnumerable<MediaType> SupportedMediaTypes => new[]
{
@@ -69,16 +77,19 @@ public sealed partial class Blu
MediaType.Unknown, MediaType.FlashDrive, MediaType.CompactFlash, MediaType.CompactFlashType2,
MediaType.PCCardTypeI, MediaType.PCCardTypeII, MediaType.PCCardTypeIII, MediaType.PCCardTypeIV
};
/// <inheritdoc />
public IEnumerable<(string name, Type type, string description, object @default)> SupportedOptions =>
Array.Empty<(string name, Type type, string description, object @default)>();
/// <inheritdoc />
public IEnumerable<string> KnownExtensions => new[]
{
".blu"
}; // Just invented
public IEnumerable<string> KnownExtensions => new[] { ".blu" }; // Just invented
/// <inheritdoc />
public bool IsWriting { get; private set; }
/// <inheritdoc />
public string ErrorMessage { get; private set; }
#endregion
}

View File

@@ -42,6 +42,8 @@ namespace Aaru.DiscImages;
public sealed partial class Blu
{
#region IWritableImage Members
/// <inheritdoc />
public ErrorNumber Open(IFilter imageFilter)
{
@@ -53,7 +55,7 @@ public sealed partial class Blu
DeviceName = new byte[0x0D]
};
byte[] header = new byte[0x17];
var header = new byte[0x17];
stream.EnsureRead(header, 0, 0x17);
Array.Copy(header, 0, _imageHeader.DeviceName, 0, 0x0D);
_imageHeader.DeviceType = BigEndianBitConverter.ToUInt32(header, 0x0C) & 0x00FFFFFF;
@@ -63,13 +65,15 @@ public sealed partial class Blu
AaruConsole.DebugWriteLine(MODULE_NAME, "ImageHeader.deviceName = \"{0}\"",
StringHandlers.CToString(_imageHeader.DeviceName));
AaruConsole.DebugWriteLine(MODULE_NAME, "ImageHeader.deviceType = {0}", _imageHeader.DeviceType);
AaruConsole.DebugWriteLine(MODULE_NAME, "ImageHeader.deviceBlock = {0}", _imageHeader.DeviceBlocks);
AaruConsole.DebugWriteLine(MODULE_NAME, "ImageHeader.deviceType = {0}", _imageHeader.DeviceType);
AaruConsole.DebugWriteLine(MODULE_NAME, "ImageHeader.deviceBlock = {0}", _imageHeader.DeviceBlocks);
AaruConsole.DebugWriteLine(MODULE_NAME, "ImageHeader.bytesPerBlock = {0}", _imageHeader.BytesPerBlock);
for(int i = 0; i < 0xD; i++)
for(var i = 0; i < 0xD; i++)
{
if(_imageHeader.DeviceName[i] < 0x20)
return ErrorNumber.InvalidArgument;
}
if((_imageHeader.BytesPerBlock & 0xFE00) != 0x200)
return ErrorNumber.InvalidArgument;
@@ -83,7 +87,7 @@ public sealed partial class Blu
_imageInfo.Sectors = _imageHeader.DeviceBlocks;
_imageInfo.ImageSize = _imageHeader.DeviceBlocks * _imageHeader.BytesPerBlock;
_bptag = _imageHeader.BytesPerBlock - 0x200;
byte[] hdrTag = new byte[_bptag];
var hdrTag = new byte[_bptag];
Array.Copy(header, 0x200, hdrTag, 0, _bptag);
switch(StringHandlers.CToString(_imageHeader.DeviceName))
@@ -113,7 +117,8 @@ public sealed partial class Blu
break;
case PRIAM_NAME:
_imageInfo.MediaType = _imageInfo.Sectors == 0x022C7C ? MediaType.PriamDataTower
_imageInfo.MediaType = _imageInfo.Sectors == 0x022C7C
? MediaType.PriamDataTower
: MediaType.GENERIC_HDD;
// This values are invented...
@@ -174,9 +179,9 @@ public sealed partial class Blu
Stream stream = _bluImageFilter.GetDataForkStream();
stream.Seek((long)((sectorAddress + 1) * _imageHeader.BytesPerBlock), SeekOrigin.Begin);
for(int i = 0; i < length; i++)
for(var i = 0; i < length; i++)
{
byte[] sector = new byte[read];
var sector = new byte[read];
stream.EnsureRead(sector, 0, read);
ms.Write(sector, 0, read);
stream.Seek(skip, SeekOrigin.Current);
@@ -211,10 +216,10 @@ public sealed partial class Blu
Stream stream = _bluImageFilter.GetDataForkStream();
stream.Seek((long)((sectorAddress + 1) * _imageHeader.BytesPerBlock), SeekOrigin.Begin);
for(int i = 0; i < length; i++)
for(var i = 0; i < length; i++)
{
stream.Seek(seek, SeekOrigin.Current);
byte[] sector = new byte[read];
var sector = new byte[read];
stream.EnsureRead(sector, 0, read);
ms.Write(sector, 0, read);
}
@@ -246,4 +251,6 @@ public sealed partial class Blu
return ErrorNumber.NoError;
}
#endregion
}

View File

@@ -36,6 +36,8 @@ namespace Aaru.DiscImages;
public sealed partial class Blu
{
#region IWritableImage Members
/// <inheritdoc />
public ErrorNumber ReadMediaTag(MediaTagType tag, out byte[] buffer)
{
@@ -43,4 +45,6 @@ public sealed partial class Blu
return ErrorNumber.NotSupported;
}
#endregion
}

View File

@@ -36,12 +36,14 @@ namespace Aaru.DiscImages;
public sealed partial class Blu
{
#region IVerifiableSectorsImage Members
// TODO: Check tag checksums
/// <inheritdoc />
public bool? VerifySector(ulong sectorAddress) => null;
/// <inheritdoc />
public bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas,
public bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
@@ -52,4 +54,6 @@ public sealed partial class Blu
return null;
}
#endregion
}

View File

@@ -47,9 +47,11 @@ namespace Aaru.DiscImages;
public sealed partial class Blu
{
#region IWritableImage Members
/// <inheritdoc />
public bool Create(string path, MediaType mediaType, Dictionary<string, string> options, ulong sectors,
uint sectorSize)
uint sectorSize)
{
if(sectorSize != 512)
{
@@ -130,7 +132,7 @@ public sealed partial class Blu
return false;
}
_writingStream.Seek(longSectorSize + ((long)sectorAddress * longSectorSize), SeekOrigin.Begin);
_writingStream.Seek(longSectorSize + (long)sectorAddress * longSectorSize, SeekOrigin.Begin);
_writingStream.Write(data, 0, data.Length);
ErrorMessage = "";
@@ -164,7 +166,7 @@ public sealed partial class Blu
return false;
}
_writingStream.Seek(longSectorSize + ((long)sectorAddress * longSectorSize), SeekOrigin.Begin);
_writingStream.Seek(longSectorSize + (long)sectorAddress * longSectorSize, SeekOrigin.Begin);
_writingStream.Write(data, 0, data.Length);
ErrorMessage = "";
@@ -253,8 +255,8 @@ public sealed partial class Blu
newTag ??= new byte[longSectorSize - 512];
_writingStream.Seek(longSectorSize + ((long)sectorAddress * longSectorSize), SeekOrigin.Begin);
_writingStream.Write(data, 0, 512);
_writingStream.Seek(longSectorSize + (long)sectorAddress * longSectorSize, SeekOrigin.Begin);
_writingStream.Write(data, 0, 512);
_writingStream.Write(newTag, 0, newTag.Length);
ErrorMessage = "";
@@ -287,7 +289,8 @@ public sealed partial class Blu
case 536:
case 532:
case 524:
case 512: break;
case 512:
break;
default:
ErrorMessage = Localization.Incorrect_data_size;
@@ -304,7 +307,7 @@ public sealed partial class Blu
// Sony tag, convert to Profile
case 12 when longSectorSize == 532:
oldTag = new byte[12];
Array.Copy(data, (givenSectorSize * i) + 512, oldTag, 0, 12);
Array.Copy(data, givenSectorSize * i + 512, oldTag, 0, 12);
newTag = LisaTag.DecodeSonyTag(oldTag)?.ToProfile().GetBytes();
break;
@@ -312,7 +315,7 @@ public sealed partial class Blu
// Sony tag, convert to Priam
case 12:
oldTag = new byte[12];
Array.Copy(data, (givenSectorSize * i) + 512, oldTag, 0, 12);
Array.Copy(data, givenSectorSize * i + 512, oldTag, 0, 12);
newTag = LisaTag.DecodeSonyTag(oldTag)?.ToPriam().GetBytes();
break;
@@ -320,14 +323,14 @@ public sealed partial class Blu
// Profile tag, copy to Profile
case 20 when longSectorSize == 532:
newTag = new byte[20];
Array.Copy(data, (givenSectorSize * i) + 512, newTag, 0, 20);
Array.Copy(data, givenSectorSize * i + 512, newTag, 0, 20);
break;
// Profile tag, convert to Priam
case 20:
oldTag = new byte[20];
Array.Copy(data, (givenSectorSize * i) + 512, oldTag, 0, 20);
Array.Copy(data, givenSectorSize * i + 512, oldTag, 0, 20);
newTag = LisaTag.DecodeProfileTag(oldTag)?.ToPriam().GetBytes();
break;
@@ -335,7 +338,7 @@ public sealed partial class Blu
// Priam tag, convert to Profile
case 24 when longSectorSize == 532:
oldTag = new byte[24];
Array.Copy(data, (givenSectorSize * i) + 512, oldTag, 0, 24);
Array.Copy(data, givenSectorSize * i + 512, oldTag, 0, 24);
newTag = LisaTag.DecodePriamTag(oldTag)?.ToProfile().GetBytes();
break;
@@ -343,7 +346,7 @@ public sealed partial class Blu
// Priam tag, copy to Priam
case 24:
newTag = new byte[24];
Array.Copy(data, (givenSectorSize * i) + 512, newTag, 0, 24);
Array.Copy(data, givenSectorSize * i + 512, newTag, 0, 24);
break;
case 0:
@@ -358,9 +361,9 @@ public sealed partial class Blu
newTag ??= new byte[longSectorSize - 512];
_writingStream.Seek(longSectorSize + ((long)sectorAddress * longSectorSize), SeekOrigin.Begin);
_writingStream.Write(data, (int)(givenSectorSize * i), 512);
_writingStream.Write(newTag, 0, newTag.Length);
_writingStream.Seek(longSectorSize + (long)sectorAddress * longSectorSize, SeekOrigin.Begin);
_writingStream.Write(data, (int)(givenSectorSize * i), 512);
_writingStream.Write(newTag, 0, newTag.Length);
}
ErrorMessage = "";
@@ -380,7 +383,7 @@ public sealed partial class Blu
byte[] markerTag = Encoding.UTF8.GetBytes("Aaru " + Version.GetVersion());
byte[] driveName;
byte[] driveType = new byte[3];
var driveType = new byte[3];
byte[] driveBlocks = BigEndianBitConverter.GetBytes((uint)_imageInfo.Sectors);
int longSectorSize = _imageInfo.MediaType == MediaType.PriamDataTower ? 536 : 532;
byte[] blockSize = BigEndianBitConverter.GetBytes((ushort)longSectorSize);
@@ -456,4 +459,6 @@ public sealed partial class Blu
/// <inheritdoc />
public bool SetMetadata(Metadata metadata) => false;
#endregion
}

View File

@@ -43,6 +43,7 @@ namespace Aaru.DiscImages;
/// <summary>Implements reading BlindWrite 4 disc images</summary>
public sealed partial class BlindWrite4 : IOpticalMediaImage
{
const string MODULE_NAME = "BlindWrite4 plugin";
List<TrackDescriptor> _bwTracks;
IFilter _dataFilter, _subFilter;
Header _header;
@@ -71,6 +72,4 @@ public sealed partial class BlindWrite4 : IOpticalMediaImage
DriveSerialNumber = null,
DriveFirmwareRevision = null
};
const string MODULE_NAME = "BlindWrite4 plugin";
}

View File

@@ -34,8 +34,14 @@ namespace Aaru.DiscImages;
public sealed partial class BlindWrite4
{
#region Nested type: TrackType
enum TrackType : byte
{
Audio = 0, Mode1 = 1, Mode2 = 2
Audio = 0,
Mode1 = 1,
Mode2 = 2
}
#endregion
}

View File

@@ -39,6 +39,8 @@ namespace Aaru.DiscImages;
public sealed partial class BlindWrite4
{
#region IOpticalMediaImage Members
/// <inheritdoc />
public bool Identify(IFilter imageFilter)
{
@@ -48,9 +50,11 @@ public sealed partial class BlindWrite4
if(stream.Length < 19)
return false;
byte[] signature = new byte[19];
var signature = new byte[19];
stream.EnsureRead(signature, 0, 19);
return _bw4Signature.SequenceEqual(signature);
}
#endregion
}

View File

@@ -41,15 +41,20 @@ namespace Aaru.DiscImages;
public sealed partial class BlindWrite4
{
#region IOpticalMediaImage Members
/// <inheritdoc />
public ImageInfo Info => _imageInfo;
/// <inheritdoc />
public string Name => Localization.BlindWrite4_Name;
/// <inheritdoc />
public Guid Id => new("664568B2-15D4-4E64-8A7A-20BDA8B8386F");
/// <inheritdoc />
public string Author => Authors.NataliaPortillo;
/// <inheritdoc />
public string Format => "BlindWrite 4 TOC file";
@@ -61,8 +66,12 @@ public sealed partial class BlindWrite4
/// <inheritdoc />
public List<Session> Sessions { get; set; }
/// <inheritdoc />
public List<DumpHardware> DumpHardware => null;
/// <inheritdoc />
public Metadata AaruMetadata => null;
#endregion
}

View File

@@ -49,6 +49,8 @@ namespace Aaru.DiscImages;
public sealed partial class BlindWrite4
{
#region IOpticalMediaImage Members
/// <inheritdoc />
public ErrorNumber Open(IFilter imageFilter)
{
@@ -58,10 +60,10 @@ public sealed partial class BlindWrite4
if(stream.Length < 19)
return ErrorNumber.InvalidArgument;
byte[] tmpArray = new byte[19];
byte[] tmpUShort = new byte[2];
byte[] tmpUInt = new byte[4];
byte[] tmpULong = new byte[8];
var tmpArray = new byte[19];
var tmpUShort = new byte[2];
var tmpUInt = new byte[4];
var tmpULong = new byte[8];
stream.EnsureRead(tmpArray, 0, 19);
@@ -129,31 +131,31 @@ public sealed partial class BlindWrite4
AaruConsole.DebugWriteLine(MODULE_NAME, "header.signature = {0}",
StringHandlers.CToString(_header.Signature));
AaruConsole.DebugWriteLine(MODULE_NAME, "header.unknown1 = {0}", _header.Unknown1);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.timestamp = {0}", _header.Timestamp);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.volumeIdLength = {0}", _header.VolumeIdLength);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.unknown1 = {0}", _header.Unknown1);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.timestamp = {0}", _header.Timestamp);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.volumeIdLength = {0}", _header.VolumeIdLength);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.volumeIdentifier = {0}", _header.VolumeIdentifier);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.sysIdLength = {0}", _header.SysIdLength);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.sysIdLength = {0}", _header.SysIdLength);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.systemIdentifier = {0}", _header.SystemIdentifier);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.commentsLength = {0}", _header.CommentsLength);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.comments = {0}", _header.Comments);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.commentsLength = {0}", _header.CommentsLength);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.comments = {0}", _header.Comments);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.trackDescriptors = {0}", _header.TrackDescriptors);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.dataFileLength = {0}", _header.DataFileLength);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.dataFilter = {0}", _header.DataFilter);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.dataFile = {0}", _header.DataFile);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.dataFileLength = {0}", _header.DataFileLength);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.dataFilter = {0}", _header.DataFilter);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.dataFile = {0}", _header.DataFile);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.subchannelFileLength = {0}",
_header.SubchannelFileLength);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.subchannelFilter = {0}", _header.SubchannelFilter);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.subchannelFile = {0}", _header.SubchannelFile);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.unknown2 = {0}", _header.Unknown2);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.unknown3 = {0}", _header.Unknown3);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.unknown4.Length = {0}", _header.Unknown4.Length);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.subchannelFile = {0}", _header.SubchannelFile);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.unknown2 = {0}", _header.Unknown2);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.unknown3 = {0}", _header.Unknown3);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.unknown4.Length = {0}", _header.Unknown4.Length);
_bwTracks = new List<TrackDescriptor>();
for(int i = 0; i < _header.TrackDescriptors; i++)
for(var i = 0; i < _header.TrackDescriptors; i++)
{
AaruConsole.DebugWriteLine(MODULE_NAME, "stream.Position = {0}", stream.Position);
@@ -210,7 +212,7 @@ public sealed partial class BlindWrite4
track.unknown13 = new uint[2];
for(int j = 0; j < track.unknown13.Length; j++)
for(var j = 0; j < track.unknown13.Length; j++)
{
stream.EnsureRead(tmpUInt, 0, 4);
track.unknown13[j] = BitConverter.ToUInt32(tmpUInt, 0);
@@ -322,67 +324,71 @@ public sealed partial class BlindWrite4
track.isrcUpc = StringHandlers.CToString(track.isrcBytes, Encoding.Default);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.filenameLen = {0}", track.filenameLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.filename = {0}", track.filename);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.offset = {0}", track.offset);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.subchannel = {0}", track.subchannel);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.filename = {0}", track.filename);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.offset = {0}", track.offset);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.subchannel = {0}", track.subchannel);
for(int j = 0; j < track.unknown1.Length; j++)
for(var j = 0; j < track.unknown1.Length; j++)
{
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unknown1[{1}] = 0x{0:X8}", track.unknown1[j],
j);
}
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unknown2 = {0}", track.unknown2);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unknown3 = {0}", track.unknown3);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.session = {0}", track.session);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unknown4 = {0}", track.unknown4);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.adrCtl = {0}", track.adrCtl);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unknown5 = {0}", track.unknown5);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.trackMode = {0}", track.trackMode);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unknown6 = {0}", track.unknown6);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.point = {0}", track.point);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unknown7 = {0}", track.unknown7);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unknown8 = {0}", track.unknown8);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unknown9 = {0}", track.pregapOffsetAdjustment);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unknown10 = {0}", track.unknown10);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unknown11 = {0}", track.unknown11);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.lastSector = {0}", track.lastSector);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unknown12 = {0}", track.unknown12);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.pregap = {0}", track.pregap);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unknown2 = {0}", track.unknown2);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unknown3 = {0}", track.unknown3);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.session = {0}", track.session);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unknown4 = {0}", track.unknown4);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.adrCtl = {0}", track.adrCtl);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unknown5 = {0}", track.unknown5);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.trackMode = {0}", track.trackMode);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unknown6 = {0}", track.unknown6);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.point = {0}", track.point);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unknown7 = {0}", track.unknown7);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unknown8 = {0}", track.unknown8);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unknown9 = {0}", track.pregapOffsetAdjustment);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unknown10 = {0}", track.unknown10);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unknown11 = {0}", track.unknown11);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.lastSector = {0}", track.lastSector);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unknown12 = {0}", track.unknown12);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.pregap = {0}", track.pregap);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.startSector = {0}", track.startSector);
for(int j = 0; j < track.unknown13.Length; j++)
for(var j = 0; j < track.unknown13.Length; j++)
{
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unknown13[{1}] = 0x{0:X8}", track.unknown13[j],
j);
}
AaruConsole.DebugWriteLine(MODULE_NAME, "track.titleLen = {0}", track.titleLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.title = {0}", track.title);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.titleLen = {0}", track.titleLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.title = {0}", track.title);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.performerLen = {0}", track.performerLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.performer = {0}", track.performer);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkStrLen1 = {0}", track.unkStrLen1);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkString1 = {0}", track.unkString1);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkStrLen2 = {0}", track.unkStrLen2);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkString2 = {0}", track.unkString2);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkStrLen3 = {0}", track.unkStrLen3);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkString3 = {0}", track.unkString3);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkStrLen4 = {0}", track.unkStrLen4);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkString4 = {0}", track.unkString4);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.discIdLen = {0}", track.discIdLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.discId = {0}", track.discId);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkStrLen5 = {0}", track.unkStrLen5);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkString5 = {0}", track.unkString5);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkStrLen6 = {0}", track.unkStrLen6);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkString6 = {0}", track.unkString6);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkStrLen7 = {0}", track.unkStrLen7);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkString7 = {0}", track.unkString7);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkStrLen8 = {0}", track.unkStrLen8);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkString8 = {0}", track.unkString8);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkStrLen9 = {0}", track.unkStrLen9);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkString9 = {0}", track.unkString9);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkStrLen10 = {0}", track.unkStrLen10);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkString10 = {0}", track.unkString10);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkStrLen11 = {0}", track.unkStrLen11);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkString11 = {0}", track.unkString11);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.isrcLen = {0}", track.isrcLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.isrcUpc = {0}", track.isrcUpc);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.performer = {0}", track.performer);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkStrLen1 = {0}", track.unkStrLen1);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkString1 = {0}", track.unkString1);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkStrLen2 = {0}", track.unkStrLen2);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkString2 = {0}", track.unkString2);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkStrLen3 = {0}", track.unkStrLen3);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkString3 = {0}", track.unkString3);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkStrLen4 = {0}", track.unkStrLen4);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkString4 = {0}", track.unkString4);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.discIdLen = {0}", track.discIdLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.discId = {0}", track.discId);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkStrLen5 = {0}", track.unkStrLen5);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkString5 = {0}", track.unkString5);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkStrLen6 = {0}", track.unkStrLen6);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkString6 = {0}", track.unkString6);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkStrLen7 = {0}", track.unkStrLen7);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkString7 = {0}", track.unkString7);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkStrLen8 = {0}", track.unkStrLen8);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkString8 = {0}", track.unkString8);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkStrLen9 = {0}", track.unkStrLen9);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkString9 = {0}", track.unkString9);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkStrLen10 = {0}", track.unkStrLen10);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkString10 = {0}", track.unkString10);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkStrLen11 = {0}", track.unkStrLen11);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.unkString11 = {0}", track.unkString11);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.isrcLen = {0}", track.isrcLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "track.isrcUpc = {0}", track.isrcUpc);
_bwTracks.Add(track);
}
@@ -390,6 +396,7 @@ public sealed partial class BlindWrite4
var filtersList = new FiltersList();
if(!string.IsNullOrEmpty(_header.DataFile))
{
while(true)
{
_dataFilter = filtersList.GetFilter(Path.Combine(imageFilter.ParentFolder, _header.DataFile));
@@ -409,26 +416,29 @@ public sealed partial class BlindWrite4
if(_dataFilter != null)
break;
_dataFilter = filtersList.GetFilter(Path.Combine(imageFilter.ParentFolder, _header.DataFile.Split(new[]
{
'\\'
}, StringSplitOptions.RemoveEmptyEntries).Last()));
_dataFilter = filtersList.GetFilter(Path.Combine(imageFilter.ParentFolder,
_header.DataFile.
Split(new[] { '\\' },
StringSplitOptions.RemoveEmptyEntries).
Last()));
if(_dataFilter != null)
break;
_dataFilter = filtersList.GetFilter(Path.Combine(imageFilter.ParentFolder, _header.DataFile.Split(new[]
{
'\\'
}, StringSplitOptions.RemoveEmptyEntries).Last().ToLower(CultureInfo.CurrentCulture)));
_dataFilter = filtersList.GetFilter(Path.Combine(imageFilter.ParentFolder,
_header.DataFile.
Split(new[] { '\\' },
StringSplitOptions.RemoveEmptyEntries).
Last().ToLower(CultureInfo.CurrentCulture)));
if(_dataFilter != null)
break;
_dataFilter = filtersList.GetFilter(Path.Combine(imageFilter.ParentFolder, _header.DataFile.Split(new[]
{
'\\'
}, StringSplitOptions.RemoveEmptyEntries).Last().ToUpper(CultureInfo.CurrentCulture)));
_dataFilter = filtersList.GetFilter(Path.Combine(imageFilter.ParentFolder,
_header.DataFile.
Split(new[] { '\\' },
StringSplitOptions.RemoveEmptyEntries).
Last().ToUpper(CultureInfo.CurrentCulture)));
if(_dataFilter != null)
break;
@@ -437,6 +447,7 @@ public sealed partial class BlindWrite4
return ErrorNumber.NoSuchFile;
}
}
else
{
AaruConsole.ErrorWriteLine(Localization.Unable_to_find_data_file);
@@ -454,18 +465,19 @@ public sealed partial class BlindWrite4
_header.SubchannelFile.ToLower(CultureInfo.CurrentCulture)))) ??
filtersList.GetFilter(Path.Combine(imageFilter.ParentFolder,
_header.SubchannelFile.ToUpper(CultureInfo.CurrentCulture)))) ??
filtersList.GetFilter(Path.Combine(imageFilter.ParentFolder, _header.SubchannelFile.Split(new[]
{
'\\'
}, StringSplitOptions.RemoveEmptyEntries).Last()))) ??
filtersList.GetFilter(Path.Combine(imageFilter.ParentFolder, _header.SubchannelFile.Split(new[]
{
'\\'
}, StringSplitOptions.RemoveEmptyEntries).Last().ToLower(CultureInfo.CurrentCulture)))) ??
filtersList.GetFilter(Path.Combine(imageFilter.ParentFolder, _header.SubchannelFile.Split(new[]
{
'\\'
}, StringSplitOptions.RemoveEmptyEntries).Last().ToUpper(CultureInfo.CurrentCulture)));
filtersList.GetFilter(Path.Combine(imageFilter.ParentFolder,
_header.SubchannelFile.
Split(new[] { '\\' },
StringSplitOptions.RemoveEmptyEntries).Last()))) ??
filtersList.GetFilter(Path.Combine(imageFilter.ParentFolder,
_header.SubchannelFile.
Split(new[] { '\\' },
StringSplitOptions.RemoveEmptyEntries).Last().
ToLower(CultureInfo.CurrentCulture)))) ??
filtersList.GetFilter(Path.Combine(imageFilter.ParentFolder,
_header.SubchannelFile.
Split(new[] { '\\' }, StringSplitOptions.RemoveEmptyEntries).
Last().ToUpper(CultureInfo.CurrentCulture)));
}
Tracks = new List<Track>();
@@ -477,6 +489,7 @@ public sealed partial class BlindWrite4
_imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackFlags);
foreach(TrackDescriptor bwTrack in _bwTracks)
{
if(bwTrack.point < 0xA0)
{
var track = new Track
@@ -486,6 +499,7 @@ public sealed partial class BlindWrite4
};
if(!string.IsNullOrEmpty(bwTrack.filename))
{
do
{
track.Filter = filtersList.GetFilter(Path.Combine(imageFilter.ParentFolder, bwTrack.filename));
@@ -508,20 +522,18 @@ public sealed partial class BlindWrite4
break;
track.Filter = filtersList.GetFilter(Path.Combine(imageFilter.ParentFolder, bwTrack.filename.
Split(new[]
{
'\\'
}, StringSplitOptions.RemoveEmptyEntries).
Split(new[] { '\\' },
StringSplitOptions.
RemoveEmptyEntries).
Last()));
if(track.Filter != null)
break;
track.Filter = filtersList.GetFilter(Path.Combine(imageFilter.ParentFolder, bwTrack.filename.
Split(new[]
{
'\\'
}, StringSplitOptions.RemoveEmptyEntries).
Split(new[] { '\\' },
StringSplitOptions.
RemoveEmptyEntries).
Last().ToLower(CultureInfo.
CurrentCulture)));
@@ -529,23 +541,23 @@ public sealed partial class BlindWrite4
break;
track.Filter = filtersList.GetFilter(Path.Combine(imageFilter.ParentFolder, bwTrack.filename.
Split(new[]
{
'\\'
}, StringSplitOptions.RemoveEmptyEntries).
Split(new[] { '\\' },
StringSplitOptions.
RemoveEmptyEntries).
Last().ToUpper(CultureInfo.
CurrentCulture)));
track.Filter = _dataFilter;
} while(true);
}
else
track.Filter = _dataFilter;
track.File = _dataFilter.Filename;
track.FileOffset = bwTrack.offset + ((150 - bwTrack.pregapOffsetAdjustment) * 2352);
track.FileOffset = bwTrack.offset + (150 - bwTrack.pregapOffsetAdjustment) * 2352;
track.SubchannelOffset = ((bwTrack.offset / 2352) + (150 - bwTrack.pregapOffsetAdjustment)) * 96;
track.SubchannelOffset = (bwTrack.offset / 2352 + (150 - bwTrack.pregapOffsetAdjustment)) * 96;
if(bwTrack.pregap > 0)
{
@@ -692,6 +704,7 @@ public sealed partial class BlindWrite4
!_imageInfo.ReadableMediaTags.Contains(MediaTagType.CD_MCN))
_imageInfo.ReadableMediaTags.Add(MediaTagType.CD_MCN);
}
}
Sessions = new List<Session>();
@@ -724,8 +737,10 @@ public sealed partial class BlindWrite4
// As long as subchannel is written for any track, it is present for all tracks
if(Tracks.Any(t => t.SubchannelType == TrackSubchannelType.Packed))
{
foreach(Track track in Tracks)
track.SubchannelType = TrackSubchannelType.Packed;
}
_imageInfo.MediaType = MediaType.CD;
@@ -738,11 +753,11 @@ public sealed partial class BlindWrite4
_imageInfo.LastModificationTime = _dataFilter.LastWriteTime;
_imageInfo.MetadataMediaType = MetadataMediaType.OpticalDisc;
bool data = false;
bool mode2 = false;
bool firstAudio = false;
bool firstData = false;
bool audio = false;
var data = false;
var mode2 = false;
var firstAudio = false;
var firstData = false;
var audio = false;
foreach(Track bwTrack in Tracks)
{
@@ -759,10 +774,10 @@ public sealed partial class BlindWrite4
audio |= bwTrack.Sequence != 1 && bwTrack.Type == CommonTypes.Enums.TrackType.Audio;
mode2 = bwTrack.Type switch
{
CommonTypes.Enums.TrackType.CdMode2Formless => true,
_ => mode2
};
{
CommonTypes.Enums.TrackType.CdMode2Formless => true,
_ => mode2
};
}
if(!data &&
@@ -773,7 +788,7 @@ public sealed partial class BlindWrite4
Sessions.Count > 1 &&
mode2)
_imageInfo.MediaType = MediaType.CDPLUS;
else if((firstData && audio) || mode2)
else if(firstData && audio || mode2)
_imageInfo.MediaType = MediaType.CDROMXA;
else if(!audio)
_imageInfo.MediaType = MediaType.CDROM;
@@ -806,7 +821,8 @@ public sealed partial class BlindWrite4
return ErrorNumber.NoError;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
}
@@ -830,10 +846,13 @@ public sealed partial class BlindWrite4
{
buffer = null;
foreach(KeyValuePair<uint, ulong> kvp in from kvp in _offsetMap where sectorAddress >= kvp.Value
from track in Tracks where track.Sequence == kvp.Key
foreach(KeyValuePair<uint, ulong> kvp in from kvp in _offsetMap
where sectorAddress >= kvp.Value
from track in Tracks
where track.Sequence == kvp.Key
where sectorAddress - kvp.Value <
track.EndSector - track.StartSector + 1 select kvp)
track.EndSector - track.StartSector + 1
select kvp)
return ReadSectors(sectorAddress - kvp.Value, length, kvp.Key, out buffer);
return ErrorNumber.SectorNotFound;
@@ -844,10 +863,13 @@ public sealed partial class BlindWrite4
{
buffer = null;
foreach(KeyValuePair<uint, ulong> kvp in from kvp in _offsetMap where sectorAddress >= kvp.Value
from track in Tracks where track.Sequence == kvp.Key
foreach(KeyValuePair<uint, ulong> kvp in from kvp in _offsetMap
where sectorAddress >= kvp.Value
from track in Tracks
where track.Sequence == kvp.Key
where sectorAddress - kvp.Value <
track.EndSector - track.StartSector + 1 select kvp)
track.EndSector - track.StartSector + 1
select kvp)
return ReadSectorsTag(sectorAddress - kvp.Value, length, kvp.Key, tag, out buffer);
return ErrorNumber.SectorNotFound;
@@ -868,7 +890,7 @@ public sealed partial class BlindWrite4
uint sectorOffset;
uint sectorSize;
uint sectorSkip;
bool mode2 = false;
var mode2 = false;
switch(aaruTrack.Type)
{
@@ -905,7 +927,8 @@ public sealed partial class BlindWrite4
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
buffer = new byte[sectorSize * length];
@@ -923,9 +946,9 @@ public sealed partial class BlindWrite4
buffer = br.ReadBytes((int)(sectorSize * length));
for(int i = 0; i < length; i++)
for(var i = 0; i < length; i++)
{
byte[] sector = new byte[sectorSize];
var sector = new byte[sectorSize];
Array.Copy(buffer, sectorSize * i, sector, 0, sectorSize);
sector = Sector.GetUserDataFromMode2(sector);
mode2Ms.Write(sector, 0, sector.Length);
@@ -937,7 +960,8 @@ public sealed partial class BlindWrite4
sectorSkip == 0)
buffer = br.ReadBytes((int)(sectorSize * length));
else
for(int i = 0; i < length; i++)
{
for(var i = 0; i < length; i++)
{
br.BaseStream.Seek(sectorOffset, SeekOrigin.Current);
byte[] sector = br.ReadBytes((int)sectorSize);
@@ -945,12 +969,13 @@ public sealed partial class BlindWrite4
Array.Copy(sector, 0, buffer, i * sectorSize, sectorSize);
}
}
return ErrorNumber.NoError;
}
/// <inheritdoc />
public ErrorNumber ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag,
public ErrorNumber ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag,
out byte[] buffer)
{
buffer = null;
@@ -978,18 +1003,17 @@ public sealed partial class BlindWrite4
case SectorTagType.CdSectorHeader:
case SectorTagType.CdSectorSubchannel:
case SectorTagType.CdSectorSubHeader:
case SectorTagType.CdSectorSync: break;
case SectorTagType.CdSectorSync:
break;
case SectorTagType.CdTrackFlags:
if(!_trackFlags.TryGetValue((uint)sectorAddress, out byte flag))
return ErrorNumber.NoData;
buffer = new[]
{
flag
};
buffer = new[] { flag };
return ErrorNumber.NoError;
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
switch(aaruTrack.Type)
@@ -1013,7 +1037,8 @@ public sealed partial class BlindWrite4
break;
}
case SectorTagType.CdSectorSubHeader: return ErrorNumber.NotSupported;
case SectorTagType.CdSectorSubHeader:
return ErrorNumber.NotSupported;
case SectorTagType.CdSectorEcc:
{
sectorOffset = 2076;
@@ -1065,7 +1090,8 @@ public sealed partial class BlindWrite4
case SectorTagType.CdSectorHeader:
case SectorTagType.CdSectorEcc:
case SectorTagType.CdSectorEccP:
case SectorTagType.CdSectorEccQ: return ErrorNumber.NotSupported;
case SectorTagType.CdSectorEccQ:
return ErrorNumber.NotSupported;
case SectorTagType.CdSectorSubHeader:
{
sectorOffset = 0;
@@ -1106,36 +1132,43 @@ public sealed partial class BlindWrite4
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
buffer = new byte[sectorSize * length];
_imageStream = tag == SectorTagType.CdSectorSubchannel ? aaruTrack.SubchannelFilter.GetDataForkStream()
_imageStream = tag == SectorTagType.CdSectorSubchannel
? aaruTrack.SubchannelFilter.GetDataForkStream()
: aaruTrack.Filter.GetDataForkStream();
var br = new BinaryReader(_imageStream);
br.BaseStream.
Seek((long)(tag == SectorTagType.CdSectorSubchannel ? aaruTrack.SubchannelOffset : aaruTrack.FileOffset) + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)),
SeekOrigin.Begin);
Seek(
(long)(tag == SectorTagType.CdSectorSubchannel ? aaruTrack.SubchannelOffset : aaruTrack.FileOffset) +
(long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)),
SeekOrigin.Begin);
if(sectorOffset == 0 &&
sectorSkip == 0)
buffer = br.ReadBytes((int)(sectorSize * length));
else
for(int i = 0; i < length; i++)
{
for(var i = 0; i < length; i++)
{
br.BaseStream.Seek(sectorOffset, SeekOrigin.Current);
byte[] sector = br.ReadBytes((int)sectorSize);
br.BaseStream.Seek(sectorSkip, SeekOrigin.Current);
Array.Copy(sector, 0, buffer, i * sectorSize, sectorSize);
}
}
if(tag == SectorTagType.CdSectorSubchannel)
buffer = Subchannel.Interleave(buffer);
@@ -1156,10 +1189,13 @@ public sealed partial class BlindWrite4
{
buffer = null;
foreach(KeyValuePair<uint, ulong> kvp in from kvp in _offsetMap where sectorAddress >= kvp.Value
from track in Tracks where track.Sequence == kvp.Key
foreach(KeyValuePair<uint, ulong> kvp in from kvp in _offsetMap
where sectorAddress >= kvp.Value
from track in Tracks
where track.Sequence == kvp.Key
where sectorAddress - kvp.Value <
track.EndSector - track.StartSector + 1 select kvp)
track.EndSector - track.StartSector + 1
select kvp)
return ReadSectorsLong(sectorAddress - kvp.Value, length, kvp.Key, out buffer);
return ErrorNumber.SectorNotFound;
@@ -1190,7 +1226,8 @@ public sealed partial class BlindWrite4
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
_imageStream = aaruTrack.Filter.GetDataForkStream();
@@ -1209,4 +1246,6 @@ public sealed partial class BlindWrite4
/// <inheritdoc />
public List<Track> GetSessionTracks(ushort session) => Tracks.Where(track => track.Session == session).ToList();
#endregion
}

View File

@@ -37,6 +37,8 @@ namespace Aaru.DiscImages;
public sealed partial class BlindWrite4
{
#region Nested type: Header
struct Header
{
public byte[] Signature;
@@ -58,7 +60,7 @@ public sealed partial class BlindWrite4
public byte[] Unknown4;
// On memory only
#pragma warning disable 649
#pragma warning disable 649
public string VolumeIdentifier;
public string SystemIdentifier;
public string Comments;
@@ -66,9 +68,13 @@ public sealed partial class BlindWrite4
public IFilter SubchannelFilter;
public string DataFile;
public string SubchannelFile;
#pragma warning restore 649
#pragma warning restore 649
}
#endregion
#region Nested type: TrackDescriptor
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct TrackDescriptor
{
@@ -149,4 +155,6 @@ public sealed partial class BlindWrite4
public string unkString11;
public string isrcUpc;
}
#endregion
}

View File

@@ -39,6 +39,8 @@ namespace Aaru.DiscImages;
public sealed partial class BlindWrite4
{
#region IOpticalMediaImage Members
/// <inheritdoc />
public bool? VerifySector(ulong sectorAddress)
{
@@ -48,7 +50,7 @@ public sealed partial class BlindWrite4
}
/// <inheritdoc />
public bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas,
public bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
@@ -58,10 +60,10 @@ public sealed partial class BlindWrite4
if(errno != ErrorNumber.NoError)
return null;
int bps = (int)(buffer.Length / length);
byte[] sector = new byte[bps];
var bps = (int)(buffer.Length / length);
var sector = new byte[bps];
for(int i = 0; i < length; i++)
for(var i = 0; i < length; i++)
{
Array.Copy(buffer, i * bps, sector, 0, bps);
bool? sectorStatus = CdChecksums.CheckCdSector(sector);
@@ -86,7 +88,7 @@ public sealed partial class BlindWrite4
}
/// <inheritdoc />
public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
@@ -96,10 +98,10 @@ public sealed partial class BlindWrite4
if(errno != ErrorNumber.NoError)
return null;
int bps = (int)(buffer.Length / length);
byte[] sector = new byte[bps];
var bps = (int)(buffer.Length / length);
var sector = new byte[bps];
for(int i = 0; i < length; i++)
for(var i = 0; i < length; i++)
{
Array.Copy(buffer, i * bps, sector, 0, bps);
bool? sectorStatus = CdChecksums.CheckCdSector(sector);
@@ -122,4 +124,6 @@ public sealed partial class BlindWrite4
return failingLbas.Count <= 0;
}
#endregion
}

View File

@@ -43,6 +43,7 @@ namespace Aaru.DiscImages;
/// <summary>Implements reading BlindWrite 5/6/7 disc images</summary>
public sealed partial class BlindWrite5 : IOpticalMediaImage
{
const string MODULE_NAME = "BlindWrite5 plugin";
byte[] _atip;
byte[] _bca;
List<SessionDescriptor> _bwSessions;
@@ -84,6 +85,4 @@ public sealed partial class BlindWrite5 : IOpticalMediaImage
DriveSerialNumber = null,
DriveFirmwareRevision = null
};
const string MODULE_NAME = "BlindWrite5 plugin";
}

View File

@@ -37,15 +37,29 @@ namespace Aaru.DiscImages;
[SuppressMessage("ReSharper", "UnusedMember.Local")]
public sealed partial class BlindWrite5
{
enum TrackType : byte
{
NotData = 0, Audio = 1, Mode1 = 2,
Mode2 = 3, Mode2F1 = 4, Mode2F2 = 5,
Dvd = 6
}
#region Nested type: TrackSubchannel
enum TrackSubchannel : byte
{
None = 0, Q16 = 2, Linear = 4
None = 0,
Q16 = 2,
Linear = 4
}
#endregion
#region Nested type: TrackType
enum TrackType : byte
{
NotData = 0,
Audio = 1,
Mode1 = 2,
Mode2 = 3,
Mode2F1 = 4,
Mode2F2 = 5,
Dvd = 6
}
#endregion
}

View File

@@ -38,55 +38,84 @@ namespace Aaru.DiscImages;
public sealed partial class BlindWrite5
{
static CommonTypes.Enums.TrackType BlindWriteTrackTypeToTrackType(TrackType trackType) => trackType switch
{
TrackType.Mode1 => CommonTypes.Enums.TrackType.CdMode1,
TrackType.Mode2F1 => CommonTypes.Enums.TrackType.CdMode2Form1,
TrackType.Mode2F2 => CommonTypes.Enums.TrackType.CdMode2Form2,
TrackType.Mode2 => CommonTypes.Enums.TrackType.CdMode2Formless,
TrackType.Audio => CommonTypes.Enums.TrackType.Audio,
_ => CommonTypes.Enums.TrackType.Data
};
{
TrackType.Mode1 => CommonTypes.Enums.TrackType.CdMode1,
TrackType.Mode2F1 => CommonTypes.Enums.TrackType.CdMode2Form1,
TrackType.Mode2F2 => CommonTypes.Enums.TrackType.CdMode2Form2,
TrackType.Mode2 => CommonTypes.Enums.TrackType.CdMode2Formless,
TrackType.Audio => CommonTypes.Enums.TrackType.Audio,
_ => CommonTypes.Enums.TrackType.Data
};
static MediaType BlindWriteProfileToMediaType(ProfileNumber profile)
{
switch(profile)
{
case ProfileNumber.BDRE: return MediaType.BDRE;
case ProfileNumber.BDROM: return MediaType.BDROM;
case ProfileNumber.BDRE:
return MediaType.BDRE;
case ProfileNumber.BDROM:
return MediaType.BDROM;
case ProfileNumber.BDRRdm:
case ProfileNumber.BDRSeq: return MediaType.BDR;
case ProfileNumber.BDRSeq:
return MediaType.BDR;
case ProfileNumber.CDR:
case ProfileNumber.HDBURNR: return MediaType.CDR;
case ProfileNumber.HDBURNR:
return MediaType.CDR;
case ProfileNumber.CDROM:
case ProfileNumber.HDBURNROM: return MediaType.CDROM;
case ProfileNumber.HDBURNROM:
return MediaType.CDROM;
case ProfileNumber.CDRW:
case ProfileNumber.HDBURNRW: return MediaType.CDRW;
case ProfileNumber.DDCDR: return MediaType.DDCDR;
case ProfileNumber.DDCDROM: return MediaType.DDCD;
case ProfileNumber.DDCDRW: return MediaType.DDCDRW;
case ProfileNumber.DVDDownload: return MediaType.DVDDownload;
case ProfileNumber.DVDRAM: return MediaType.DVDRAM;
case ProfileNumber.HDBURNRW:
return MediaType.CDRW;
case ProfileNumber.DDCDR:
return MediaType.DDCDR;
case ProfileNumber.DDCDROM:
return MediaType.DDCD;
case ProfileNumber.DDCDRW:
return MediaType.DDCDRW;
case ProfileNumber.DVDDownload:
return MediaType.DVDDownload;
case ProfileNumber.DVDRAM:
return MediaType.DVDRAM;
case ProfileNumber.DVDRDLJump:
case ProfileNumber.DVDRDLSeq: return MediaType.DVDRDL;
case ProfileNumber.DVDRDLPlus: return MediaType.DVDPRDL;
case ProfileNumber.DVDROM: return MediaType.DVDROM;
case ProfileNumber.DVDRPlus: return MediaType.DVDPR;
case ProfileNumber.DVDRSeq: return MediaType.DVDR;
case ProfileNumber.DVDRWDL: return MediaType.DVDRWDL;
case ProfileNumber.DVDRWDLPlus: return MediaType.DVDPRWDL;
case ProfileNumber.DVDRWPlus: return MediaType.DVDPRW;
case ProfileNumber.DVDRDLSeq:
return MediaType.DVDRDL;
case ProfileNumber.DVDRDLPlus:
return MediaType.DVDPRDL;
case ProfileNumber.DVDROM:
return MediaType.DVDROM;
case ProfileNumber.DVDRPlus:
return MediaType.DVDPR;
case ProfileNumber.DVDRSeq:
return MediaType.DVDR;
case ProfileNumber.DVDRWDL:
return MediaType.DVDRWDL;
case ProfileNumber.DVDRWDLPlus:
return MediaType.DVDPRWDL;
case ProfileNumber.DVDRWPlus:
return MediaType.DVDPRW;
case ProfileNumber.DVDRWRes:
case ProfileNumber.DVDRWSeq: return MediaType.DVDRW;
case ProfileNumber.HDDVDR: return MediaType.HDDVDR;
case ProfileNumber.HDDVDRAM: return MediaType.HDDVDRAM;
case ProfileNumber.HDDVDRDL: return MediaType.HDDVDRDL;
case ProfileNumber.HDDVDROM: return MediaType.HDDVDROM;
case ProfileNumber.HDDVDRW: return MediaType.HDDVDRW;
case ProfileNumber.HDDVDRWDL: return MediaType.HDDVDRWDL;
case ProfileNumber.DVDRWSeq:
return MediaType.DVDRW;
case ProfileNumber.HDDVDR:
return MediaType.HDDVDR;
case ProfileNumber.HDDVDRAM:
return MediaType.HDDVDRAM;
case ProfileNumber.HDDVDRDL:
return MediaType.HDDVDRDL;
case ProfileNumber.HDDVDROM:
return MediaType.HDDVDROM;
case ProfileNumber.HDDVDRW:
return MediaType.HDDVDRW;
case ProfileNumber.HDDVDRWDL:
return MediaType.HDDVDRWDL;
case ProfileNumber.ASMO:
case ProfileNumber.MOErasable: return MediaType.UnknownMO;
case ProfileNumber.NonRemovable: return MediaType.GENERIC_HDD;
default: return MediaType.CD;
case ProfileNumber.MOErasable:
return MediaType.UnknownMO;
case ProfileNumber.NonRemovable:
return MediaType.GENERIC_HDD;
default:
return MediaType.CD;
}
}
}

View File

@@ -39,6 +39,8 @@ namespace Aaru.DiscImages;
public sealed partial class BlindWrite5
{
#region IOpticalMediaImage Members
/// <inheritdoc />
public bool Identify(IFilter imageFilter)
{
@@ -48,13 +50,15 @@ public sealed partial class BlindWrite5
if(stream.Length < 276)
return false;
byte[] signature = new byte[16];
var signature = new byte[16];
stream.EnsureRead(signature, 0, 16);
byte[] footer = new byte[16];
var footer = new byte[16];
stream.Seek(-16, SeekOrigin.End);
stream.EnsureRead(footer, 0, 16);
return _bw5Signature.SequenceEqual(signature) && _bw5Footer.SequenceEqual(footer);
}
#endregion
}

View File

@@ -41,15 +41,20 @@ namespace Aaru.DiscImages;
public sealed partial class BlindWrite5
{
#region IOpticalMediaImage Members
/// <inheritdoc />
public ImageInfo Info => _imageInfo;
/// <inheritdoc />
public string Name => Localization.BlindWrite5_Name;
/// <inheritdoc />
public Guid Id => new("9CB7A381-0509-4F9F-B801-3F65434BC3EE");
/// <inheritdoc />
public string Author => Authors.NataliaPortillo;
/// <inheritdoc />
public string Format => "BlindWrite 5 TOC file";
@@ -64,6 +69,9 @@ public sealed partial class BlindWrite5
/// <inheritdoc />
public List<DumpHardware> DumpHardware => null;
/// <inheritdoc />
public Metadata AaruMetadata => null;
#endregion
}

View File

@@ -56,6 +56,8 @@ namespace Aaru.DiscImages;
public sealed partial class BlindWrite5
{
#region IOpticalMediaImage Members
/// <inheritdoc />
public ErrorNumber Open(IFilter imageFilter)
{
@@ -65,42 +67,42 @@ public sealed partial class BlindWrite5
if(stream.Length < 276)
return ErrorNumber.InvalidArgument;
byte[] hdr = new byte[260];
var hdr = new byte[260];
stream.EnsureRead(hdr, 0, 260);
_header = Marshal.ByteArrayToStructureLittleEndian<Header>(hdr);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.signature = {0}",
StringHandlers.CToString(_header.signature));
for(int i = 0; i < _header.unknown1.Length; i++)
for(var i = 0; i < _header.unknown1.Length; i++)
AaruConsole.DebugWriteLine(MODULE_NAME, "header.unknown1[{1}] = 0x{0:X8}", _header.unknown1[i], i);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.profile = {0}", _header.profile);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.profile = {0}", _header.profile);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.sessions = {0}", _header.sessions);
for(int i = 0; i < _header.unknown2.Length; i++)
for(var i = 0; i < _header.unknown2.Length; i++)
AaruConsole.DebugWriteLine(MODULE_NAME, "header.unknown2[{1}] = 0x{0:X8}", _header.unknown2[i], i);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.mcnIsValid = {0}", _header.mcnIsValid);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.mcn = {0}", StringHandlers.CToString(_header.mcn));
AaruConsole.DebugWriteLine(MODULE_NAME, "header.mcnIsValid = {0}", _header.mcnIsValid);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.mcn = {0}", StringHandlers.CToString(_header.mcn));
AaruConsole.DebugWriteLine(MODULE_NAME, "header.unknown3 = 0x{0:X4}", _header.unknown3);
for(int i = 0; i < _header.unknown4.Length; i++)
for(var i = 0; i < _header.unknown4.Length; i++)
AaruConsole.DebugWriteLine(MODULE_NAME, "header.unknown4[{1}] = 0x{0:X8}", _header.unknown4[i], i);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.pmaLen = {0}", _header.pmaLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.atipLen = {0}", _header.atipLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.cdtLen = {0}", _header.cdtLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.pmaLen = {0}", _header.pmaLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.atipLen = {0}", _header.atipLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.cdtLen = {0}", _header.cdtLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.cdInfoLen = {0}", _header.cdInfoLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.bcaLen = {0}", _header.bcaLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.bcaLen = {0}", _header.bcaLen);
for(int i = 0; i < _header.unknown5.Length; i++)
for(var i = 0; i < _header.unknown5.Length; i++)
AaruConsole.DebugWriteLine(MODULE_NAME, "header.unknown5[{1}] = 0x{0:X8}", _header.unknown5[i], i);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.dvdStrLen = {0}", _header.dvdStrLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.dvdStrLen = {0}", _header.dvdStrLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.dvdInfoLen = {0}", _header.dvdInfoLen);
for(int i = 0; i < _header.unknown6.Length; i++)
for(var i = 0; i < _header.unknown6.Length; i++)
AaruConsole.DebugWriteLine(MODULE_NAME, "header.unknown6[{1}] = 0x{0:X2}", _header.unknown6[i], i);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.manufacturer = {0}",
@@ -118,11 +120,11 @@ public sealed partial class BlindWrite5
AaruConsole.DebugWriteLine(MODULE_NAME, "header.volumeId = {0}",
StringHandlers.CToString(_header.volumeId));
AaruConsole.DebugWriteLine(MODULE_NAME, "header.mode2ALen = {0}", _header.mode2ALen);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.unkBlkLen = {0}", _header.unkBlkLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.dataLen = {0}", _header.dataLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.mode2ALen = {0}", _header.mode2ALen);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.unkBlkLen = {0}", _header.unkBlkLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.dataLen = {0}", _header.dataLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.sessionsLen = {0}", _header.sessionsLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.dpmLen = {0}", _header.dpmLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "header.dpmLen = {0}", _header.dpmLen);
_mode2A = new byte[_header.mode2ALen];
@@ -133,8 +135,10 @@ public sealed partial class BlindWrite5
var decoded2A = ModePage_2A.Decode(_mode2A);
if(decoded2A is not null)
{
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.mode_page_2A_0,
Modes.PrettifyModePage_2A(decoded2A));
}
else
_mode2A = null;
}
@@ -144,7 +148,7 @@ public sealed partial class BlindWrite5
if(_unkBlock.Length > 0)
stream.EnsureRead(_unkBlock, 0, _unkBlock.Length);
byte[] temp = new byte[_header.pmaLen];
var temp = new byte[_header.pmaLen];
if(temp.Length > 0)
{
@@ -193,7 +197,7 @@ public sealed partial class BlindWrite5
_pfi = new byte[2052];
// TODO: CMI
Array.Copy(temp, 2, _dmi, 4, 2048);
Array.Copy(temp, 2, _dmi, 4, 2048);
Array.Copy(temp, 0x802, _pfi, 4, 2048);
_pfi[0] = 0x08;
@@ -243,20 +247,20 @@ public sealed partial class BlindWrite5
_discInformation = null;
// How many data blocks
byte[] tmpArray = new byte[4];
var tmpArray = new byte[4];
stream.EnsureRead(tmpArray, 0, tmpArray.Length);
uint dataBlockCount = BitConverter.ToUInt32(tmpArray, 0);
var dataBlockCount = BitConverter.ToUInt32(tmpArray, 0);
stream.EnsureRead(tmpArray, 0, tmpArray.Length);
uint dataPathLen = BitConverter.ToUInt32(tmpArray, 0);
byte[] dataPathBytes = new byte[dataPathLen];
var dataPathLen = BitConverter.ToUInt32(tmpArray, 0);
var dataPathBytes = new byte[dataPathLen];
stream.EnsureRead(dataPathBytes, 0, dataPathBytes.Length);
_dataPath = Encoding.Unicode.GetString(dataPathBytes);
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Data_path_0, _dataPath);
_dataFiles = new List<DataFile>();
for(int cD = 0; cD < dataBlockCount; cD++)
for(var cD = 0; cD < dataBlockCount; cD++)
{
tmpArray = new byte[52];
@@ -293,28 +297,32 @@ public sealed partial class BlindWrite5
_dataFiles.Add(dataFile);
AaruConsole.DebugWriteLine(MODULE_NAME, "dataFile.type = 0x{0:X8}", dataFile.Type);
AaruConsole.DebugWriteLine(MODULE_NAME, "dataFile.length = {0}", dataFile.Length);
AaruConsole.DebugWriteLine(MODULE_NAME, "dataFile.length = {0}", dataFile.Length);
for(int i = 0; i < dataFile.Unknown1.Length; i++)
for(var i = 0; i < dataFile.Unknown1.Length; i++)
{
AaruConsole.DebugWriteLine(MODULE_NAME, "dataFile.unknown1[{1}] = {0}", dataFile.Unknown1[i],
i);
}
AaruConsole.DebugWriteLine(MODULE_NAME, "dataFile.offset = {0}", dataFile.Offset);
for(int i = 0; i < dataFile.Unknown2.Length; i++)
for(var i = 0; i < dataFile.Unknown2.Length; i++)
{
AaruConsole.DebugWriteLine(MODULE_NAME, "dataFile.unknown2[{1}] = {0}", dataFile.Unknown2[i],
i);
}
AaruConsole.DebugWriteLine(MODULE_NAME, "dataFile.startLba = {0}", dataFile.StartLba);
AaruConsole.DebugWriteLine(MODULE_NAME, "dataFile.sectors = {0}", dataFile.Sectors);
AaruConsole.DebugWriteLine(MODULE_NAME, "dataFile.startLba = {0}", dataFile.StartLba);
AaruConsole.DebugWriteLine(MODULE_NAME, "dataFile.sectors = {0}", dataFile.Sectors);
AaruConsole.DebugWriteLine(MODULE_NAME, "dataFile.filenameLen = {0}", dataFile.FilenameLen);
AaruConsole.DebugWriteLine(MODULE_NAME, "dataFile.filename = {0}", dataFile.Filename);
AaruConsole.DebugWriteLine(MODULE_NAME, "dataFile.unknown3 = {0}", dataFile.Unknown3);
AaruConsole.DebugWriteLine(MODULE_NAME, "dataFile.filename = {0}", dataFile.Filename);
AaruConsole.DebugWriteLine(MODULE_NAME, "dataFile.unknown3 = {0}", dataFile.Unknown3);
}
_bwSessions = new List<SessionDescriptor>();
for(int ses = 0; ses < _header.sessions; ses++)
for(var ses = 0; ses < _header.sessions; ses++)
{
var session = new SessionDescriptor();
tmpArray = new byte[16];
@@ -329,18 +337,18 @@ public sealed partial class BlindWrite5
session.Tracks = new TrackDescriptor[session.Entries];
AaruConsole.DebugWriteLine(MODULE_NAME, "session[{0}].filename = {1}", ses, session.Sequence);
AaruConsole.DebugWriteLine(MODULE_NAME, "session[{0}].entries = {1}", ses, session.Entries);
AaruConsole.DebugWriteLine(MODULE_NAME, "session[{0}].unknown = {1}", ses, session.Unknown);
AaruConsole.DebugWriteLine(MODULE_NAME, "session[{0}].start = {1}", ses, session.Start);
AaruConsole.DebugWriteLine(MODULE_NAME, "session[{0}].end = {1}", ses, session.End);
AaruConsole.DebugWriteLine(MODULE_NAME, "session[{0}].entries = {1}", ses, session.Entries);
AaruConsole.DebugWriteLine(MODULE_NAME, "session[{0}].unknown = {1}", ses, session.Unknown);
AaruConsole.DebugWriteLine(MODULE_NAME, "session[{0}].start = {1}", ses, session.Start);
AaruConsole.DebugWriteLine(MODULE_NAME, "session[{0}].end = {1}", ses, session.End);
AaruConsole.DebugWriteLine(MODULE_NAME, "session[{0}].firstTrack = {1}", ses, session.FirstTrack);
AaruConsole.DebugWriteLine(MODULE_NAME, "session[{0}].lastTrack = {1}", ses, session.LastTrack);
for(int tSeq = 0; tSeq < session.Entries; tSeq++)
for(var tSeq = 0; tSeq < session.Entries; tSeq++)
{
byte[] trk = new byte[72];
var trk = new byte[72];
stream.EnsureRead(trk, 0, 72);
session.Tracks[tSeq] = Marshal.ByteArrayToStructureLittleEndian<TrackDescriptor>(trk);
@@ -354,9 +362,11 @@ public sealed partial class BlindWrite5
AaruConsole.DebugWriteLine(MODULE_NAME, "session[{0}].track[{1}].type = {2}", ses, tSeq,
session.Tracks[tSeq].type);
for(int i = 0; i < session.Tracks[tSeq].unknown1.Length; i++)
for(var i = 0; i < session.Tracks[tSeq].unknown1.Length; i++)
{
AaruConsole.DebugWriteLine(MODULE_NAME, "session[{0}].track[{1}].unknown1[{2}] = 0x{3:X2}",
ses, tSeq, i, session.Tracks[tSeq].unknown1[i]);
}
AaruConsole.DebugWriteLine(MODULE_NAME, "session[{0}].track[{1}].unknown2 = 0x{2:X8}", ses,
tSeq, session.Tracks[tSeq].unknown2);
@@ -406,9 +416,11 @@ public sealed partial class BlindWrite5
AaruConsole.DebugWriteLine(MODULE_NAME, "session[{0}].track[{1}].pregap = {2}", ses, tSeq,
session.Tracks[tSeq].pregap);
for(int i = 0; i < session.Tracks[tSeq].unknown6.Length; i++)
for(var i = 0; i < session.Tracks[tSeq].unknown6.Length; i++)
{
AaruConsole.DebugWriteLine(MODULE_NAME, "session[{0}].track[{1}].unknown6[{2}] = 0x{3:X8}",
ses, tSeq, i, session.Tracks[tSeq].unknown6[i]);
}
AaruConsole.DebugWriteLine(MODULE_NAME, "session[{0}].track[{1}].startLba = {2}", ses, tSeq,
session.Tracks[tSeq].startLba);
@@ -416,9 +428,11 @@ public sealed partial class BlindWrite5
AaruConsole.DebugWriteLine(MODULE_NAME, "session[{0}].track[{1}].sectors = {2}", ses, tSeq,
session.Tracks[tSeq].sectors);
for(int i = 0; i < session.Tracks[tSeq].unknown7.Length; i++)
for(var i = 0; i < session.Tracks[tSeq].unknown7.Length; i++)
{
AaruConsole.DebugWriteLine(MODULE_NAME, "session[{0}].track[{1}].unknown7[{2}] = 0x{3:X8}",
ses, tSeq, i, session.Tracks[tSeq].unknown7[i]);
}
AaruConsole.DebugWriteLine(MODULE_NAME, "session[{0}].track[{1}].session = {2}", ses, tSeq,
session.Tracks[tSeq].session);
@@ -430,10 +444,12 @@ public sealed partial class BlindWrite5
continue;
{
for(int i = 0; i < session.Tracks[tSeq].unknown9.Length; i++)
for(var i = 0; i < session.Tracks[tSeq].unknown9.Length; i++)
{
AaruConsole.DebugWriteLine(MODULE_NAME,
"session[{0}].track[{1}].unknown9[{2}] = 0x{3:X8}", ses, tSeq, i,
session.Tracks[tSeq].unknown9[i]);
}
}
}
@@ -447,14 +463,16 @@ public sealed partial class BlindWrite5
tmpArray = new byte[4];
stream.EnsureRead(tmpArray, 0, tmpArray.Length);
byte[] footer = new byte[16];
var footer = new byte[16];
stream.EnsureRead(footer, 0, footer.Length);
if(_bw5Footer.SequenceEqual(footer))
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Correctly_arrived_end_of_image);
else
{
AaruConsole.ErrorWriteLine(Localization.
BlindWrite5_image_ends_after_expected_position_Probably_new_version_with_different_data_Errors_may_occur);
}
_filePaths = new List<DataFileCharacteristics>();
@@ -577,6 +595,7 @@ public sealed partial class BlindWrite5
long sectorSize = dataFile.Length / dataFile.Sectors;
if(sectorSize > 2352)
{
switch(sectorSize - 2352)
{
case 16:
@@ -593,6 +612,7 @@ public sealed partial class BlindWrite5
return ErrorNumber.NotSupported;
}
}
else
chars.Subchannel = TrackSubchannelType.None;
@@ -609,14 +629,11 @@ public sealed partial class BlindWrite5
Partitions = new List<Partition>();
var fullTocStream = new MemoryStream();
fullTocStream.Write(new byte[]
{
0, 0
}, 0, 2);
fullTocStream.Write(new byte[] { 0, 0 }, 0, 2);
ulong offsetBytes = 0;
_offsetMap = new Dictionary<uint, ulong>();
bool isDvd = false;
var isDvd = false;
byte firstSession = byte.MaxValue;
byte lastSession = 0;
_trackFlags = new Dictionary<uint, byte>();
@@ -643,7 +660,7 @@ public sealed partial class BlindWrite5
foreach(TrackDescriptor trk in ses.Tracks)
{
byte adrCtl = (byte)((trk.adr << 4) + trk.ctl);
var adrCtl = (byte)((trk.adr << 4) + trk.ctl);
fullTocStream.WriteByte((byte)trk.session);
fullTocStream.WriteByte(adrCtl);
fullTocStream.WriteByte(0x00);
@@ -754,11 +771,11 @@ public sealed partial class BlindWrite5
track.StartSector = (ulong)(trk.startLba + trk.pregap);
track.EndSector = (ulong)(trk.sectors + trk.startLba) - 1;
List<DataFileCharacteristics> fileCharsForThisTrack = _filePaths.
Where(chars => trk.startLba >= chars.StartLba &&
trk.startLba + trk.sectors <=
chars.StartLba + chars.Sectors).
ToList();
var fileCharsForThisTrack = _filePaths.
Where(chars => trk.startLba >= chars.StartLba &&
trk.startLba + trk.sectors <=
chars.StartLba + chars.Sectors).
ToList();
if(fileCharsForThisTrack.Count == 0 &&
_filePaths.Any(f => Path.GetExtension(f.FilePath).ToLowerInvariant() == ".b00"))
@@ -767,8 +784,8 @@ public sealed partial class BlindWrite5
_filePaths.FirstOrDefault(f => Path.GetExtension(f.FilePath).ToLowerInvariant() == ".b00");
string filename = Path.GetFileNameWithoutExtension(splitStartChars.FilePath);
bool lowerCaseExtension = false;
bool lowerCaseFileName = false;
var lowerCaseExtension = false;
var lowerCaseFileName = false;
string basePath;
bool version5 = string.Compare(Path.GetExtension(imageFilter.Filename), ".B5T",
@@ -876,8 +893,10 @@ public sealed partial class BlindWrite5
else if(File.Exists(Path.Combine(imageFilter.ParentFolder,
_dataPath.ToLower(CultureInfo.CurrentCulture),
$"{filename}.{firstExtension}")))
{
basePath = Path.Combine(imageFilter.ParentFolder,
_dataPath.ToLower(CultureInfo.CurrentCulture));
}
else if(File.Exists(Path.Combine(imageFilter.ParentFolder,
_dataPath.ToLower(CultureInfo.CurrentCulture), $"{filename}.b00")))
{
@@ -946,7 +965,10 @@ public sealed partial class BlindWrite5
try
{
splitStream.
Add(Path.Combine(basePath, $"{filename}.{(lowerCaseExtension ? firstExtensionLower : firstExtension)}"),
Add(
Path.Combine(
basePath,
$"{filename}.{(lowerCaseExtension ? firstExtensionLower : firstExtension)}"),
FileMode.Open, FileAccess.Read);
splitStream.AddRange(basePath, $"{filename}.{extension}");
@@ -962,8 +984,10 @@ public sealed partial class BlindWrite5
track.File = $"{filename}.{extension}";
if(trk.startLba >= 0)
{
track.FileOffset =
(ulong)((trk.startLba * splitStartChars.SectorSize) + splitStartChars.Offset);
(ulong)(trk.startLba * splitStartChars.SectorSize + splitStartChars.Offset);
}
else
track.FileOffset = (ulong)(trk.startLba * -1 * splitStartChars.SectorSize);
@@ -987,14 +1011,17 @@ public sealed partial class BlindWrite5
_filePaths.Add(splitStartChars);
}
else
{
foreach(DataFileCharacteristics chars in fileCharsForThisTrack)
{
track.Filter = chars.FileFilter;
track.File = chars.FileFilter.Filename;
if(trk.startLba >= 0)
{
track.FileOffset = (ulong)((trk.startLba - chars.StartLba) * chars.SectorSize) +
chars.Offset;
}
else
track.FileOffset = (ulong)(trk.startLba * -1 * chars.SectorSize);
@@ -1013,6 +1040,7 @@ public sealed partial class BlindWrite5
break;
}
}
if(track.Filter is null)
{
@@ -1090,7 +1118,7 @@ public sealed partial class BlindWrite5
foreach(Partition partition in Partitions)
{
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Partition_sequence_0, partition.Sequence);
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Partition_sequence_0, partition.Sequence);
AaruConsole.DebugWriteLine(MODULE_NAME, "\t" + Localization.Partition_name_0, partition.Name);
AaruConsole.DebugWriteLine(MODULE_NAME, "\t" + Localization.Partition_description_0,
@@ -1135,22 +1163,28 @@ public sealed partial class BlindWrite5
if(pfi0.HasValue)
{
_imageInfo.MediaType = pfi0.Value.DiskCategory switch
{
DiskCategory.DVDPR => MediaType.DVDPR,
DiskCategory.DVDPRDL => MediaType.DVDPRDL,
DiskCategory.DVDPRW => MediaType.DVDPRW,
DiskCategory.DVDPRWDL => MediaType.DVDPRWDL,
DiskCategory.DVDR => pfi0.Value.PartVersion >= 6 ? MediaType.DVDRDL : MediaType.DVDR,
DiskCategory.DVDRAM => MediaType.DVDRAM,
DiskCategory.DVDRW => pfi0.Value.PartVersion >= 15 ? MediaType.DVDRWDL : MediaType.DVDRW,
DiskCategory.HDDVDR => MediaType.HDDVDR,
DiskCategory.HDDVDRAM => MediaType.HDDVDRAM,
DiskCategory.HDDVDROM => MediaType.HDDVDROM,
DiskCategory.HDDVDRW => MediaType.HDDVDRW,
DiskCategory.Nintendo => pfi0.Value.DiscSize == DVDSize.Eighty ? MediaType.GOD : MediaType.WOD,
DiskCategory.UMD => MediaType.UMD,
_ => MediaType.DVDROM
};
{
DiskCategory.DVDPR => MediaType.DVDPR,
DiskCategory.DVDPRDL => MediaType.DVDPRDL,
DiskCategory.DVDPRW => MediaType.DVDPRW,
DiskCategory.DVDPRWDL => MediaType.DVDPRWDL,
DiskCategory.DVDR => pfi0.Value.PartVersion >= 6
? MediaType.DVDRDL
: MediaType.DVDR,
DiskCategory.DVDRAM => MediaType.DVDRAM,
DiskCategory.DVDRW => pfi0.Value.PartVersion >= 15
? MediaType.DVDRWDL
: MediaType.DVDRW,
DiskCategory.HDDVDR => MediaType.HDDVDR,
DiskCategory.HDDVDRAM => MediaType.HDDVDRAM,
DiskCategory.HDDVDROM => MediaType.HDDVDROM,
DiskCategory.HDDVDRW => MediaType.HDDVDRW,
DiskCategory.Nintendo => pfi0.Value.DiscSize == DVDSize.Eighty
? MediaType.GOD
: MediaType.WOD,
DiskCategory.UMD => MediaType.UMD,
_ => MediaType.DVDROM
};
if(DMI.IsXbox(_dmi))
_imageInfo.MediaType = MediaType.XGD;
@@ -1160,11 +1194,11 @@ public sealed partial class BlindWrite5
}
else if(_imageInfo.MediaType is MediaType.CD or MediaType.CDROM)
{
bool data = false;
bool mode2 = false;
bool firstAudio = false;
bool firstData = false;
bool audio = false;
var data = false;
var mode2 = false;
var firstAudio = false;
var firstData = false;
var audio = false;
foreach(Track bwTrack in Tracks)
{
@@ -1199,7 +1233,7 @@ public sealed partial class BlindWrite5
Sessions.Count > 1 &&
mode2)
_imageInfo.MediaType = MediaType.CDPLUS;
else if((firstData && audio) || mode2)
else if(firstData && audio || mode2)
_imageInfo.MediaType = MediaType.CDROMXA;
else if(!audio)
_imageInfo.MediaType = MediaType.CDROM;
@@ -1229,14 +1263,15 @@ public sealed partial class BlindWrite5
{
PMA.CDPMA pma0 = PMA.Decode(_pma).Value;
foreach(uint id in from descriptor in pma0.PMADescriptors where descriptor.ADR == 2
foreach(uint id in from descriptor in pma0.PMADescriptors
where descriptor.ADR == 2
select (uint)((descriptor.Min << 16) + (descriptor.Sec << 8) + descriptor.Frame))
_imageInfo.MediaSerialNumber = $"{id & 0x00FFFFFF:X6}";
}
if(_atip != null)
{
byte[] atipTmp = new byte[_atip.Length + 4];
var atipTmp = new byte[_atip.Length + 4];
Array.Copy(_atip, 0, atipTmp, 4, _atip.Length);
atipTmp[0] = (byte)((_atip.Length & 0xFF00) >> 8);
atipTmp[1] = (byte)(_atip.Length & 0xFF);
@@ -1253,7 +1288,7 @@ public sealed partial class BlindWrite5
}
}
bool isBd = false;
var isBd = false;
if(_imageInfo.MediaType is MediaType.BDR or MediaType.BDRE or MediaType.BDROM)
{
@@ -1262,12 +1297,14 @@ public sealed partial class BlindWrite5
}
if(isBd && _imageInfo.Sectors > 24438784)
{
_imageInfo.MediaType = _imageInfo.MediaType switch
{
MediaType.BDR => MediaType.BDRXL,
MediaType.BDRE => MediaType.BDREXL,
_ => _imageInfo.MediaType
};
{
MediaType.BDR => MediaType.BDRXL,
MediaType.BDRE => MediaType.BDREXL,
_ => _imageInfo.MediaType
};
}
AaruConsole.DebugWriteLine(MODULE_NAME, "ImageInfo.mediaType = {0}", _imageInfo.MediaType);
@@ -1284,10 +1321,12 @@ public sealed partial class BlindWrite5
_imageInfo.ReadableMediaTags.Add(MediaTagType.CD_TEXT);
if(_bca != null)
{
if(isDvd)
_imageInfo.ReadableMediaTags.Add(MediaTagType.DVD_BCA);
else if(isBd)
_imageInfo.ReadableMediaTags.Add(MediaTagType.BD_BCA);
}
byte[] tmp;
@@ -1369,7 +1408,8 @@ public sealed partial class BlindWrite5
buffer = _fullToc?.Clone() as byte[];
return buffer != null ? ErrorNumber.NoError : ErrorNumber.NoData;
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
}
@@ -1393,10 +1433,13 @@ public sealed partial class BlindWrite5
{
buffer = null;
foreach(KeyValuePair<uint, ulong> kvp in from kvp in _offsetMap where sectorAddress >= kvp.Value
from track in Tracks where track.Sequence == kvp.Key
foreach(KeyValuePair<uint, ulong> kvp in from kvp in _offsetMap
where sectorAddress >= kvp.Value
from track in Tracks
where track.Sequence == kvp.Key
where sectorAddress - kvp.Value <
track.EndSector - track.StartSector + 1 select kvp)
track.EndSector - track.StartSector + 1
select kvp)
return ReadSectors(sectorAddress - kvp.Value, length, kvp.Key, out buffer);
return ErrorNumber.SectorNotFound;
@@ -1407,10 +1450,13 @@ public sealed partial class BlindWrite5
{
buffer = null;
foreach(KeyValuePair<uint, ulong> kvp in from kvp in _offsetMap where sectorAddress >= kvp.Value
from track in Tracks where track.Sequence == kvp.Key
foreach(KeyValuePair<uint, ulong> kvp in from kvp in _offsetMap
where sectorAddress >= kvp.Value
from track in Tracks
where track.Sequence == kvp.Key
where sectorAddress - kvp.Value <
track.EndSector - track.StartSector + 1 select kvp)
track.EndSector - track.StartSector + 1
select kvp)
return ReadSectorsTag(sectorAddress - kvp.Value, length, kvp.Key, tag, out buffer);
return ErrorNumber.SectorNotFound;
@@ -1430,8 +1476,10 @@ public sealed partial class BlindWrite5
if(length + sectorAddress > aaruTrack.EndSector - aaruTrack.StartSector + 1)
return ErrorNumber.OutOfRange;
DataFileCharacteristics chars = (from characteristics in _filePaths let firstSector = characteristics.StartLba
let lastSector = firstSector + characteristics.Sectors - 1 let wantedSector =
DataFileCharacteristics chars = (from characteristics in _filePaths
let firstSector = characteristics.StartLba
let lastSector = firstSector + characteristics.Sectors - 1
let wantedSector =
(int)(sectorAddress + aaruTrack.StartSector)
where wantedSector >= firstSector && wantedSector <= lastSector
select characteristics).FirstOrDefault();
@@ -1443,7 +1491,7 @@ public sealed partial class BlindWrite5
uint sectorOffset;
uint sectorSize;
uint sectorSkip;
bool mode2 = false;
var mode2 = false;
switch(aaruTrack.Type)
{
@@ -1482,7 +1530,8 @@ public sealed partial class BlindWrite5
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
switch(chars.Subchannel)
@@ -1499,7 +1548,8 @@ public sealed partial class BlindWrite5
sectorSkip += 96;
break;
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
buffer = new byte[sectorSize * length];
@@ -1517,9 +1567,9 @@ public sealed partial class BlindWrite5
buffer = br.ReadBytes((int)((sectorSize + sectorSkip) * length));
for(int i = 0; i < length; i++)
for(var i = 0; i < length; i++)
{
byte[] sector = new byte[sectorSize];
var sector = new byte[sectorSize];
Array.Copy(buffer, (sectorSize + sectorSkip) * i, sector, 0, sectorSize);
sector = Sector.GetUserDataFromMode2(sector);
mode2Ms.Write(sector, 0, sector.Length);
@@ -1531,19 +1581,21 @@ public sealed partial class BlindWrite5
sectorSkip == 0)
buffer = br.ReadBytes((int)(sectorSize * length));
else
for(int i = 0; i < length; i++)
{
for(var i = 0; i < length; i++)
{
br.BaseStream.Seek(sectorOffset, SeekOrigin.Current);
byte[] sector = br.ReadBytes((int)sectorSize);
br.BaseStream.Seek(sectorSkip, SeekOrigin.Current);
Array.Copy(sector, 0, buffer, i * sectorSize, sectorSize);
}
}
return ErrorNumber.NoError;
}
/// <inheritdoc />
public ErrorNumber ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag,
public ErrorNumber ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag,
out byte[] buffer)
{
buffer = null;
@@ -1557,8 +1609,10 @@ public sealed partial class BlindWrite5
if(length + sectorAddress > aaruTrack.EndSector - aaruTrack.StartSector + 1)
return ErrorNumber.OutOfRange;
DataFileCharacteristics chars = (from characteristics in _filePaths let firstSector = characteristics.StartLba
let lastSector = firstSector + characteristics.Sectors - 1 let wantedSector =
DataFileCharacteristics chars = (from characteristics in _filePaths
let firstSector = characteristics.StartLba
let lastSector = firstSector + characteristics.Sectors - 1
let wantedSector =
(int)(sectorAddress + aaruTrack.StartSector)
where wantedSector >= firstSector && wantedSector <= lastSector
select characteristics).FirstOrDefault();
@@ -1579,18 +1633,17 @@ public sealed partial class BlindWrite5
case SectorTagType.CdSectorHeader:
case SectorTagType.CdSectorSubchannel:
case SectorTagType.CdSectorSubHeader:
case SectorTagType.CdSectorSync: break;
case SectorTagType.CdSectorSync:
break;
case SectorTagType.CdTrackFlags:
if(!_trackFlags.TryGetValue((uint)sectorAddress, out byte flag))
return ErrorNumber.NoData;
buffer = new[]
{
flag
};
buffer = new[] { flag };
return ErrorNumber.NoError;
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
uint sectorOffset;
@@ -1618,7 +1671,8 @@ public sealed partial class BlindWrite5
break;
}
case SectorTagType.CdSectorSubHeader: return ErrorNumber.NotSupported;
case SectorTagType.CdSectorSubHeader:
return ErrorNumber.NotSupported;
case SectorTagType.CdSectorEcc:
{
sectorOffset = 2076;
@@ -1682,12 +1736,14 @@ public sealed partial class BlindWrite5
return ErrorNumber.NoError;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
break;
@@ -1699,7 +1755,8 @@ public sealed partial class BlindWrite5
case SectorTagType.CdSectorHeader:
case SectorTagType.CdSectorEcc:
case SectorTagType.CdSectorEccP:
case SectorTagType.CdSectorEccQ: return ErrorNumber.NotSupported;
case SectorTagType.CdSectorEccQ:
return ErrorNumber.NotSupported;
case SectorTagType.CdSectorSubHeader:
{
sectorOffset = 0;
@@ -1747,12 +1804,14 @@ public sealed partial class BlindWrite5
return ErrorNumber.NoError;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
break;
@@ -1847,12 +1906,14 @@ public sealed partial class BlindWrite5
return ErrorNumber.NoError;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
break;
@@ -1922,12 +1983,14 @@ public sealed partial class BlindWrite5
return ErrorNumber.NoError;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
break;
@@ -1965,20 +2028,24 @@ public sealed partial class BlindWrite5
return ErrorNumber.NoError;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
if(tag != SectorTagType.CdSectorSubchannel)
{
switch(chars.Subchannel)
{
case TrackSubchannelType.None:
@@ -1993,8 +2060,10 @@ public sealed partial class BlindWrite5
sectorSkip += 96;
break;
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
}
buffer = new byte[sectorSize * length];
@@ -2009,23 +2078,25 @@ public sealed partial class BlindWrite5
sectorSkip == 0)
buffer = br.ReadBytes((int)(sectorSize * length));
else
for(int i = 0; i < length; i++)
{
for(var i = 0; i < length; i++)
{
br.BaseStream.Seek(sectorOffset, SeekOrigin.Current);
byte[] sector = br.ReadBytes((int)sectorSize);
br.BaseStream.Seek(sectorSkip, SeekOrigin.Current);
Array.Copy(sector, 0, buffer, i * sectorSize, sectorSize);
}
}
if(tag != SectorTagType.CdSectorSubchannel)
return ErrorNumber.NoError;
buffer = chars.Subchannel switch
{
TrackSubchannelType.Q16Interleaved => Subchannel.ConvertQToRaw(buffer),
TrackSubchannelType.PackedInterleaved => Subchannel.Interleave(buffer),
_ => buffer
};
{
TrackSubchannelType.Q16Interleaved => Subchannel.ConvertQToRaw(buffer),
TrackSubchannelType.PackedInterleaved => Subchannel.Interleave(buffer),
_ => buffer
};
return ErrorNumber.NoError;
}
@@ -2043,10 +2114,13 @@ public sealed partial class BlindWrite5
{
buffer = null;
foreach(KeyValuePair<uint, ulong> kvp in from kvp in _offsetMap where sectorAddress >= kvp.Value
from track in Tracks where track.Sequence == kvp.Key
foreach(KeyValuePair<uint, ulong> kvp in from kvp in _offsetMap
where sectorAddress >= kvp.Value
from track in Tracks
where track.Sequence == kvp.Key
where sectorAddress - kvp.Value <
track.EndSector - track.StartSector + 1 select kvp)
track.EndSector - track.StartSector + 1
select kvp)
return ReadSectorsLong(sectorAddress - kvp.Value, length, kvp.Key, out buffer);
return ErrorNumber.SectorNotFound;
@@ -2066,8 +2140,10 @@ public sealed partial class BlindWrite5
if(length + sectorAddress > aaruTrack.EndSector - aaruTrack.StartSector + 1)
return ErrorNumber.OutOfRange;
DataFileCharacteristics chars = (from characteristics in _filePaths let firstSector = characteristics.StartLba
let lastSector = firstSector + characteristics.Sectors - 1 let wantedSector =
DataFileCharacteristics chars = (from characteristics in _filePaths
let firstSector = characteristics.StartLba
let lastSector = firstSector + characteristics.Sectors - 1
let wantedSector =
(int)(sectorAddress + aaruTrack.StartSector)
where wantedSector >= firstSector && wantedSector <= lastSector
select characteristics).FirstOrDefault();
@@ -2102,7 +2178,8 @@ public sealed partial class BlindWrite5
break;
}
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
switch(chars.Subchannel)
@@ -2119,7 +2196,8 @@ public sealed partial class BlindWrite5
sectorSkip += 96;
break;
default: return ErrorNumber.NotSupported;
default:
return ErrorNumber.NotSupported;
}
buffer = new byte[sectorSize * length];
@@ -2133,13 +2211,15 @@ public sealed partial class BlindWrite5
if(sectorSkip == 0)
buffer = br.ReadBytes((int)(sectorSize * length));
else
for(int i = 0; i < length; i++)
{
for(var i = 0; i < length; i++)
{
br.BaseStream.Seek(sectorOffset, SeekOrigin.Current);
byte[] sector = br.ReadBytes((int)sectorSize);
br.BaseStream.Seek(sectorSkip, SeekOrigin.Current);
Array.Copy(sector, 0, buffer, i * sectorSize, sectorSize);
}
}
return ErrorNumber.NoError;
}
@@ -2151,4 +2231,6 @@ public sealed partial class BlindWrite5
/// <inheritdoc />
public List<Track> GetSessionTracks(ushort session) =>
Tracks.Where(aaruTrack => aaruTrack.Session == session).ToList();
#endregion
}

View File

@@ -39,6 +39,50 @@ namespace Aaru.DiscImages;
public sealed partial class BlindWrite5
{
#region Nested type: DataFile
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct DataFile
{
public uint Type;
public uint Length;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public uint[] Unknown1;
public uint Offset;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public uint[] Unknown2;
public int StartLba;
public int Sectors;
public uint FilenameLen;
public byte[] FilenameBytes;
public uint Unknown3;
public string Filename;
/// <inheritdoc />
public readonly override string ToString() => Filename;
}
#endregion
#region Nested type: DataFileCharacteristics
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct DataFileCharacteristics
{
public IFilter FileFilter;
public string FilePath;
public TrackSubchannelType Subchannel;
public long SectorSize;
public int StartLba;
public int Sectors;
public uint Offset;
}
#endregion
#region Nested type: Header
[StructLayout(LayoutKind.Sequential, Pack = 1)]
readonly struct Header
{
@@ -85,28 +129,27 @@ public sealed partial class BlindWrite5
public readonly uint dpmLen;
}
#endregion
#region Nested type: SessionDescriptor
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct DataFile
struct SessionDescriptor
{
public uint Type;
public uint Length;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public uint[] Unknown1;
public uint Offset;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public uint[] Unknown2;
public int StartLba;
public int Sectors;
public uint FilenameLen;
public byte[] FilenameBytes;
public uint Unknown3;
public string Filename;
/// <inheritdoc />
public readonly override string ToString() => Filename;
public ushort Sequence;
public byte Entries;
public byte Unknown;
public int Start;
public int End;
public ushort FirstTrack;
public ushort LastTrack;
public TrackDescriptor[] Tracks;
}
#endregion
#region Nested type: TrackDescriptor
[StructLayout(LayoutKind.Sequential, Pack = 1)]
readonly struct TrackDescriptor
{
@@ -143,28 +186,5 @@ public sealed partial class BlindWrite5
public readonly uint[] unknown9;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SessionDescriptor
{
public ushort Sequence;
public byte Entries;
public byte Unknown;
public int Start;
public int End;
public ushort FirstTrack;
public ushort LastTrack;
public TrackDescriptor[] Tracks;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct DataFileCharacteristics
{
public IFilter FileFilter;
public string FilePath;
public TrackSubchannelType Subchannel;
public long SectorSize;
public int StartLba;
public int Sectors;
public uint Offset;
}
#endregion
}

View File

@@ -39,6 +39,8 @@ namespace Aaru.DiscImages;
public sealed partial class BlindWrite5
{
#region IOpticalMediaImage Members
/// <inheritdoc />
public bool? VerifySector(ulong sectorAddress)
{
@@ -48,7 +50,7 @@ public sealed partial class BlindWrite5
}
/// <inheritdoc />
public bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas,
public bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
@@ -58,10 +60,10 @@ public sealed partial class BlindWrite5
if(errno != ErrorNumber.NoError)
return null;
int bps = (int)(buffer.Length / length);
byte[] sector = new byte[bps];
var bps = (int)(buffer.Length / length);
var sector = new byte[bps];
for(int i = 0; i < length; i++)
for(var i = 0; i < length; i++)
{
Array.Copy(buffer, i * bps, sector, 0, bps);
bool? sectorStatus = CdChecksums.CheckCdSector(sector);
@@ -86,7 +88,7 @@ public sealed partial class BlindWrite5
}
/// <inheritdoc />
public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
@@ -96,10 +98,10 @@ public sealed partial class BlindWrite5
if(errno != ErrorNumber.NoError)
return null;
int bps = (int)(buffer.Length / length);
byte[] sector = new byte[bps];
var bps = (int)(buffer.Length / length);
var sector = new byte[bps];
for(int i = 0; i < length; i++)
for(var i = 0; i < length; i++)
{
Array.Copy(buffer, i * bps, sector, 0, bps);
bool? sectorStatus = CdChecksums.CheckCdSector(sector);
@@ -122,4 +124,6 @@ public sealed partial class BlindWrite5
return failingLbas.Count <= 0;
}
#endregion
}

View File

@@ -20,18 +20,27 @@ public class AtariLynx : IByteAddressableImage
Stream _dataStream;
ImageInfo _imageInfo;
bool _opened;
#region IByteAddressableImage Members
/// <inheritdoc />
public string Author => Authors.NataliaPortillo;
/// <inheritdoc />
public Metadata AaruMetadata => null;
/// <inheritdoc />
public List<DumpHardware> DumpHardware => null;
/// <inheritdoc />
public string Format => "Atari Lynx cartridge dump";
/// <inheritdoc />
public Guid Id => new("809A6835-0486-4FD3-BD8B-2EF40C3EF97B");
/// <inheritdoc />
public ImageInfo Info => _imageInfo;
/// <inheritdoc />
public string Name => Localization.AtariLynx_Name;
@@ -48,9 +57,9 @@ public class AtariLynx : IByteAddressableImage
return false;
stream.Position = 0;
byte[] magicBytes = new byte[4];
var magicBytes = new byte[4];
stream.EnsureRead(magicBytes, 0, 4);
uint magic = BitConverter.ToUInt32(magicBytes, 0);
var magic = BitConverter.ToUInt32(magicBytes, 0);
// "LYNX"
return magic == 0x584E594C;
@@ -69,14 +78,14 @@ public class AtariLynx : IByteAddressableImage
return ErrorNumber.InvalidArgument;
stream.Position = 0x0;
byte[] magicBytes = new byte[4];
var magicBytes = new byte[4];
stream.EnsureRead(magicBytes, 0, 4);
uint magic = BitConverter.ToUInt32(magicBytes, 0);
var magic = BitConverter.ToUInt32(magicBytes, 0);
if(magic != 0x584E594C)
return ErrorNumber.InvalidArgument;
byte[] headerBytes = new byte[64];
var headerBytes = new byte[64];
stream.Position = 0;
stream.EnsureRead(headerBytes, 0, 64);
@@ -104,7 +113,7 @@ public class AtariLynx : IByteAddressableImage
var sb = new StringBuilder();
sb.AppendFormat(Localization.Name_0, _imageInfo.MediaTitle).AppendLine();
sb.AppendFormat(Localization.Name_0, _imageInfo.MediaTitle).AppendLine();
sb.AppendFormat(Localization.Manufacturer_0, _imageInfo.MediaManufacturer).AppendLine();
sb.AppendFormat(Localization.Bank_zero_size_0_pages_1_bytes, header.Bank0Length, header.Bank0Length * 65536).
@@ -123,29 +132,29 @@ public class AtariLynx : IByteAddressableImage
/// <inheritdoc />
public string ErrorMessage { get; private set; }
/// <inheritdoc />
public bool IsWriting { get; private set; }
/// <inheritdoc />
public IEnumerable<string> KnownExtensions => new[]
{
".lnx"
};
public IEnumerable<string> KnownExtensions => new[] { ".lnx" };
/// <inheritdoc />
public IEnumerable<MediaTagType> SupportedMediaTags => Array.Empty<MediaTagType>();
/// <inheritdoc />
public IEnumerable<MediaType> SupportedMediaTypes => new[]
{
MediaType.AtariLynxCard
};
public IEnumerable<MediaType> SupportedMediaTypes => new[] { MediaType.AtariLynxCard };
/// <inheritdoc />
public IEnumerable<(string name, Type type, string description, object @default)> SupportedOptions =>
Array.Empty<(string name, Type type, string description, object @default)>();
/// <inheritdoc />
public IEnumerable<SectorTagType> SupportedSectorTags => Array.Empty<SectorTagType>();
/// <inheritdoc />
public bool Create(string path, MediaType mediaType, Dictionary<string, string> options, ulong sectors,
uint sectorSize) => Create(path, mediaType, options, (long)sectors) == ErrorNumber.NoError;
uint sectorSize) => Create(path, mediaType, options, (long)sectors) == ErrorNumber.NoError;
/// <inheritdoc />
public bool Close()
@@ -168,8 +177,8 @@ public class AtariLynx : IByteAddressableImage
HandyHeader header = new()
{
Bank0Length = (short)(_data.Length > 4 * 131072 ? 4 * 131072 / 256 : _data.Length / 256),
Bank1Length = (short)(_data.Length > 4 * 131072 ? (_data.Length - (4 * 131072)) / 256 : 0),
Bank0Length = (short)(_data.Length > 4 * 131072 ? 4 * 131072 / 256 : _data.Length / 256),
Bank1Length = (short)(_data.Length > 4 * 131072 ? (_data.Length - 4 * 131072) / 256 : 0),
Magic = 0x584E594C,
Manufacturer = new byte[16],
Name = new byte[32],
@@ -185,7 +194,7 @@ public class AtariLynx : IByteAddressableImage
byte[] headerBytes = Marshal.StructureToByteArrayBigEndian(header);
_dataStream.Write(headerBytes, 0, headerBytes.Length);
_dataStream.Write(_data, 0, _data.Length);
_dataStream.Write(_data, 0, _data.Length);
_dataStream.Close();
IsWriting = false;
@@ -396,18 +405,21 @@ public class AtariLynx : IByteAddressableImage
return ErrorNumber.ReadOnly;
}
bool foundRom = false;
var foundRom = false;
// Sanitize
foreach(LinearMemoryDevice map in mappings.Devices)
{
switch(map.Type)
{
case LinearMemoryType.ROM when !foundRom:
foundRom = true;
break;
default: return ErrorNumber.InvalidArgument;
default:
return ErrorNumber.InvalidArgument;
}
}
// Cannot save in this image format anyway
return foundRom ? ErrorNumber.NoError : ErrorNumber.InvalidArgument;
@@ -450,7 +462,7 @@ public class AtariLynx : IByteAddressableImage
/// <inheritdoc />
public ErrorNumber WriteBytes(byte[] buffer, int offset, int bytesToWrite, out int bytesWritten,
bool advance = true) =>
bool advance = true) =>
WriteBytesAt(Position, buffer, offset, bytesToWrite, out bytesWritten, advance);
/// <inheritdoc />
@@ -503,8 +515,13 @@ public class AtariLynx : IByteAddressableImage
return ErrorNumber.NoError;
}
[StructLayout(LayoutKind.Sequential, Pack = 1), SuppressMessage("ReSharper", "MemberCanBePrivate.Local"),
SuppressMessage("ReSharper", "FieldCanBeMadeReadOnly.Local")]
#endregion
#region Nested type: HandyHeader
[StructLayout(LayoutKind.Sequential, Pack = 1)]
[SuppressMessage("ReSharper", "MemberCanBePrivate.Local")]
[SuppressMessage("ReSharper", "FieldCanBeMadeReadOnly.Local")]
struct HandyHeader
{
public uint Magic;
@@ -519,4 +536,6 @@ public class AtariLynx : IByteAddressableImage
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public byte[] Spare;
}
#endregion
}

View File

@@ -20,18 +20,27 @@ public class GameBoy : IByteAddressableImage
Stream _dataStream;
ImageInfo _imageInfo;
bool _opened;
#region IByteAddressableImage Members
/// <inheritdoc />
public string Author => Authors.NataliaPortillo;
/// <inheritdoc />
public Metadata AaruMetadata => null;
/// <inheritdoc />
public List<DumpHardware> DumpHardware => null;
/// <inheritdoc />
public string Format => "Nintendo Game Boy cartridge dump";
/// <inheritdoc />
public Guid Id => new("04AFDB93-587E-413B-9B52-10D4A92966CF");
/// <inheritdoc />
public ImageInfo Info => _imageInfo;
/// <inheritdoc />
public string Name => Localization.GameBoy_Name;
@@ -48,9 +57,9 @@ public class GameBoy : IByteAddressableImage
return false;
stream.Position = 0x104;
byte[] magicBytes = new byte[8];
var magicBytes = new byte[8];
stream.EnsureRead(magicBytes, 0, 8);
ulong magic = BitConverter.ToUInt64(magicBytes, 0);
var magic = BitConverter.ToUInt64(magicBytes, 0);
return magic == 0x0B000DCC6666EDCE;
}
@@ -68,9 +77,9 @@ public class GameBoy : IByteAddressableImage
return ErrorNumber.InvalidArgument;
stream.Position = 0x104;
byte[] magicBytes = new byte[8];
var magicBytes = new byte[8];
stream.EnsureRead(magicBytes, 0, 8);
ulong magic = BitConverter.ToUInt64(magicBytes, 0);
var magic = BitConverter.ToUInt64(magicBytes, 0);
if(magic != 0x0B000DCC6666EDCE)
return ErrorNumber.InvalidArgument;
@@ -92,7 +101,7 @@ public class GameBoy : IByteAddressableImage
Header header = Marshal.ByteArrayToStructureBigEndian<Header>(_data, 0x100, Marshal.SizeOf<Header>());
byte[] name = new byte[(header.Name[^1] & 0x80) == 0x80 ? 15 : 16];
var name = new byte[(header.Name[^1] & 0x80) == 0x80 ? 15 : 16];
Array.Copy(header.Name, 0, name, 0, name.Length);
_imageInfo.MediaTitle = StringHandlers.CToString(name);
@@ -134,29 +143,29 @@ public class GameBoy : IByteAddressableImage
/// <inheritdoc />
public string ErrorMessage { get; private set; }
/// <inheritdoc />
public bool IsWriting { get; private set; }
/// <inheritdoc />
public IEnumerable<string> KnownExtensions => new[]
{
".gb", ".gbc", ".sgb"
};
public IEnumerable<string> KnownExtensions => new[] { ".gb", ".gbc", ".sgb" };
/// <inheritdoc />
public IEnumerable<MediaTagType> SupportedMediaTags => Array.Empty<MediaTagType>();
/// <inheritdoc />
public IEnumerable<MediaType> SupportedMediaTypes => new[]
{
MediaType.GameBoyGamePak
};
public IEnumerable<MediaType> SupportedMediaTypes => new[] { MediaType.GameBoyGamePak };
/// <inheritdoc />
public IEnumerable<(string name, Type type, string description, object @default)> SupportedOptions =>
Array.Empty<(string name, Type type, string description, object @default)>();
/// <inheritdoc />
public IEnumerable<SectorTagType> SupportedSectorTags => Array.Empty<SectorTagType>();
/// <inheritdoc />
public bool Create(string path, MediaType mediaType, Dictionary<string, string> options, ulong sectors,
uint sectorSize) => Create(path, mediaType, options, (long)sectors) == ErrorNumber.NoError;
uint sectorSize) => Create(path, mediaType, options, (long)sectors) == ErrorNumber.NoError;
/// <inheritdoc />
public bool Close()
@@ -253,8 +262,8 @@ public class GameBoy : IByteAddressableImage
Header header = Marshal.ByteArrayToStructureBigEndian<Header>(_data, 0x100, Marshal.SizeOf<Header>());
bool hasMapper = false;
bool hasSaveRam = false;
var hasMapper = false;
var hasSaveRam = false;
string mapperManufacturer = null;
string mapperName = null;
@@ -474,7 +483,7 @@ public class GameBoy : IByteAddressableImage
if(header.SramSize > 0)
hasSaveRam = true;
int devices = 1;
var devices = 1;
if(hasSaveRam)
devices++;
@@ -493,6 +502,7 @@ public class GameBoy : IByteAddressableImage
};
if(hasSaveRam)
{
mappings.Devices[1] = new LinearMemoryDevice
{
Type = LinearMemoryType.SaveRAM,
@@ -502,14 +512,17 @@ public class GameBoy : IByteAddressableImage
Length = DecodeSaveRamSize(header.SramSize)
}
};
}
if(hasMapper)
{
mappings.Devices[^1] = new LinearMemoryDevice
{
Type = LinearMemoryType.Mapper,
Manufacturer = mapperManufacturer,
Model = mapperName
};
}
return ErrorNumber.NoError;
}
@@ -608,12 +621,13 @@ public class GameBoy : IByteAddressableImage
return ErrorNumber.ReadOnly;
}
bool foundRom = false;
bool foundSaveRam = false;
bool foundMapper = false;
var foundRom = false;
var foundSaveRam = false;
var foundMapper = false;
// Sanitize
foreach(LinearMemoryDevice map in mappings.Devices)
{
switch(map.Type)
{
case LinearMemoryType.ROM when !foundRom:
@@ -628,8 +642,10 @@ public class GameBoy : IByteAddressableImage
foundMapper = true;
break;
default: return ErrorNumber.InvalidArgument;
default:
return ErrorNumber.InvalidArgument;
}
}
// Cannot save in this image format anyway
return foundRom ? ErrorNumber.NoError : ErrorNumber.InvalidArgument;
@@ -672,7 +688,7 @@ public class GameBoy : IByteAddressableImage
/// <inheritdoc />
public ErrorNumber WriteBytes(byte[] buffer, int offset, int bytesToWrite, out int bytesWritten,
bool advance = true) =>
bool advance = true) =>
WriteBytesAt(Position, buffer, offset, bytesToWrite, out bytesWritten, advance);
/// <inheritdoc />
@@ -725,294 +741,303 @@ public class GameBoy : IByteAddressableImage
return ErrorNumber.NoError;
}
#endregion
[SuppressMessage("ReSharper", "StringLiteralTypo")]
static string DecodeLicensee(byte headerLicensee, byte[] headerLicenseeNew)
{
if(headerLicensee != 0x33)
{
return headerLicensee switch
{
0x00 => Localization.none_licensee,
0x01 => "nintendo",
0x08 => "capcom",
0x09 => "hot-b",
0x0A => "jaleco",
0x0B => "coconuts",
0x0C => "elite systems",
0x13 => "electronic arts",
0x18 => "hudsonsoft",
0x19 => "itc entertainment",
0x1A => "yanoman",
0x1D => "clary",
0x1F => "virgin",
0x20 => "KSS",
0x24 => "pcm complete",
0x25 => "san-x",
0x28 => "kotobuki systems",
0x29 => "seta",
0x30 => "infogrames",
0x31 => "nintendo",
0x32 => "bandai",
0x33 => Localization.GBC_see_above,
0x34 => "konami",
0x35 => "hector",
0x38 => "Capcom",
0x39 => "Banpresto",
0x3C => "*entertainment i",
0x3E => "gremlin",
0x41 => "Ubisoft",
0x42 => "Atlus",
0x44 => "Malibu",
0x46 => "angel",
0x47 => "spectrum holoby",
0x49 => "irem",
0x4A => "virgin",
0x4D => "malibu",
0x4F => "u.s. gold",
0x50 => "absolute",
0x51 => "acclaim",
0x52 => "activision",
0x53 => "american sammy",
0x54 => "gametek",
0x55 => "park place",
0x56 => "ljn",
0x57 => "matchbox",
0x59 => "milton bradley",
0x5A => "mindscape",
0x5B => "romstar",
0x5C => "naxat soft",
0x5D => "tradewest",
0x60 => "titus",
0x61 => "virgin",
0x67 => "ocean",
0x69 => "electronic arts",
0x6E => "elite systems",
0x6F => "electro brain",
0x70 => "Infogrammes",
0x71 => "Interplay",
0x72 => "broderbund",
0x73 => "sculptered soft",
0x75 => "the sales curve",
0x78 => "t*hq",
0x79 => "accolade",
0x7A => "triffix entertainment",
0x7C => "microprose",
0x7F => "kemco",
0x80 => "misawa entertainment",
0x83 => "lozc",
0x86 => "tokuma shoten intermedia",
0x8B => "bullet-proof software",
0x8C => "vic tokai",
0x8E => "ape",
0x8F => "i'max",
0x91 => "chun soft",
0x92 => "video system",
0x93 => "tsuburava",
0x95 => "varie",
0x96 => "yonezawa/s'pal",
0x97 => "kaneko",
0x99 => "arc",
0x9A => "nihon bussan",
0x9B => "Tecmo",
0x9C => "imagineer",
0x9D => "Banpresto",
0x9F => "nova",
0xA1 => "Hori electric",
0xA2 => "Bandai",
0xA4 => "Konami",
0xA6 => "kawada",
0xA7 => "takara",
0xA9 => "technos japan",
0xAA => "broderbund",
0xAC => "Toei animation",
0xAD => "toho",
0xAF => "Namco",
0xB0 => "Acclaim",
0xB1 => "ascii or nexoft",
0xB2 => "Bandai",
0xB4 => "Enix",
0xB6 => "HAL",
0xB7 => "SNK",
0xB9 => "pony canyon",
0xBA => "*culture brain o",
0xBB => "Sunsoft",
0xBD => "Sony imagesoft",
0xBF => "sammy",
0xC0 => "Taito",
0xC2 => "Kemco",
0xC3 => "Squaresoft",
0xC4 => "tokuma shoten intermedia",
0xC5 => "data east",
0xC6 => "tonkin house",
0xC8 => "koei",
0xC9 => "ufl",
0xCA => "ultra",
0xCB => "vap",
0xCC => "use",
0xCD => "meldac",
0xCE => "*pony canyon or",
0xCF => "angel",
0xD0 => "Taito",
0xD1 => "sofel",
0xD2 => "quest",
0xD3 => "sigma enterprises",
0xD4 => "ask kodansha",
0xD6 => "naxat soft",
0xD7 => "copya systems",
0xD9 => "Banpresto",
0xDA => "tomy",
0xDB => "ljn",
0xDD => "ncs",
0xDE => "human",
0xDF => "altron",
0xE0 => "jaleco",
0xE1 => "towachiki",
0xE2 => "uutaka",
0xE3 => "varie",
0xE5 => "epoch",
0xE7 => "athena",
0xE8 => "asmik",
0xE9 => "natsume",
0xEA => "king records",
0xEB => "atlus",
0xEC => "Epic/Sony records",
0xEE => "igs",
0xF0 => "a wave",
0xF3 => "extreme entertainment",
0xFF => "ljn",
_ => Localization.Unknown_licensee
};
{
0x00 => Localization.none_licensee,
0x01 => "nintendo",
0x08 => "capcom",
0x09 => "hot-b",
0x0A => "jaleco",
0x0B => "coconuts",
0x0C => "elite systems",
0x13 => "electronic arts",
0x18 => "hudsonsoft",
0x19 => "itc entertainment",
0x1A => "yanoman",
0x1D => "clary",
0x1F => "virgin",
0x20 => "KSS",
0x24 => "pcm complete",
0x25 => "san-x",
0x28 => "kotobuki systems",
0x29 => "seta",
0x30 => "infogrames",
0x31 => "nintendo",
0x32 => "bandai",
0x33 => Localization.GBC_see_above,
0x34 => "konami",
0x35 => "hector",
0x38 => "Capcom",
0x39 => "Banpresto",
0x3C => "*entertainment i",
0x3E => "gremlin",
0x41 => "Ubisoft",
0x42 => "Atlus",
0x44 => "Malibu",
0x46 => "angel",
0x47 => "spectrum holoby",
0x49 => "irem",
0x4A => "virgin",
0x4D => "malibu",
0x4F => "u.s. gold",
0x50 => "absolute",
0x51 => "acclaim",
0x52 => "activision",
0x53 => "american sammy",
0x54 => "gametek",
0x55 => "park place",
0x56 => "ljn",
0x57 => "matchbox",
0x59 => "milton bradley",
0x5A => "mindscape",
0x5B => "romstar",
0x5C => "naxat soft",
0x5D => "tradewest",
0x60 => "titus",
0x61 => "virgin",
0x67 => "ocean",
0x69 => "electronic arts",
0x6E => "elite systems",
0x6F => "electro brain",
0x70 => "Infogrammes",
0x71 => "Interplay",
0x72 => "broderbund",
0x73 => "sculptered soft",
0x75 => "the sales curve",
0x78 => "t*hq",
0x79 => "accolade",
0x7A => "triffix entertainment",
0x7C => "microprose",
0x7F => "kemco",
0x80 => "misawa entertainment",
0x83 => "lozc",
0x86 => "tokuma shoten intermedia",
0x8B => "bullet-proof software",
0x8C => "vic tokai",
0x8E => "ape",
0x8F => "i'max",
0x91 => "chun soft",
0x92 => "video system",
0x93 => "tsuburava",
0x95 => "varie",
0x96 => "yonezawa/s'pal",
0x97 => "kaneko",
0x99 => "arc",
0x9A => "nihon bussan",
0x9B => "Tecmo",
0x9C => "imagineer",
0x9D => "Banpresto",
0x9F => "nova",
0xA1 => "Hori electric",
0xA2 => "Bandai",
0xA4 => "Konami",
0xA6 => "kawada",
0xA7 => "takara",
0xA9 => "technos japan",
0xAA => "broderbund",
0xAC => "Toei animation",
0xAD => "toho",
0xAF => "Namco",
0xB0 => "Acclaim",
0xB1 => "ascii or nexoft",
0xB2 => "Bandai",
0xB4 => "Enix",
0xB6 => "HAL",
0xB7 => "SNK",
0xB9 => "pony canyon",
0xBA => "*culture brain o",
0xBB => "Sunsoft",
0xBD => "Sony imagesoft",
0xBF => "sammy",
0xC0 => "Taito",
0xC2 => "Kemco",
0xC3 => "Squaresoft",
0xC4 => "tokuma shoten intermedia",
0xC5 => "data east",
0xC6 => "tonkin house",
0xC8 => "koei",
0xC9 => "ufl",
0xCA => "ultra",
0xCB => "vap",
0xCC => "use",
0xCD => "meldac",
0xCE => "*pony canyon or",
0xCF => "angel",
0xD0 => "Taito",
0xD1 => "sofel",
0xD2 => "quest",
0xD3 => "sigma enterprises",
0xD4 => "ask kodansha",
0xD6 => "naxat soft",
0xD7 => "copya systems",
0xD9 => "Banpresto",
0xDA => "tomy",
0xDB => "ljn",
0xDD => "ncs",
0xDE => "human",
0xDF => "altron",
0xE0 => "jaleco",
0xE1 => "towachiki",
0xE2 => "uutaka",
0xE3 => "varie",
0xE5 => "epoch",
0xE7 => "athena",
0xE8 => "asmik",
0xE9 => "natsume",
0xEA => "king records",
0xEB => "atlus",
0xEC => "Epic/Sony records",
0xEE => "igs",
0xF0 => "a wave",
0xF3 => "extreme entertainment",
0xFF => "ljn",
_ => Localization.Unknown_licensee
};
}
string licenseeNew = StringHandlers.CToString(headerLicenseeNew);
return licenseeNew switch
{
"00" => Localization.none_licensee,
"01" => "Nintendo R&D1",
"08" => "Capcom",
"13" => "Electronic Arts",
"18" => "Hudson Soft",
"19" => "b-ai",
"20" => "kss",
"22" => "pow",
"24" => "PCM Complete",
"25" => "san-x",
"28" => "Kemco Japan",
"29" => "seta",
"30" => "Viacom",
"31" => "Nintendo",
"32" => "Bandai",
"33" => "Ocean / Acclaim",
"34" => "Konami",
"35" => "Hector",
"37" => "Taito",
"38" => "Hudson",
"39" => "Banpresto",
"41" => "Ubi Soft",
"42" => "Atlus",
"44" => "Malibu",
"46" => "angel",
"47" => "Bullet -Proof",
"49" => "irem",
"50" => "Absolute",
"51" => "Acclaim",
"52" => "Activision",
"53" => "American sammy",
"54" => "Konami",
"55" => "Hi tech entertainment",
"56" => "LJN",
"57" => "Matchbox",
"58" => "Mattel",
"59" => "Milton Bradley",
"60" => "Titus",
"61" => "Virgin",
"64" => "LucasArts",
"67" => "Ocean",
"69" => "Electronic Arts",
"70" => "Infogrames",
"71" => "Interplay",
"72" => "Brøderbund",
"73" => "sculptured",
"75" => "sci",
"78" => "THQ",
"79" => "Accolade",
"80" => "misawa",
"83" => "lozc",
"86" => "tokuma shoten i",
"87" => "tsukuda ori",
"91" => "Chunsoft",
"92" => "Video system",
"93" => "Ocean / Acclaim",
"95" => "Varie",
"96" => "Yonezawa / s'pal",
"97" => "Kaneko",
"99" => "Pack in soft",
"A4" => "Konami",
_ => Localization.Unknown_licensee
};
{
"00" => Localization.none_licensee,
"01" => "Nintendo R&D1",
"08" => "Capcom",
"13" => "Electronic Arts",
"18" => "Hudson Soft",
"19" => "b-ai",
"20" => "kss",
"22" => "pow",
"24" => "PCM Complete",
"25" => "san-x",
"28" => "Kemco Japan",
"29" => "seta",
"30" => "Viacom",
"31" => "Nintendo",
"32" => "Bandai",
"33" => "Ocean / Acclaim",
"34" => "Konami",
"35" => "Hector",
"37" => "Taito",
"38" => "Hudson",
"39" => "Banpresto",
"41" => "Ubi Soft",
"42" => "Atlus",
"44" => "Malibu",
"46" => "angel",
"47" => "Bullet -Proof",
"49" => "irem",
"50" => "Absolute",
"51" => "Acclaim",
"52" => "Activision",
"53" => "American sammy",
"54" => "Konami",
"55" => "Hi tech entertainment",
"56" => "LJN",
"57" => "Matchbox",
"58" => "Mattel",
"59" => "Milton Bradley",
"60" => "Titus",
"61" => "Virgin",
"64" => "LucasArts",
"67" => "Ocean",
"69" => "Electronic Arts",
"70" => "Infogrames",
"71" => "Interplay",
"72" => "Brøderbund",
"73" => "sculptured",
"75" => "sci",
"78" => "THQ",
"79" => "Accolade",
"80" => "misawa",
"83" => "lozc",
"86" => "tokuma shoten i",
"87" => "tsukuda ori",
"91" => "Chunsoft",
"92" => "Video system",
"93" => "Ocean / Acclaim",
"95" => "Varie",
"96" => "Yonezawa / s'pal",
"97" => "Kaneko",
"99" => "Pack in soft",
"A4" => "Konami",
_ => Localization.Unknown_licensee
};
}
static uint DecodeRomSize(byte headerRomType) => headerRomType switch
{
0 => 32768,
1 => 65536,
2 => 131072,
3 => 262144,
4 => 524288,
5 => 1048576,
6 => 2097152,
7 => 4194304,
8 => 8388608,
0x52 => 1179648,
0x53 => 1310720,
0x54 => 1572864,
_ => 0
};
{
0 => 32768,
1 => 65536,
2 => 131072,
3 => 262144,
4 => 524288,
5 => 1048576,
6 => 2097152,
7 => 4194304,
8 => 8388608,
0x52 => 1179648,
0x53 => 1310720,
0x54 => 1572864,
_ => 0
};
static uint DecodeSaveRamSize(byte headerRamType) => headerRamType switch
{
0 => 0,
1 => 2048,
2 => 8192,
3 => 32768,
4 => 131072,
5 => 65536,
_ => 0
};
{
0 => 0,
1 => 2048,
2 => 8192,
3 => 32768,
4 => 131072,
5 => 65536,
_ => 0
};
static string DecodeCartridgeType(byte headerRomType) => headerRomType switch
{
0x00 => Localization.ROM_only,
0x01 => Localization.ROM_and_MBC1,
0x02 => Localization.ROM_MBC1_and_RAM,
0x03 => Localization.ROM_MBC1_RAM_and_battery,
0x05 => Localization.ROM_and_MBC2,
0x06 => Localization.ROM_MBC2_and_battery,
0x08 => Localization.ROM_and_RAM,
0x09 => Localization.ROM_RAM_and_battery,
0x0B => Localization.ROM_and_MMM01,
0x0C => Localization.ROM_MMM01_and_RAM,
0x0D => Localization.ROM_MMM01_RAM_and_battery,
0x0F => Localization.ROM_MBC3_timer_and_battery,
0x10 => Localization.ROM_MBC3_RAM_timer_and_battery,
0x11 => Localization.ROM_and_MBC3,
0x12 => Localization.ROM_MBC3_and_RAM,
0x13 => Localization.ROM_MBC3_RAM_and_battery,
0x19 => Localization.ROM_and_MBC5,
0x1A => Localization.ROM_MBC5_and_RAM,
0x1B => Localization.ROM_MBC5_RAM_and_battery,
0x1C => Localization.ROM_MBC5_and_vibration_motor,
0x1D => Localization.ROM_MBC5_RAM_and_vibration_motor,
0x1E => Localization.ROM_MBC5_RAM_battery_and_vibration_motor,
0x20 => Localization.ROM_and_MBC6,
0x22 => Localization.ROM_MBC7_RAM_battery_light_sensor_and_vibration_motor,
0xFC => Localization.Pocket_Camera,
0xFD => Localization.ROM_and_TAMA5,
0xFE => Localization.ROM_and_HuC_3,
0xFF => Localization.ROM_and_HuC_1,
_ => Localization.Unknown_cartridge_type
};
{
0x00 => Localization.ROM_only,
0x01 => Localization.ROM_and_MBC1,
0x02 => Localization.ROM_MBC1_and_RAM,
0x03 => Localization.ROM_MBC1_RAM_and_battery,
0x05 => Localization.ROM_and_MBC2,
0x06 => Localization.ROM_MBC2_and_battery,
0x08 => Localization.ROM_and_RAM,
0x09 => Localization.ROM_RAM_and_battery,
0x0B => Localization.ROM_and_MMM01,
0x0C => Localization.ROM_MMM01_and_RAM,
0x0D => Localization.ROM_MMM01_RAM_and_battery,
0x0F => Localization.ROM_MBC3_timer_and_battery,
0x10 => Localization.ROM_MBC3_RAM_timer_and_battery,
0x11 => Localization.ROM_and_MBC3,
0x12 => Localization.ROM_MBC3_and_RAM,
0x13 => Localization.ROM_MBC3_RAM_and_battery,
0x19 => Localization.ROM_and_MBC5,
0x1A => Localization.ROM_MBC5_and_RAM,
0x1B => Localization.ROM_MBC5_RAM_and_battery,
0x1C => Localization.ROM_MBC5_and_vibration_motor,
0x1D => Localization.ROM_MBC5_RAM_and_vibration_motor,
0x1E => Localization.
ROM_MBC5_RAM_battery_and_vibration_motor,
0x20 => Localization.ROM_and_MBC6,
0x22 => Localization.
ROM_MBC7_RAM_battery_light_sensor_and_vibration_motor,
0xFC => Localization.Pocket_Camera,
0xFD => Localization.ROM_and_TAMA5,
0xFE => Localization.ROM_and_HuC_3,
0xFF => Localization.ROM_and_HuC_1,
_ => Localization.Unknown_cartridge_type
};
[StructLayout(LayoutKind.Sequential, Pack = 1), SuppressMessage("ReSharper", "FieldCanBeMadeReadOnly.Local")]
#region Nested type: Header
[StructLayout(LayoutKind.Sequential, Pack = 1)]
[SuppressMessage("ReSharper", "FieldCanBeMadeReadOnly.Local")]
struct Header
{
/// <summary>Usually 0x00 (NOP)</summary>
@@ -1049,4 +1074,6 @@ public class GameBoy : IByteAddressableImage
/// <summary>Cartridge checksum</summary>
public ushort Checksum;
}
#endregion
}

View File

@@ -20,18 +20,27 @@ public class GameBoyAdvance : IByteAddressableImage
Stream _dataStream;
ImageInfo _imageInfo;
bool _opened;
#region IByteAddressableImage Members
/// <inheritdoc />
public string Author => Authors.NataliaPortillo;
/// <inheritdoc />
public Metadata AaruMetadata => null;
/// <inheritdoc />
public List<DumpHardware> DumpHardware => null;
/// <inheritdoc />
public string Format => "Nintendo Game Boy Advance cartridge dump";
/// <inheritdoc />
public Guid Id => new("0040DDEB-3902-4402-9028-62915C5AA81F");
/// <inheritdoc />
public ImageInfo Info => _imageInfo;
/// <inheritdoc />
public string Name => Localization.GameBoyAdvance_Name;
@@ -48,9 +57,9 @@ public class GameBoyAdvance : IByteAddressableImage
return false;
stream.Position = 4;
byte[] magicBytes = new byte[8];
var magicBytes = new byte[8];
stream.EnsureRead(magicBytes, 0, 8);
ulong magic = BitConverter.ToUInt64(magicBytes, 0);
var magic = BitConverter.ToUInt64(magicBytes, 0);
return magic == 0x21A29A6951AEFF24;
}
@@ -68,9 +77,9 @@ public class GameBoyAdvance : IByteAddressableImage
return ErrorNumber.InvalidArgument;
stream.Position = 4;
byte[] magicBytes = new byte[8];
var magicBytes = new byte[8];
stream.EnsureRead(magicBytes, 0, 8);
ulong magic = BitConverter.ToUInt64(magicBytes, 0);
var magic = BitConverter.ToUInt64(magicBytes, 0);
if(magic != 0x21A29A6951AEFF24)
return ErrorNumber.InvalidArgument;
@@ -97,12 +106,12 @@ public class GameBoyAdvance : IByteAddressableImage
sb.AppendFormat(Localization.Name_0, _imageInfo.MediaTitle).AppendLine();
sb.AppendFormat(Localization.Device_type_0, header.DeviceType).AppendLine();
sb.AppendFormat(Localization.Console_type_0, header.UnitCode).AppendLine();
sb.AppendFormat(Localization.Device_type_0, header.DeviceType).AppendLine();
sb.AppendFormat(Localization.Console_type_0, header.UnitCode).AppendLine();
sb.AppendFormat(Localization.Product_code_AGB_0, StringHandlers.CToString(header.Code)).AppendLine();
sb.AppendFormat(Localization.Maker_code_0, StringHandlers.CToString(header.Maker)).AppendLine();
sb.AppendFormat(Localization.Revision_0, header.Revision).AppendLine();
sb.AppendFormat(Localization.Header_checksum_0, header.ComplementCheck).AppendLine();
sb.AppendFormat(Localization.Maker_code_0, StringHandlers.CToString(header.Maker)).AppendLine();
sb.AppendFormat(Localization.Revision_0, header.Revision).AppendLine();
sb.AppendFormat(Localization.Header_checksum_0, header.ComplementCheck).AppendLine();
_imageInfo.Comments = sb.ToString();
_opened = true;
@@ -112,29 +121,29 @@ public class GameBoyAdvance : IByteAddressableImage
/// <inheritdoc />
public string ErrorMessage { get; private set; }
/// <inheritdoc />
public bool IsWriting { get; private set; }
/// <inheritdoc />
public IEnumerable<string> KnownExtensions => new[]
{
".gba"
};
public IEnumerable<string> KnownExtensions => new[] { ".gba" };
/// <inheritdoc />
public IEnumerable<MediaTagType> SupportedMediaTags => Array.Empty<MediaTagType>();
/// <inheritdoc />
public IEnumerable<MediaType> SupportedMediaTypes => new[]
{
MediaType.GameBoyAdvanceGamePak
};
public IEnumerable<MediaType> SupportedMediaTypes => new[] { MediaType.GameBoyAdvanceGamePak };
/// <inheritdoc />
public IEnumerable<(string name, Type type, string description, object @default)> SupportedOptions =>
Array.Empty<(string name, Type type, string description, object @default)>();
/// <inheritdoc />
public IEnumerable<SectorTagType> SupportedSectorTags => Array.Empty<SectorTagType>();
/// <inheritdoc />
public bool Create(string path, MediaType mediaType, Dictionary<string, string> options, ulong sectors,
uint sectorSize) => Create(path, mediaType, options, (long)sectors) == ErrorNumber.NoError;
uint sectorSize) => Create(path, mediaType, options, (long)sectors) == ErrorNumber.NoError;
/// <inheritdoc />
public bool Close()
@@ -342,11 +351,12 @@ public class GameBoyAdvance : IByteAddressableImage
return ErrorNumber.ReadOnly;
}
bool foundRom = false;
bool foundSaveRam = false;
var foundRom = false;
var foundSaveRam = false;
// Sanitize
foreach(LinearMemoryDevice map in mappings.Devices)
{
switch(map.Type)
{
case LinearMemoryType.ROM when !foundRom:
@@ -357,8 +367,10 @@ public class GameBoyAdvance : IByteAddressableImage
foundSaveRam = true;
break;
default: return ErrorNumber.InvalidArgument;
default:
return ErrorNumber.InvalidArgument;
}
}
// Cannot save in this image format anyway
return foundRom ? ErrorNumber.NoError : ErrorNumber.InvalidArgument;
@@ -401,7 +413,7 @@ public class GameBoyAdvance : IByteAddressableImage
/// <inheritdoc />
public ErrorNumber WriteBytes(byte[] buffer, int offset, int bytesToWrite, out int bytesWritten,
bool advance = true) =>
bool advance = true) =>
WriteBytesAt(Position, buffer, offset, bytesToWrite, out bytesWritten, advance);
/// <inheritdoc />
@@ -454,8 +466,13 @@ public class GameBoyAdvance : IByteAddressableImage
return ErrorNumber.NoError;
}
[StructLayout(LayoutKind.Sequential, Pack = 1), SuppressMessage("ReSharper", "MemberCanBePrivate.Local"),
SuppressMessage("ReSharper", "FieldCanBeMadeReadOnly.Local")]
#endregion
#region Nested type: Header
[StructLayout(LayoutKind.Sequential, Pack = 1)]
[SuppressMessage("ReSharper", "MemberCanBePrivate.Local")]
[SuppressMessage("ReSharper", "FieldCanBeMadeReadOnly.Local")]
struct Header
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
@@ -478,4 +495,6 @@ public class GameBoyAdvance : IByteAddressableImage
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public byte[] Reserved2;
}
#endregion
}

View File

@@ -22,18 +22,27 @@ public class MasterSystem : IByteAddressableImage
ImageInfo _imageInfo;
bool _opened;
int _romSize;
#region IByteAddressableImage Members
/// <inheritdoc />
public string Author => Authors.NataliaPortillo;
/// <inheritdoc />
public Metadata AaruMetadata => null;
/// <inheritdoc />
public List<DumpHardware> DumpHardware => null;
/// <inheritdoc />
public string Format => _gameGear ? "Sega Game Gear cartridge dump" : "Sega Master System cartridge dump";
/// <inheritdoc />
public Guid Id => new("B0C02927-890D-41D0-8E95-C5D9A2A74131");
/// <inheritdoc />
public ImageInfo Info => _imageInfo;
/// <inheritdoc />
public string Name => Localization.MasterSystem_Name;
@@ -50,9 +59,9 @@ public class MasterSystem : IByteAddressableImage
return false;
stream.Position = 0x7ff0;
byte[] magicBytes = new byte[8];
var magicBytes = new byte[8];
stream.EnsureRead(magicBytes, 0, 8);
ulong magic = BitConverter.ToUInt64(magicBytes, 0);
var magic = BitConverter.ToUInt64(magicBytes, 0);
if(magic == 0x4147455320524D54)
return true;
@@ -85,12 +94,12 @@ public class MasterSystem : IByteAddressableImage
if(stream.Length % 8192 != 0)
return ErrorNumber.InvalidArgument;
int headerPosition = 0;
var headerPosition = 0;
stream.Position = 0x7ff0;
byte[] magicBytes = new byte[8];
var magicBytes = new byte[8];
stream.EnsureRead(magicBytes, 0, 8);
ulong magic = BitConverter.ToUInt64(magicBytes, 0);
var magic = BitConverter.ToUInt64(magicBytes, 0);
if(magic != 0x0B000DCC6666EDCE)
headerPosition = 0x7ff0;
@@ -135,9 +144,9 @@ public class MasterSystem : IByteAddressableImage
var sb = new StringBuilder();
int productCode = (header.ProductCode[0] & 0xF) + ((header.ProductCode[0] & 0xF0) * 10) +
((header.ProductCode[1] & 0xF) * 100) + ((header.ProductCode[1] & 0xF0) * 1000) +
(((header.VersionAndProduct & 0xF0) >> 4) * 10000);
int productCode = (header.ProductCode[0] & 0xF) + (header.ProductCode[0] & 0xF0) * 10 +
(header.ProductCode[1] & 0xF) * 100 + (header.ProductCode[1] & 0xF0) * 1000 +
((header.VersionAndProduct & 0xF0) >> 4) * 10000;
sb.AppendFormat(Localization.Product_code_0, productCode).AppendLine();
@@ -187,24 +196,24 @@ public class MasterSystem : IByteAddressableImage
int sizeCode = header.SizeAndRegion & 0xF;
_romSize = sizeCode switch
{
0 => 262144,
1 => 524288,
2 => 1048576,
0xA => 8192,
0xB => 16384,
0xC => 32768,
0xD => 49152,
0xE => 65536,
0xF => 131072,
_ => 0
};
{
0 => 262144,
1 => 524288,
2 => 1048576,
0xA => 8192,
0xB => 16384,
0xC => 32768,
0xD => 49152,
0xE => 65536,
0xF => 131072,
_ => 0
};
sb.AppendFormat(Localization.Region_0, region).AppendLine();
sb.AppendFormat(Localization.Region_0, region).AppendLine();
sb.AppendFormat(Localization.Cartridge_type_0, cartType).AppendLine();
sb.AppendFormat(Localization.ROM_size_0_bytes, _romSize).AppendLine();
sb.AppendFormat(Localization.Revision_0, header.VersionAndProduct & 0xF).AppendLine();
sb.AppendFormat(Localization.Checksum_0_X4, header.Checksum).AppendLine();
sb.AppendFormat(Localization.Revision_0, header.VersionAndProduct & 0xF).AppendLine();
sb.AppendFormat(Localization.Checksum_0_X4, header.Checksum).AppendLine();
_imageInfo.Comments = sb.ToString();
_opened = true;
@@ -214,29 +223,32 @@ public class MasterSystem : IByteAddressableImage
/// <inheritdoc />
public string ErrorMessage { get; private set; }
/// <inheritdoc />
public bool IsWriting { get; private set; }
/// <inheritdoc />
public IEnumerable<string> KnownExtensions => new[]
{
".sms", ".gg"
};
public IEnumerable<string> KnownExtensions => new[] { ".sms", ".gg" };
/// <inheritdoc />
public IEnumerable<MediaTagType> SupportedMediaTags => Array.Empty<MediaTagType>();
/// <inheritdoc />
public IEnumerable<MediaType> SupportedMediaTypes => new[]
{
MediaType.MasterSystemCartridge, MediaType.GameGearCartridge
};
/// <inheritdoc />
public IEnumerable<(string name, Type type, string description, object @default)> SupportedOptions =>
Array.Empty<(string name, Type type, string description, object @default)>();
/// <inheritdoc />
public IEnumerable<SectorTagType> SupportedSectorTags => Array.Empty<SectorTagType>();
/// <inheritdoc />
public bool Create(string path, MediaType mediaType, Dictionary<string, string> options, ulong sectors,
uint sectorSize) => Create(path, mediaType, options, (long)sectors) == ErrorNumber.NoError;
uint sectorSize) => Create(path, mediaType, options, (long)sectors) == ErrorNumber.NoError;
/// <inheritdoc />
public bool Close()
@@ -444,18 +456,21 @@ public class MasterSystem : IByteAddressableImage
return ErrorNumber.ReadOnly;
}
bool foundRom = false;
var foundRom = false;
// Sanitize
foreach(LinearMemoryDevice map in mappings.Devices)
{
switch(map.Type)
{
case LinearMemoryType.ROM when !foundRom:
foundRom = true;
break;
default: return ErrorNumber.InvalidArgument;
default:
return ErrorNumber.InvalidArgument;
}
}
// Cannot save in this image format anyway
return foundRom ? ErrorNumber.NoError : ErrorNumber.InvalidArgument;
@@ -498,7 +513,7 @@ public class MasterSystem : IByteAddressableImage
/// <inheritdoc />
public ErrorNumber WriteBytes(byte[] buffer, int offset, int bytesToWrite, out int bytesWritten,
bool advance = true) =>
bool advance = true) =>
WriteBytesAt(Position, buffer, offset, bytesToWrite, out bytesWritten, advance);
/// <inheritdoc />
@@ -551,8 +566,13 @@ public class MasterSystem : IByteAddressableImage
return ErrorNumber.NoError;
}
[StructLayout(LayoutKind.Sequential, Pack = 1), SuppressMessage("ReSharper", "FieldCanBeMadeReadOnly.Local"),
SuppressMessage("ReSharper", "MemberCanBePrivate.Local")]
#endregion
#region Nested type: Header
[StructLayout(LayoutKind.Sequential, Pack = 1)]
[SuppressMessage("ReSharper", "FieldCanBeMadeReadOnly.Local")]
[SuppressMessage("ReSharper", "MemberCanBePrivate.Local")]
struct Header
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
@@ -564,4 +584,6 @@ public class MasterSystem : IByteAddressableImage
public byte VersionAndProduct;
public byte SizeAndRegion;
}
#endregion
}

View File

@@ -35,18 +35,27 @@ public class Nes : IByteAddressableImage
int _promLen;
byte _submapper;
bool _trainer;
#region IByteAddressableImage Members
/// <inheritdoc />
public string Author => Authors.NataliaPortillo;
/// <inheritdoc />
public Metadata AaruMetadata => null;
/// <inheritdoc />
public List<DumpHardware> DumpHardware => null;
/// <inheritdoc />
public string Format => _nes20 ? "NES 2.0" : "iNES";
/// <inheritdoc />
public Guid Id => new("D597A3F4-2B1C-441C-8487-0BCABC509302");
/// <inheritdoc />
public ImageInfo Info => _imageInfo;
/// <inheritdoc />
public string Name => Localization.Nes_Name;
@@ -63,9 +72,9 @@ public class Nes : IByteAddressableImage
return false;
stream.Position = 0;
byte[] magicBytes = new byte[4];
var magicBytes = new byte[4];
stream.EnsureRead(magicBytes, 0, 8);
uint magic = BitConverter.ToUInt32(magicBytes, 0);
var magic = BitConverter.ToUInt32(magicBytes, 0);
return magic == 0x1A53454E;
}
@@ -83,9 +92,9 @@ public class Nes : IByteAddressableImage
return ErrorNumber.InvalidArgument;
stream.Position = 0;
byte[] header = new byte[16];
var header = new byte[16];
stream.EnsureRead(header, 0, 8);
uint magic = BitConverter.ToUInt32(header, 0);
var magic = BitConverter.ToUInt32(header, 0);
if(magic != 0x1A53454E)
return ErrorNumber.InvalidArgument;
@@ -105,7 +114,7 @@ public class Nes : IByteAddressableImage
NametableMirroring = (header[6] & 0x1) != 0,
BatteryPresent = (header[6] & 0x2) != 0,
FourScreenMode = (header[6] & 0x8) != 0,
Mapper = (ushort)((header[6] >> 4) | (header[7] & 0xF0))
Mapper = (ushort)(header[6] >> 4 | header[7] & 0xF0)
};
if((header[7] & 0x1) != 0)
@@ -181,7 +190,7 @@ public class Nes : IByteAddressableImage
sb.AppendFormat(Localization.PRG_ROM_size_0_bytes, _prgLen).AppendLine();
sb.AppendFormat(Localization.CHR_ROM_size_0_bytes, _chrLen).AppendLine();
sb.AppendFormat(Localization.Trainer_size_0_bytes, trainerLen).AppendLine();
sb.AppendFormat(Localization.Mapper_0, _nesHeaderInfo.Mapper).AppendLine();
sb.AppendFormat(Localization.Mapper_0, _nesHeaderInfo.Mapper).AppendLine();
if(_nesHeaderInfo.BatteryPresent)
sb.AppendLine(Localization.Has_battery_backed_RAM);
@@ -203,11 +212,12 @@ public class Nes : IByteAddressableImage
case NesConsoleType.Playchoice:
sb.AppendLine(Localization.PlayChoice_10_game);
sb.AppendFormat(Localization.INST_ROM_size_0_bytes, _instRomLen & 0xF).AppendLine();
sb.AppendFormat(Localization.PROM_size_0_bytes, _promLen).AppendLine();
sb.AppendFormat(Localization.PROM_size_0_bytes, _promLen).AppendLine();
break;
case NesConsoleType.Nes: break;
case NesConsoleType.Nes:
break;
case NesConsoleType.Extended:
switch(_nesHeaderInfo.ExtendedConsoleType)
{
@@ -216,11 +226,12 @@ public class Nes : IByteAddressableImage
break;
case NesExtendedConsoleType.Normal: break;
case NesExtendedConsoleType.Normal:
break;
case NesExtendedConsoleType.Playchoice:
sb.AppendLine(Localization.PlayChoice_10_game);
sb.AppendFormat(Localization.INST_ROM_size_0_bytes, _instRomLen & 0xF).AppendLine();
sb.AppendFormat(Localization.PROM_size_0_bytes, _promLen).AppendLine();
sb.AppendFormat(Localization.PROM_size_0_bytes, _promLen).AppendLine();
break;
case NesExtendedConsoleType.VT01_Monochrome:
@@ -262,29 +273,29 @@ public class Nes : IByteAddressableImage
/// <inheritdoc />
public string ErrorMessage { get; private set; }
/// <inheritdoc />
public bool IsWriting { get; private set; }
/// <inheritdoc />
public IEnumerable<string> KnownExtensions => new[]
{
".nes"
};
public IEnumerable<string> KnownExtensions => new[] { ".nes" };
/// <inheritdoc />
public IEnumerable<MediaTagType> SupportedMediaTags => Array.Empty<MediaTagType>();
/// <inheritdoc />
public IEnumerable<MediaType> SupportedMediaTypes => new[]
{
MediaType.NESGamePak, MediaType.FamicomGamePak
};
public IEnumerable<MediaType> SupportedMediaTypes => new[] { MediaType.NESGamePak, MediaType.FamicomGamePak };
/// <inheritdoc />
public IEnumerable<(string name, Type type, string description, object @default)> SupportedOptions =>
Array.Empty<(string name, Type type, string description, object @default)>();
/// <inheritdoc />
public IEnumerable<SectorTagType> SupportedSectorTags => Array.Empty<SectorTagType>();
/// <inheritdoc />
public bool Create(string path, MediaType mediaType, Dictionary<string, string> options, ulong sectors,
uint sectorSize) => Create(path, mediaType, options, (long)sectors) == ErrorNumber.NoError;
uint sectorSize) => Create(path, mediaType, options, (long)sectors) == ErrorNumber.NoError;
/// <inheritdoc />
public bool Close()
@@ -303,7 +314,7 @@ public class Nes : IByteAddressableImage
return false;
}
byte[] header = new byte[16];
var header = new byte[16];
if(_nesHeaderInfo is null)
{
@@ -323,8 +334,8 @@ public class Nes : IByteAddressableImage
header[1] = 0x45;
header[2] = 0x53;
header[3] = 0x1A;
header[4] = (byte)((_prgLen / 16384) & 0xFF);
header[5] = (byte)((_chrLen / 8192) & 0xFF);
header[4] = (byte)(_prgLen / 16384 & 0xFF);
header[5] = (byte)(_chrLen / 8192 & 0xFF);
header[6] = (byte)((_nesHeaderInfo.Mapper & 0xF) << 4);
if(_nesHeaderInfo.FourScreenMode)
@@ -339,23 +350,24 @@ public class Nes : IByteAddressableImage
if(_nesHeaderInfo.NametableMirroring)
header[6] |= 0x1;
header[7] = (byte)((_mapper & 0xF0) | 0x8);
header[7] = (byte)(_mapper & 0xF0 | 0x8);
header[7] |= (byte)_nesHeaderInfo.ConsoleType;
header[8] = (byte)((_nesHeaderInfo.Submapper << 4) | ((_nesHeaderInfo.Mapper & 0xF00) >> 4));
header[9] = (byte)((_prgLen / 16384) >> 8);
header[9] |= (byte)(((_chrLen / 8192) >> 4) & 0xF);
header[8] = (byte)(_nesHeaderInfo.Submapper << 4 | (_nesHeaderInfo.Mapper & 0xF00) >> 4);
header[9] = (byte)(_prgLen / 16384 >> 8);
header[9] |= (byte)(_chrLen / 8192 >> 4 & 0xF);
// TODO: PRG-RAM, PRG-NVRAM, CHR-RAM and CHR-NVRAM sizes
header[12] = (byte)_nesHeaderInfo.TimingMode;
header[13] = _nesHeaderInfo.ConsoleType switch
{
NesConsoleType.Vs => (byte)(((int)_nesHeaderInfo.VsHardwareType << 4) | (int)_nesHeaderInfo.VsPpuType),
NesConsoleType.Extended => (byte)_nesHeaderInfo.ExtendedConsoleType,
_ => header[13]
};
{
NesConsoleType.Vs => (byte)((int)_nesHeaderInfo.VsHardwareType << 4 |
(int)_nesHeaderInfo.VsPpuType),
NesConsoleType.Extended => (byte)_nesHeaderInfo.ExtendedConsoleType,
_ => header[13]
};
header[14] = 0;
@@ -470,6 +482,7 @@ public class Nes : IByteAddressableImage
};
if(_chrLen > 0)
{
devices.Add(new LinearMemoryDevice
{
Type = LinearMemoryType.CharacterROM,
@@ -478,14 +491,18 @@ public class Nes : IByteAddressableImage
Length = (ulong)_chrLen
}
});
}
if(_trainer)
{
devices.Add(new LinearMemoryDevice
{
Type = LinearMemoryType.Trainer
});
}
if(_instRomLen > 0)
{
devices.Add(new LinearMemoryDevice
{
Type = LinearMemoryType.ROM,
@@ -494,8 +511,10 @@ public class Nes : IByteAddressableImage
Length = (ulong)_instRomLen
}
});
}
if(_promLen > 0)
{
devices.Add(new LinearMemoryDevice
{
Type = LinearMemoryType.ROM,
@@ -504,8 +523,10 @@ public class Nes : IByteAddressableImage
Length = (ulong)_promLen
}
});
}
if(_prgRamLen > 0)
{
devices.Add(new LinearMemoryDevice
{
Type = LinearMemoryType.WorkRAM,
@@ -514,8 +535,10 @@ public class Nes : IByteAddressableImage
Length = (ulong)_prgRamLen
}
});
}
if(_chrRamLen > 0)
{
devices.Add(new LinearMemoryDevice
{
Type = LinearMemoryType.CharacterRAM,
@@ -524,8 +547,10 @@ public class Nes : IByteAddressableImage
Length = (ulong)_chrRamLen
}
});
}
if(_prgNvramLen > 0)
{
devices.Add(new LinearMemoryDevice
{
Type = LinearMemoryType.SaveRAM,
@@ -534,8 +559,10 @@ public class Nes : IByteAddressableImage
Length = (ulong)_prgNvramLen
}
});
}
if(_chrNvramLen > 0)
{
devices.Add(new LinearMemoryDevice
{
Type = LinearMemoryType.CharacterRAM,
@@ -544,6 +571,7 @@ public class Nes : IByteAddressableImage
Length = (ulong)_chrNvramLen
}
});
}
ushort mapper = _nesHeaderInfo?.Mapper ?? _mapper;
byte submapper = _nesHeaderInfo?.Submapper ?? _submapper;
@@ -555,11 +583,13 @@ public class Nes : IByteAddressableImage
});
if(submapper != 0)
{
devices.Add(new LinearMemoryDevice
{
Type = LinearMemoryType.Mapper,
Description = $"NES Submapper {submapper}"
});
}
mappings = new LinearMemoryMap
{
@@ -663,22 +693,23 @@ public class Nes : IByteAddressableImage
return ErrorNumber.ReadOnly;
}
bool foundRom = false;
bool foundChrRom = false;
bool foundInstRom = false;
bool foundProm = false;
bool foundRam = false;
bool foundChrRam = false;
bool foundNvram = false;
bool foundChrNvram = false;
bool foundMapper = false;
bool foundSubMapper = false;
var foundRom = false;
var foundChrRom = false;
var foundInstRom = false;
var foundProm = false;
var foundRam = false;
var foundChrRam = false;
var foundNvram = false;
var foundChrNvram = false;
var foundMapper = false;
var foundSubMapper = false;
Regex regex;
Match match;
// Sanitize
foreach(LinearMemoryDevice map in mappings.Devices)
{
switch(map.Type)
{
case LinearMemoryType.ROM when !foundRom:
@@ -730,6 +761,7 @@ public class Nes : IByteAddressableImage
match = regex.Match(map.Description);
if(match.Success)
{
if(ushort.TryParse(match.Groups["mapper"].Value, out ushort mapper))
{
if(_nesHeaderInfo is null)
@@ -739,6 +771,7 @@ public class Nes : IByteAddressableImage
foundMapper = true;
}
}
break;
case LinearMemoryType.Mapper when !foundSubMapper:
@@ -746,6 +779,7 @@ public class Nes : IByteAddressableImage
match = regex.Match(map.Description);
if(match.Success)
{
if(byte.TryParse(match.Groups["mapper"].Value, out byte mapper))
{
if(_nesHeaderInfo is null)
@@ -755,10 +789,13 @@ public class Nes : IByteAddressableImage
foundSubMapper = true;
}
}
break;
default: return ErrorNumber.InvalidArgument;
default:
return ErrorNumber.InvalidArgument;
}
}
return foundRom && foundMapper ? ErrorNumber.NoError : ErrorNumber.InvalidArgument;
}
@@ -800,7 +837,7 @@ public class Nes : IByteAddressableImage
/// <inheritdoc />
public ErrorNumber WriteBytes(byte[] buffer, int offset, int bytesToWrite, out int bytesWritten,
bool advance = true) =>
bool advance = true) =>
WriteBytesAt(Position, buffer, offset, bytesToWrite, out bytesWritten, advance);
/// <inheritdoc />
@@ -852,4 +889,6 @@ public class Nes : IByteAddressableImage
return ErrorNumber.NoError;
}
#endregion
}

View File

@@ -56,22 +56,31 @@ public class Nintendo64 : IByteAddressableImage
bool _interleaved;
bool _littleEndian;
bool _opened;
#region IByteAddressableImage Members
/// <inheritdoc />
public string Author => Authors.NataliaPortillo;
/// <inheritdoc />
public Metadata AaruMetadata => null;
/// <inheritdoc />
public List<DumpHardware> DumpHardware => null;
/// <inheritdoc />
public string Format => !_opened
? "Nintendo 64 cartridge dump"
: _interleaved
? "Doctor V64"
: "Mr. Backup Z64";
/// <inheritdoc />
public Guid Id => new("EF1B4319-48A0-4EEC-B8E8-D0EA36F8CC92");
/// <inheritdoc />
public ImageInfo Info => _imageInfo;
/// <inheritdoc />
public string Name => Localization.Nintendo64_Name;
@@ -88,9 +97,9 @@ public class Nintendo64 : IByteAddressableImage
return false;
stream.Position = 0;
byte[] magicBytes = new byte[4];
var magicBytes = new byte[4];
stream.EnsureRead(magicBytes, 0, 4);
uint magic = BitConverter.ToUInt32(magicBytes, 0);
var magic = BitConverter.ToUInt32(magicBytes, 0);
switch(magic)
{
@@ -101,8 +110,10 @@ public class Nintendo64 : IByteAddressableImage
case 0x12408037:
case 0x12418037:
case 0x37804012:
case 0x37804112: return true;
default: return false;
case 0x37804112:
return true;
default:
return false;
}
}
@@ -119,9 +130,9 @@ public class Nintendo64 : IByteAddressableImage
return ErrorNumber.InvalidArgument;
stream.Position = 0;
byte[] magicBytes = new byte[4];
var magicBytes = new byte[4];
stream.EnsureRead(magicBytes, 0, 4);
uint magic = BitConverter.ToUInt32(magicBytes, 0);
var magic = BitConverter.ToUInt32(magicBytes, 0);
switch(magic)
{
@@ -149,7 +160,8 @@ public class Nintendo64 : IByteAddressableImage
_littleEndian = false;
break;
default: return ErrorNumber.InvalidArgument;
default:
return ErrorNumber.InvalidArgument;
}
_data = new byte[imageFilter.DataForkLength];
@@ -169,9 +181,9 @@ public class Nintendo64 : IByteAddressableImage
if(_littleEndian)
{
byte[] tmp = new byte[_data.Length];
var tmp = new byte[_data.Length];
for(int i = 0; i < _data.Length; i += 4)
for(var i = 0; i < _data.Length; i += 4)
{
tmp[i] = _data[i + 3];
tmp[i + 1] = _data[i + 2];
@@ -184,9 +196,9 @@ public class Nintendo64 : IByteAddressableImage
if(_interleaved)
{
byte[] tmp = new byte[_data.Length];
var tmp = new byte[_data.Length];
for(int i = 0; i < _data.Length; i += 2)
for(var i = 0; i < _data.Length; i += 2)
{
tmp[i] = _data[i + 1];
tmp[i + 1] = _data[i];
@@ -208,17 +220,17 @@ public class Nintendo64 : IByteAddressableImage
}
_imageInfo.MediaPartNumber = StringHandlers.SpacePaddedToString(header.CartridgeId, encoding);
_imageInfo.MediaTitle = StringHandlers.SpacePaddedToString(header.Name, encoding);
_imageInfo.MediaTitle = StringHandlers.SpacePaddedToString(header.Name, encoding);
var sb = new StringBuilder();
sb.AppendFormat(Localization.Name_0, _imageInfo.MediaTitle).AppendLine();
sb.AppendFormat(Localization.Region_0, DecodeCountryCode(header.CountryCode)).AppendLine();
sb.AppendFormat(Localization.Cartridge_ID_0, _imageInfo.MediaPartNumber).AppendLine();
sb.AppendFormat(Localization.Name_0, _imageInfo.MediaTitle).AppendLine();
sb.AppendFormat(Localization.Region_0, DecodeCountryCode(header.CountryCode)).AppendLine();
sb.AppendFormat(Localization.Cartridge_ID_0, _imageInfo.MediaPartNumber).AppendLine();
sb.AppendFormat(Localization.Cartridge_type_0, (char)header.CartridgeType).AppendLine();
sb.AppendFormat(Localization.Version_0_1, (header.Version / 10) + 1, header.Version % 10).AppendLine();
sb.AppendFormat(Localization.CRC1_0, header.Crc1).AppendLine();
sb.AppendFormat(Localization.CRC2_0, header.Crc2).AppendLine();
sb.AppendFormat(Localization.Version_0_1, header.Version / 10 + 1, header.Version % 10).AppendLine();
sb.AppendFormat(Localization.CRC1_0, header.Crc1).AppendLine();
sb.AppendFormat(Localization.CRC2_0, header.Crc2).AppendLine();
_imageInfo.Comments = sb.ToString();
_opened = true;
@@ -669,11 +681,12 @@ public class Nintendo64 : IByteAddressableImage
return ErrorNumber.ReadOnly;
}
bool foundRom = false;
bool foundSaveRam = false;
var foundRom = false;
var foundSaveRam = false;
// Sanitize
foreach(LinearMemoryDevice map in mappings.Devices)
{
switch(map.Type)
{
case LinearMemoryType.ROM when !foundRom:
@@ -686,8 +699,10 @@ public class Nintendo64 : IByteAddressableImage
foundSaveRam = true;
break;
default: return ErrorNumber.InvalidArgument;
default:
return ErrorNumber.InvalidArgument;
}
}
// Cannot save in this image format anyway
return foundRom ? ErrorNumber.NoError : ErrorNumber.InvalidArgument;
@@ -730,7 +745,7 @@ public class Nintendo64 : IByteAddressableImage
/// <inheritdoc />
public ErrorNumber WriteBytes(byte[] buffer, int offset, int bytesToWrite, out int bytesWritten,
bool advance = true) =>
bool advance = true) =>
WriteBytesAt(Position, buffer, offset, bytesToWrite, out bytesWritten, advance);
/// <inheritdoc />
@@ -785,29 +800,29 @@ public class Nintendo64 : IByteAddressableImage
/// <inheritdoc />
public string ErrorMessage { get; private set; }
/// <inheritdoc />
public bool IsWriting { get; private set; }
/// <inheritdoc />
public IEnumerable<string> KnownExtensions => new[]
{
".n64", ".v64", ".z64"
};
public IEnumerable<string> KnownExtensions => new[] { ".n64", ".v64", ".z64" };
/// <inheritdoc />
public IEnumerable<MediaTagType> SupportedMediaTags => Array.Empty<MediaTagType>();
/// <inheritdoc />
public IEnumerable<MediaType> SupportedMediaTypes => new[]
{
MediaType.N64GamePak
};
public IEnumerable<MediaType> SupportedMediaTypes => new[] { MediaType.N64GamePak };
/// <inheritdoc />
public IEnumerable<(string name, Type type, string description, object @default)> SupportedOptions =>
Array.Empty<(string name, Type type, string description, object @default)>();
/// <inheritdoc />
public IEnumerable<SectorTagType> SupportedSectorTags => Array.Empty<SectorTagType>();
/// <inheritdoc />
public bool Create(string path, MediaType mediaType, Dictionary<string, string> options, ulong sectors,
uint sectorSize) => Create(path, mediaType, options, (long)sectors) == ErrorNumber.NoError;
uint sectorSize) => Create(path, mediaType, options, (long)sectors) == ErrorNumber.NoError;
/// <inheritdoc />
public bool Close()
@@ -828,9 +843,9 @@ public class Nintendo64 : IByteAddressableImage
if(_interleaved)
{
byte[] tmp = new byte[_data.Length];
var tmp = new byte[_data.Length];
for(int i = 0; i < _data.Length; i += 2)
for(var i = 0; i < _data.Length; i += 2)
{
tmp[i] = _data[i + 1];
tmp[i + 1] = _data[i];
@@ -858,32 +873,37 @@ public class Nintendo64 : IByteAddressableImage
/// <inheritdoc />
public bool SetImageInfo(ImageInfo imageInfo) => true;
static string DecodeCountryCode(byte countryCode) => countryCode switch
{
0x37 => Localization.Beta,
0x41 => Localization.Asia_NTSC,
0x42 => Localization.Brazil,
0x43 => Localization.China,
0x44 => Localization.Germany,
0x45 => Localization.North_America,
0x46 => Localization.France,
0x47 => Localization.Gateway_64_NTSC,
0x48 => Localization.Netherlands,
0x49 => Localization.Italy,
0x4A => Localization.Japan,
0x4B => Localization.Korea,
0x4C => Localization.Gateway_64_PAL,
0x4E => Localization.Canada,
0x50 => Localization.Europe,
0x53 => Localization.Spain,
0x55 => Localization.Australia,
0x57 => Localization.Scandinavia,
0x58 => Localization.Europe,
0x59 => Localization.Europe,
_ => Localization.Unknown_country
};
#endregion
[StructLayout(LayoutKind.Sequential, Pack = 1), SuppressMessage("ReSharper", "MemberCanBePrivate.Local")]
static string DecodeCountryCode(byte countryCode) => countryCode switch
{
0x37 => Localization.Beta,
0x41 => Localization.Asia_NTSC,
0x42 => Localization.Brazil,
0x43 => Localization.China,
0x44 => Localization.Germany,
0x45 => Localization.North_America,
0x46 => Localization.France,
0x47 => Localization.Gateway_64_NTSC,
0x48 => Localization.Netherlands,
0x49 => Localization.Italy,
0x4A => Localization.Japan,
0x4B => Localization.Korea,
0x4C => Localization.Gateway_64_PAL,
0x4E => Localization.Canada,
0x50 => Localization.Europe,
0x53 => Localization.Spain,
0x55 => Localization.Australia,
0x57 => Localization.Scandinavia,
0x58 => Localization.Europe,
0x59 => Localization.Europe,
_ => Localization.Unknown_country
};
#region Nested type: Header
[StructLayout(LayoutKind.Sequential, Pack = 1)]
[SuppressMessage("ReSharper", "MemberCanBePrivate.Local")]
struct Header
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
@@ -908,4 +928,6 @@ public class Nintendo64 : IByteAddressableImage
public readonly byte CountryCode;
public readonly byte Version;
}
#endregion
}

View File

@@ -57,12 +57,17 @@ public class SegaMegaDrive : IByteAddressableImage
bool _opened;
bool _smd;
#region IByteAddressableImage Members
/// <inheritdoc />
public string Author => Authors.NataliaPortillo;
/// <inheritdoc />
public Metadata AaruMetadata => null;
/// <inheritdoc />
public List<DumpHardware> DumpHardware => null;
/// <inheritdoc />
public string Format => !_opened
? "Mega Drive cartridge dump"
@@ -71,10 +76,13 @@ public class SegaMegaDrive : IByteAddressableImage
: _interleaved
? "Multi Game Doctor 2"
: "Magicom";
/// <inheritdoc />
public Guid Id => new("7B1CE2E7-3BC4-4283-BFA4-F292D646DF15");
/// <inheritdoc />
public ImageInfo Info => _imageInfo;
/// <inheritdoc />
public string Name => Localization.SegaMegaDrive_Name;
@@ -90,7 +98,7 @@ public class SegaMegaDrive : IByteAddressableImage
if(stream.Length % 512 != 0)
return false;
byte[] buffer = new byte[4];
var buffer = new byte[4];
stream.Position = 256;
stream.EnsureRead(buffer, 0, 4);
@@ -106,7 +114,7 @@ public class SegaMegaDrive : IByteAddressableImage
if(buffer[0] == 0x45 &&
buffer[1] == 0x41)
{
stream.Position = (stream.Length / 2) + 256;
stream.Position = stream.Length / 2 + 256;
stream.EnsureRead(buffer, 0, 2);
// SG
@@ -142,7 +150,7 @@ public class SegaMegaDrive : IByteAddressableImage
if(stream.Length % 512 != 0)
return ErrorNumber.InvalidArgument;
byte[] buffer = new byte[4];
var buffer = new byte[4];
stream.Position = 256;
stream.EnsureRead(buffer, 0, 4);
@@ -154,7 +162,7 @@ public class SegaMegaDrive : IByteAddressableImage
if(buffer[0] == 0x45 &&
buffer[1] == 0x41)
{
stream.Position = (stream.Length / 2) + 256;
stream.Position = stream.Length / 2 + 256;
stream.EnsureRead(buffer, 0, 2);
// SG
@@ -195,18 +203,18 @@ public class SegaMegaDrive : IByteAddressableImage
// Interleaves every 16KiB
if(_smd)
{
byte[] tmp = new byte[_data.Length];
byte[] bankIn = new byte[16384];
byte[] bankOut = new byte[16384];
var tmp = new byte[_data.Length];
var bankIn = new byte[16384];
var bankOut = new byte[16384];
for(int b = 0; b < _data.Length / 16384; b++)
for(var b = 0; b < _data.Length / 16384; b++)
{
Array.Copy(_data, b * 16384, bankIn, 0, 16384);
for(int i = 0; i < 8192; i++)
for(var i = 0; i < 8192; i++)
{
bankOut[(i * 2) + 1] = bankIn[i];
bankOut[i * 2] = bankIn[i + 8192];
bankOut[i * 2 + 1] = bankIn[i];
bankOut[i * 2] = bankIn[i + 8192];
}
Array.Copy(bankOut, 0, tmp, b * 16384, 16384);
@@ -216,13 +224,13 @@ public class SegaMegaDrive : IByteAddressableImage
}
else if(_interleaved)
{
byte[] tmp = new byte[_data.Length];
int half = _data.Length / 2;
var tmp = new byte[_data.Length];
int half = _data.Length / 2;
for(int i = 0; i < half; i++)
for(var i = 0; i < half; i++)
{
tmp[i * 2] = _data[i];
tmp[(i * 2) + 1] = _data[i + half];
tmp[i * 2] = _data[i];
tmp[i * 2 + 1] = _data[i + half];
}
_data = tmp;
@@ -310,7 +318,8 @@ public class SegaMegaDrive : IByteAddressableImage
sb.AppendFormat(Localization.Extra_RAM_starts_at_0_and_ends_at_1_2_bytes, header.ExtraRamStart,
header.ExtraRamEnd,
(header.ExtraRamType & 0x10) == 0x10 ? (header.ExtraRamEnd - header.ExtraRamStart + 2) / 2
(header.ExtraRamType & 0x10) == 0x10
? (header.ExtraRamEnd - header.ExtraRamStart + 2) / 2
: header.ExtraRamEnd - header.ExtraRamStart + 1).AppendLine();
}
else
@@ -327,15 +336,15 @@ public class SegaMegaDrive : IByteAddressableImage
_imageInfo.ImageSize = (ulong)stream.Length;
_imageInfo.LastModificationTime = imageFilter.LastWriteTime;
_imageInfo.CreationTime = imageFilter.CreationTime;
_imageInfo.MediaPartNumber = StringHandlers.SpacePaddedToString(header.SerialNumber, encoding);
_imageInfo.MediaPartNumber = StringHandlers.SpacePaddedToString(header.SerialNumber, encoding);
_imageInfo.MediaTitle = StringHandlers.SpacePaddedToString(header.DomesticTitle, encoding);
_imageInfo.MediaType = StringHandlers.SpacePaddedToString(header.SystemType, encoding) switch
{
"SEGA 32X" => MediaType._32XCartridge,
"SEGA PICO" => MediaType.SegaPicoCartridge,
_ => MediaType.MegaDriveCartridge
};
{
"SEGA 32X" => MediaType._32XCartridge,
"SEGA PICO" => MediaType.SegaPicoCartridge,
_ => MediaType.MegaDriveCartridge
};
_imageInfo.Sectors = (ulong)_data.Length;
_imageInfo.MetadataMediaType = MetadataMediaType.LinearMedia;
@@ -348,29 +357,32 @@ public class SegaMegaDrive : IByteAddressableImage
/// <inheritdoc />
public string ErrorMessage { get; private set; }
/// <inheritdoc />
public bool IsWriting { get; private set; }
/// <inheritdoc />
public IEnumerable<string> KnownExtensions => new[]
{
".smd", ".md", ".32x"
};
public IEnumerable<string> KnownExtensions => new[] { ".smd", ".md", ".32x" };
/// <inheritdoc />
public IEnumerable<MediaTagType> SupportedMediaTags => Array.Empty<MediaTagType>();
/// <inheritdoc />
public IEnumerable<MediaType> SupportedMediaTypes => new[]
{
MediaType._32XCartridge, MediaType.MegaDriveCartridge, MediaType.SegaPicoCartridge
};
/// <inheritdoc />
public IEnumerable<(string name, Type type, string description, object @default)> SupportedOptions =>
Array.Empty<(string name, Type type, string description, object @default)>();
/// <inheritdoc />
public IEnumerable<SectorTagType> SupportedSectorTags => Array.Empty<SectorTagType>();
/// <inheritdoc />
public bool Create(string path, MediaType mediaType, Dictionary<string, string> options, ulong sectors,
uint sectorSize) => Create(path, mediaType, options, (long)sectors) == ErrorNumber.NoError;
uint sectorSize) => Create(path, mediaType, options, (long)sectors) == ErrorNumber.NoError;
/// <inheritdoc />
public bool Close()
@@ -391,13 +403,13 @@ public class SegaMegaDrive : IByteAddressableImage
if(_interleaved)
{
byte[] tmp = new byte[_data.Length];
int half = _data.Length / 2;
var tmp = new byte[_data.Length];
int half = _data.Length / 2;
for(int i = 0; i < half; i++)
for(var i = 0; i < half; i++)
{
tmp[i] = _data[i * 2];
tmp[i + half] = _data[(i * 2) + 1];
tmp[i + half] = _data[i * 2 + 1];
}
_data = tmp;
@@ -419,18 +431,18 @@ public class SegaMegaDrive : IByteAddressableImage
_dataStream.Write(smdHeader, 0, smdHeader.Length);
byte[] tmp = new byte[_data.Length];
byte[] bankIn = new byte[16384];
byte[] bankOut = new byte[16384];
var tmp = new byte[_data.Length];
var bankIn = new byte[16384];
var bankOut = new byte[16384];
for(int b = 0; b < _data.Length / 16384; b++)
for(var b = 0; b < _data.Length / 16384; b++)
{
Array.Copy(_data, b * 16384, bankIn, 0, 16384);
for(int i = 0; i < 8192; i++)
for(var i = 0; i < 8192; i++)
{
bankOut[i] = bankIn[(i * 2) + 1];
bankOut[i + 8192] = bankIn[i * 2];
bankOut[i] = bankIn[i * 2 + 1];
bankOut[i + 8192] = bankIn[i * 2];
}
Array.Copy(bankOut, 0, tmp, b * 16384, 16384);
@@ -723,11 +735,12 @@ public class SegaMegaDrive : IByteAddressableImage
return ErrorNumber.ReadOnly;
}
bool foundRom = false;
bool foundSaveRam = false;
var foundRom = false;
var foundSaveRam = false;
// Sanitize
foreach(LinearMemoryDevice map in mappings.Devices)
{
switch(map.Type)
{
case LinearMemoryType.ROM when !foundRom:
@@ -738,8 +751,10 @@ public class SegaMegaDrive : IByteAddressableImage
foundSaveRam = true;
break;
default: return ErrorNumber.InvalidArgument;
default:
return ErrorNumber.InvalidArgument;
}
}
// Cannot save in this image format anyway
return foundRom ? ErrorNumber.NoError : ErrorNumber.InvalidArgument;
@@ -782,7 +797,7 @@ public class SegaMegaDrive : IByteAddressableImage
/// <inheritdoc />
public ErrorNumber WriteBytes(byte[] buffer, int offset, int bytesToWrite, out int bytesWritten,
bool advance = true) =>
bool advance = true) =>
WriteBytesAt(Position, buffer, offset, bytesToWrite, out bytesWritten, advance);
/// <inheritdoc />
@@ -835,8 +850,13 @@ public class SegaMegaDrive : IByteAddressableImage
return ErrorNumber.NoError;
}
[StructLayout(LayoutKind.Sequential, Pack = 1), SuppressMessage("ReSharper", "MemberCanBePrivate.Local"),
SuppressMessage("ReSharper", "FieldCanBeMadeReadOnly.Local")]
#endregion
#region Nested type: SegaHeader
[StructLayout(LayoutKind.Sequential, Pack = 1)]
[SuppressMessage("ReSharper", "MemberCanBePrivate.Local")]
[SuppressMessage("ReSharper", "FieldCanBeMadeReadOnly.Local")]
struct SegaHeader
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 15)]
@@ -873,8 +893,13 @@ public class SegaMegaDrive : IByteAddressableImage
public byte[] Padding3;
}
[StructLayout(LayoutKind.Sequential, Pack = 1), SuppressMessage("ReSharper", "MemberCanBePrivate.Local"),
SuppressMessage("ReSharper", "FieldCanBeMadeReadOnly.Local")]
#endregion
#region Nested type: SuperMagicDriveHeader
[StructLayout(LayoutKind.Sequential, Pack = 1)]
[SuppressMessage("ReSharper", "MemberCanBePrivate.Local")]
[SuppressMessage("ReSharper", "FieldCanBeMadeReadOnly.Local")]
struct SuperMagicDriveHeader
{
/// <summary>16 KiB pages</summary>
@@ -894,4 +919,6 @@ public class SegaMegaDrive : IByteAddressableImage
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 501)]
public byte[] Empty;
}
#endregion
}

Some files were not shown because too many files have changed in this diff Show More