Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Aaru.CommonTypes/Enums/Images.cs
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,10 @@ public enum MediaTagType
DVD_PFI_2ndLayer = 74,
/// <summary>Floppy write protection status</summary>
[Description("Write protection status")]
Floppy_WriteProtection = 75
Floppy_WriteProtection = 75,
/// <summary>DPM</summary>
[Description("DPM")]
DPM = 76
}

/// <summary>Enumeration of media types defined in metadata</summary>
Expand Down
13 changes: 13 additions & 0 deletions Aaru.CommonTypes/Interfaces/IOpticalMediaImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,19 @@ public interface IOpticalMediaImage : IMediaImage, IPartitionableMediaImage, IVe
/// <value>The sessions.</value>
List<Session> Sessions { get; }

/// <summary>Reads a disc's DPM data.</summary>
/// <returns>The disc's DPM data.</returns>
/// <param name="dpmStartSector">Starting sector lba.</param>
/// <param name="dpmResolution">DPM Resolution.</param>
/// <param name="numberOfDpmEntries">The number of DPM entries.</param>
/// <param name="dpm">The array of DPM data.</param>
ErrorNumber ReadDPM(out uint dpmStartSector, out uint dpmResolution, out uint numberOfDpmEntries, out ulong[] dpm);

/// <summary>Reads a sector's DPM data.</summary>
/// <returns>The sector's DPM data, null if it is not stored for that sector.</returns>
/// <param name="dpm">The sector's dpm.</param>
ErrorNumber ReadSectorDPM(ulong sectorAddress, out ulong? dpm);

/// <summary>Reads a sector's user data, relative to track.</summary>
/// <returns>The sector's user data.</returns>
/// <param name="sectorAddress">Sector address (relative LBA).</param>
Expand Down
17 changes: 17 additions & 0 deletions Aaru.CommonTypes/Interfaces/IWritableOpticalImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,28 @@ namespace Aaru.CommonTypes.Interfaces;
/// <summary>Defines an image that is writable and can store an optical disc (CD, DVD, etc)</summary>
public interface IWritableOpticalImage : IWritableImage, IOpticalMediaImage
{
/// <summary>Start sector for DPM</summary>
uint HeldDpmStartSector { get; set; }

/// <summary>Resolution for DPM</summary>
uint HeldDpmResolution { get; set; }

/// <summary>Number of DPM entries.</summary>
uint HeldNumberOfDpmEntries { get; set; }

/// <summary>Array of DPM entries.</summary>
ulong[] HeldDpm { get; set; }

/// <summary>Image format capabilities</summary>
OpticalImageCapabilities OpticalCapabilities { get; }

/// <summary>Sets tracks for optical media</summary>
/// <param name="tracks">List of tracks</param>
/// <returns><c>true</c> if operating completed successfully, <c>false</c> otherwise</returns>
bool SetTracks(List<Track> tracks);

/// <summary>Writes DPM data to the image</summary>
/// <param name="dpm">The array of dpm entry values.</param>
/// <returns><c>true</c> if operating completed successfully, <c>false</c> otherwise</returns>
bool WriteDPM();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where's the param?

}
11 changes: 11 additions & 0 deletions Aaru.Core/Image/Convert/Optical.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,17 @@ ErrorNumber ConvertOptical(IOpticalMediaImage inputOptical, IWritableOpticalImag
// Write MCN
if(mcn != null) outputOptical.WriteMediaTag(Encoding.UTF8.GetBytes(mcn), MediaTagType.CD_MCN);

var errorNumber = inputOptical.ReadDPM(out uint dpmStartSector, out uint dpmResolution, out uint numberOfDpmEntries, out ulong[] dpm);

if(errorNumber == ErrorNumber.NoError)
{
outputOptical.HeldDpmStartSector = dpmStartSector;
outputOptical.HeldDpmResolution = dpmResolution;
outputOptical.HeldNumberOfDpmEntries = numberOfDpmEntries;
outputOptical.HeldDpm = dpm;
}


if(!IsCompactDiscMedia(inputOptical.Info.MediaType) || !_generateSubchannels) return ErrorNumber.NoError;

// Generate subchannel data
Expand Down
5 changes: 5 additions & 0 deletions Aaru.Images/AaruFormat/AaruFormat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,9 @@ public sealed partial class AaruFormat : IWritableOpticalImage, IVerifiableImage
DriveSerialNumber = null,
DriveFirmwareRevision = null
};

public uint HeldDpmStartSector { get; set; }
public uint HeldDpmResolution { get; set; }
public uint HeldNumberOfDpmEntries { get; set; }
public ulong[] HeldDpm { get; set; }
}
17 changes: 17 additions & 0 deletions Aaru.Images/AaruFormat/Read.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,23 @@ public ErrorNumber ReadSector(ulong sectorAddress, bool negative, out byte[] buf
return ErrorNumber.NoError;
}

public ErrorNumber ReadDPM(out uint dpmStartSector, out uint dpmResolution, out uint numberOfDpmEntries, out ulong[] dpm)
{
dpmStartSector = 0;
dpmResolution = 0;
numberOfDpmEntries = 0;
dpm = null;

return ErrorNumber.NotSupported;
}

public ErrorNumber ReadSectorDPM(ulong sectorAddress, out ulong? dpm)
{
dpm = null;

return ErrorNumber.NotSupported;
}

/// <inheritdoc />
public ErrorNumber ReadSector(ulong sectorAddress, uint track, out byte[] buffer, out SectorStatus sectorStatus)
{
Expand Down
8 changes: 8 additions & 0 deletions Aaru.Images/AaruFormat/Write.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ private static partial IntPtr aaruf_create(string filepath, MediaType mediaType,

#region IWritableOpticalImage Members

/// <inheritdoc />
public bool WriteDPM()
{
ErrorMessage = Localization.Unsupported_feature;

return false;
}

/// <inheritdoc />
public bool WriteSector(byte[] data, ulong sectorAddress, bool negative, SectorStatus sectorStatus)
{
Expand Down
5 changes: 5 additions & 0 deletions Aaru.Images/Alcohol120/Alcohol120.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ public sealed partial class Alcohol120 : IWritableOpticalImage
byte[] _bca;
FileStream _descriptorStream;
byte[] _dmi;
uint _alcBlockCount;
uint[] _alcBlockStartAddress;
uint[] _dpm;
DPM _dpmBlockHeader;
bool _dpmPresent;
byte[] _fullToc;
Header _header;
ImageInfo _imageInfo;
Expand Down
116 changes: 113 additions & 3 deletions Aaru.Images/Alcohol120/Read.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Aaru.CommonTypes;
using Aaru.CommonTypes.Enums;
Expand All @@ -42,6 +43,7 @@
using Aaru.Helpers;
using Aaru.Logging;
using DMI = Aaru.Decoders.Xbox.DMI;
using Marshal = Aaru.Helpers.Marshal;
using Sector = Aaru.Decoders.CD.Sector;

namespace Aaru.Images;
Expand Down Expand Up @@ -89,10 +91,60 @@ public ErrorNumber Open(IFilter imageFilter)
AaruLogging.Debug(MODULE_NAME, "header.unknown4[{1}] = 0x{0:X8}", _header.unknown4[i], i);

AaruLogging.Debug(MODULE_NAME, "header.sessionOffset = {0}", _header.sessionOffset);
AaruLogging.Debug(MODULE_NAME, "header.dpmOffset = {0}", _header.dpmOffset);
AaruLogging.Debug(MODULE_NAME, "header.discMetadataOffset = {0}", _header.discMetadataOffset);

if(_header.version[0] > MAXIMUM_SUPPORTED_VERSION) return ErrorNumber.NotSupported;

// DPM Reading Start
if(_header.discMetadataOffset != 0)
{
stream.Seek(_header.discMetadataOffset, SeekOrigin.Begin);
var blocks = new byte[4];
stream.EnsureRead(blocks, 0, 4);

// Only the DPM metadata block is currently read, as it's currently unknown what any of the other blocks represent.
_alcBlockCount = Marshal.SpanToStructureLittleEndian<uint>(blocks);
_alcBlockStartAddress = new uint[_alcBlockCount];

for(int i = 0; i < _alcBlockCount; i++)
{
var startA = new byte[4];
stream.EnsureRead(startA, 0, 4);
_alcBlockStartAddress[i] = Marshal.SpanToStructureLittleEndian<uint>(startA);
}

stream.Seek(_alcBlockStartAddress[0], SeekOrigin.Begin);
var firstBlockTypeBytes = new byte[4];
stream.EnsureRead(firstBlockTypeBytes, 0, 4);
uint firstBlockType = Marshal.SpanToStructureLittleEndian<uint>(firstBlockTypeBytes);

// This value indicates what kind of block it is. DPM is 01. Other, non-dpm block types have
// been observed, but their purpose is currently unknown
if(firstBlockType == 1)
{
_dpmPresent = true;
var dpmBlockHdr = new byte[12];
stream.EnsureRead(dpmBlockHdr, 0, 12);
_dpmBlockHeader = Marshal.SpanToStructureLittleEndian<DPM>(dpmBlockHdr);
var dpmBytes = new byte[_dpmBlockHeader.numberOfDpmEntries * 4];
stream.EnsureRead(dpmBytes, 0, dpmBytes.Length);
ReadOnlySpan<byte> span = dpmBytes;
_dpm = new uint[_dpmBlockHeader.numberOfDpmEntries];
_dpm = MemoryMarshal.Cast<byte, uint>(span)[..(int)_dpmBlockHeader.numberOfDpmEntries].ToArray();
//_imageInfo.ReadableMediaTags.Add(MediaTagType.DPM);
}
else
{
_dpmPresent = false;
}
}
else
{
_dpmPresent = false;
}

// DPM Reading End

stream.Seek(_header.sessionOffset, SeekOrigin.Begin);
_alcSessions = new Dictionary<int, Session>();

Expand Down Expand Up @@ -341,9 +393,9 @@ public ErrorNumber Open(IFilter imageFilter)
{
stream.Seek(_alcFooter.filenameOffset, SeekOrigin.Begin);

byte[] filename = _header.dpmOffset == 0
byte[] filename = _header.discMetadataOffset == 0
? new byte[stream.Length - stream.Position]
: new byte[_header.dpmOffset - stream.Position];
: new byte[_header.discMetadataOffset - stream.Position];

stream.EnsureRead(filename, 0, filename.Length);

Expand Down Expand Up @@ -724,6 +776,64 @@ or TrackMode.Mode2F1Alt
return ErrorNumber.NoError;
}

/// <inheritdoc />
public ErrorNumber ReadDPM(out uint dpmStartSector, out uint dpmResolution, out uint numberOfDpmEntries, out ulong[] dpm)
{
if(_dpmPresent)
{
dpmStartSector = _dpmBlockHeader.dpmStartSector;
dpmResolution = _dpmBlockHeader.dpmResolution;
numberOfDpmEntries = _dpmBlockHeader.numberOfDpmEntries;
dpm = new ulong[numberOfDpmEntries];

// Arbitrary multiplication. If you want to go lower than a120's minimum dpm resolution of 50, you start
// losing precision since cumulative hex angles are only stored as uint32. Outside of this, the format a120
// /mds uses is otherwise as perfect as DPM storage realistically can be, so aaru can just give a bit of
// extra room for more possible values.

for(uint i = 0; i < numberOfDpmEntries; i++)
{
dpm[i] = _dpm[i] * 10000;
}

return ErrorNumber.NoError;
}
else
{
dpmStartSector = 0;
dpmResolution = 0;
numberOfDpmEntries = 0;
dpm = null;

return ErrorNumber.NoData;
}
}

public ErrorNumber ReadSectorDPM(ulong sectorAddress, out ulong? dpm)
{
if(_dpmPresent)
{
if(sectorAddress % _dpmBlockHeader.dpmResolution != 0)
{
dpm = null;

return ErrorNumber.NoData;
}
else
{
dpm = _dpm[sectorAddress / _dpmBlockHeader.dpmResolution] * 10000;

return ErrorNumber.NoError;
}
}
else
{
dpm = null;

return ErrorNumber.NoData;
}
}

/// <inheritdoc />
public ErrorNumber ReadMediaTag(MediaTagType tag, out byte[] buffer)
{
Expand Down
16 changes: 14 additions & 2 deletions Aaru.Images/Alcohol120/Structs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@ namespace Aaru.Images;

public sealed partial class Alcohol120
{
#region Nested type: DPM

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct DPM
{
public uint dpmStartSector;
public uint dpmResolution;
public uint numberOfDpmEntries;
}

#endregion

#region Nested type: Footer

[StructLayout(LayoutKind.Sequential, Pack = 1)]
Expand Down Expand Up @@ -71,8 +83,8 @@ struct Header
public uint structuresOffset;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public uint[] unknown4;
public uint sessionOffset;
public readonly uint dpmOffset;
public uint sessionOffset;
public uint discMetadataOffset;
}

#endregion
Expand Down
Loading
Loading