Add support for MagicISO UIF disc images. Fixes #258

This commit is contained in:
2026-04-19 23:22:22 +01:00
parent d38b539148
commit 5c5b8c4955
12 changed files with 1911 additions and 0 deletions

View File

@@ -6087,5 +6087,53 @@ namespace Aaru.Images {
return ResourceManager.GetString("Ewf_Identify_Signature_0", resourceCulture);
}
}
internal static string MagicIso_disc_image {
get {
return ResourceManager.GetString("MagicIso_disc_image", resourceCulture);
}
}
internal static string MagicIso_bbis_signature_not_found {
get {
return ResourceManager.GetString("MagicIso_bbis_signature_not_found", resourceCulture);
}
}
internal static string MagicIso_blhr_signature_not_found {
get {
return ResourceManager.GetString("MagicIso_blhr_signature_not_found", resourceCulture);
}
}
internal static string MagicIso_password_protected_images_are_not_supported {
get {
return ResourceManager.GetString("MagicIso_password_protected_images_are_not_supported", resourceCulture);
}
}
internal static string MagicIso_unsupported_image_type_0 {
get {
return ResourceManager.GetString("MagicIso_unsupported_image_type_0", resourceCulture);
}
}
internal static string MagicIso_unsupported_block_type_0 {
get {
return ResourceManager.GetString("MagicIso_unsupported_block_type_0", resourceCulture);
}
}
internal static string MagicIso_NRG_trailer_not_found {
get {
return ResourceManager.GetString("MagicIso_NRG_trailer_not_found", resourceCulture);
}
}
internal static string MagicIso_NRG_trailer_has_no_tracks {
get {
return ResourceManager.GetString("MagicIso_NRG_trailer_has_no_tracks", resourceCulture);
}
}
}
}

View File

@@ -3036,4 +3036,28 @@
<data name="Ewf_Identify_Signature_0" xml:space="preserve">
<value>Firma: {0}</value>
</data>
<data name="MagicIso_disc_image" xml:space="preserve">
<value>Imagen de disco UIF de MagicISO</value>
</data>
<data name="MagicIso_bbis_signature_not_found" xml:space="preserve">
<value>No se encontró la firma del pie UIF de MagicISO.</value>
</data>
<data name="MagicIso_blhr_signature_not_found" xml:space="preserve">
<value>No se encontró la cabecera BLHR en la imagen UIF de MagicISO.</value>
</data>
<data name="MagicIso_password_protected_images_are_not_supported" xml:space="preserve">
<value>Las imágenes UIF de MagicISO protegidas con contraseña no están soportadas.</value>
</data>
<data name="MagicIso_unsupported_image_type_0" xml:space="preserve">
<value>El tipo de imagen UIF de MagicISO {0} no está soportado.</value>
</data>
<data name="MagicIso_unsupported_block_type_0" xml:space="preserve">
<value>El tipo de bloque UIF de MagicISO {0} no está soportado.</value>
</data>
<data name="MagicIso_NRG_trailer_not_found" xml:space="preserve">
<value>No se encontró el ancla NRG dentro de la imagen UIF de MagicISO.</value>
</data>
<data name="MagicIso_NRG_trailer_has_no_tracks" xml:space="preserve">
<value>El bloque NRG incrustado en la imagen UIF de MagicISO no contiene pistas.</value>
</data>
</root>

View File

@@ -3055,4 +3055,28 @@
<data name="Ewf_Identify_Signature_0" xml:space="preserve">
<value>Signature: {0}</value>
</data>
<data name="MagicIso_disc_image" xml:space="preserve">
<value>MagicISO UIF disc image</value>
</data>
<data name="MagicIso_bbis_signature_not_found" xml:space="preserve">
<value>MagicISO UIF footer signature not found.</value>
</data>
<data name="MagicIso_blhr_signature_not_found" xml:space="preserve">
<value>MagicISO UIF BLHR block list header not found.</value>
</data>
<data name="MagicIso_password_protected_images_are_not_supported" xml:space="preserve">
<value>Password-protected MagicISO UIF images are not supported.</value>
</data>
<data name="MagicIso_unsupported_image_type_0" xml:space="preserve">
<value>MagicISO UIF image type {0} is not supported.</value>
</data>
<data name="MagicIso_unsupported_block_type_0" xml:space="preserve">
<value>MagicISO UIF block type {0} is not supported.</value>
</data>
<data name="MagicIso_NRG_trailer_not_found" xml:space="preserve">
<value>NRG trailer anchor was not found inside the MagicISO UIF image.</value>
</data>
<data name="MagicIso_NRG_trailer_has_no_tracks" xml:space="preserve">
<value>The NRG trailer embedded in the MagicISO UIF image has no tracks.</value>
</data>
</root>

View File

@@ -0,0 +1,73 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : Constants.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Disc image plugins.
//
// --[ Description ] ----------------------------------------------------------
//
// Contains constants for MagicISO UIF disc images.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2026 Natalia Portillo
// ****************************************************************************/
namespace Aaru.Images;
public sealed partial class MagicIso
{
const string MODULE_NAME = "MagicISO plugin";
const uint MAX_CACHE_SIZE = 16777216;
// Descriptor signatures, stored little-endian in the UIF file.
// ASCII "bbis", "blhr", "bsdr", "blms", "blss" as 32-bit little-endian integers.
const uint BBIS_SIGNATURE = 0x73696262;
const uint BLHR_SIGNATURE = 0x72686C62;
const uint BSDR_SIGNATURE = 0x72647362;
const uint BLMS_SIGNATURE = 0x736D6C62;
const uint BLSS_SIGNATURE = 0x73736C62;
// Image variants recorded in BBIS.imageType
const ushort IMAGE_TYPE_ISO = 8;
const ushort IMAGE_TYPE_MIXED = 9;
// Block entry compression types
const uint BLOCK_TYPE_RAW = 1;
const uint BLOCK_TYPE_ZERO = 3;
const uint BLOCK_TYPE_ZLIB = 5;
// NRG trailer chunk tags, stored big-endian. Equal to the ASCII four-byte id.
const uint NRG_ANCHOR_NERO = 0x4E45524F; // "NERO"
const uint NRG_ANCHOR_NER5 = 0x4E455235; // "NER5"
const uint NRG_CHUNK_DAOI = 0x44414F49; // "DAOI"
const uint NRG_CHUNK_DAOX = 0x44414F58; // "DAOX"
const uint NRG_CHUNK_ETNF = 0x45544E46; // "ETNF"
const uint NRG_CHUNK_ETN2 = 0x45544E32; // "ETN2"
const uint NRG_CHUNK_CDTX = 0x43445458; // "CDTX"
const uint NRG_CHUNK_SINF = 0x53494E46; // "SINF"
const uint NRG_CHUNK_END = 0x454E4421; // "END!"
// Nero DAO mode byte values
const byte NRG_MODE_MODE1 = 0x00;
const byte NRG_MODE_MODE2_FORM1 = 0x02;
const byte NRG_MODE_MODE2_RAW = 0x03;
const byte NRG_MODE_AUDIO = 0x07;
}

View File

@@ -0,0 +1,49 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : Enums.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Disc image plugins.
//
// --[ Description ] ----------------------------------------------------------
//
// Contains enumerations for MagicISO UIF disc images.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2026 Natalia Portillo
// ****************************************************************************/
namespace Aaru.Images;
public sealed partial class MagicIso
{
#region Nested type: UifVariant
/// <summary>Describes how the decompressed data fork should be interpreted.</summary>
enum UifVariant
{
/// <summary>Single cooked ISO data track, 2048 bytes per sector.</summary>
Iso = 0,
/// <summary>Mixed disc whose track layout is described by an embedded NRG trailer.</summary>
NrgTrailer = 1
}
#endregion
}

View File

@@ -0,0 +1,58 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : Identify.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Disc image plugins.
//
// --[ Description ] ----------------------------------------------------------
//
// Identifies MagicISO UIF disc images.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2026 Natalia Portillo
// ****************************************************************************/
using System;
using System.IO;
using Aaru.CommonTypes.Interfaces;
using Aaru.Helpers;
namespace Aaru.Images;
public sealed partial class MagicIso
{
/// <summary>Footer size as stored on disc (packed, 64 bytes).</summary>
const int BBIS_FOOTER_SIZE = 64;
/// <inheritdoc />
public bool Identify(IFilter imageFilter)
{
Stream stream = imageFilter.GetDataForkStream();
if(stream.Length < BBIS_FOOTER_SIZE) return false;
stream.Seek(-BBIS_FOOTER_SIZE, SeekOrigin.End);
var footer = new byte[BBIS_FOOTER_SIZE];
stream.EnsureRead(footer, 0, BBIS_FOOTER_SIZE);
return BitConverter.ToUInt32(footer, 0) == BBIS_SIGNATURE;
}
}

View File

@@ -0,0 +1,78 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : MagicIso.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Disc image plugins.
//
// --[ Description ] ----------------------------------------------------------
//
// Manages MagicISO UIF disc images.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2026 Natalia Portillo
// ****************************************************************************/
using System.Collections.Generic;
using System.IO;
using Aaru.CommonTypes.Interfaces;
using Aaru.CommonTypes.Structs;
using Aaru.Decoders.CD;
namespace Aaru.Images;
public sealed partial class MagicIso : IOpticalMediaImage
{
SortedList<uint, BlhrEntry> _blhrEntries;
uint[] _blhrStartSectors;
byte[] _cdText;
Dictionary<uint, byte[]> _chunkCache;
uint _currentChunkCacheSize;
BbisFooter _footer;
IFilter _imageFilter;
ImageInfo _imageInfo;
Stream _imageStream;
List<MagicIsoTrack> _magicIsoTracks;
SectorBuilder _sectorBuilder;
Dictionary<ulong, byte[]> _sectorCache;
byte[] _upc;
UifVariant _variant;
public MagicIso() => _imageInfo = new ImageInfo
{
ReadableSectorTags = [],
ReadableMediaTags = [],
HasPartitions = true,
HasSessions = true,
Version = null,
ApplicationVersion = null,
MediaTitle = null,
Creator = null,
MediaManufacturer = null,
MediaModel = null,
MediaPartNumber = null,
MediaSequence = 0,
LastMediaSequence = 0,
DriveManufacturer = null,
DriveModel = null,
DriveSerialNumber = null,
DriveFirmwareRevision = null
};
}

View File

@@ -0,0 +1,68 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : Properties.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Disc image plugins.
//
// --[ Description ] ----------------------------------------------------------
//
// Exposes properties for MagicISO UIF disc images.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2026 Natalia Portillo
// ****************************************************************************/
using System;
using System.Collections.Generic;
using Aaru.CommonTypes.AaruMetadata;
using Aaru.CommonTypes.Interfaces;
using Aaru.CommonTypes.Structs;
using Partition = Aaru.CommonTypes.Partition;
using Track = Aaru.CommonTypes.Structs.Track;
namespace Aaru.Images;
public sealed partial class MagicIso : IOpticalMediaImage
{
/// <inheritdoc />
public string Author => Authors.NataliaPortillo;
/// <inheritdoc />
public Metadata AaruMetadata => null;
/// <inheritdoc />
public List<DumpHardware> DumpHardware => null;
/// <inheritdoc />
public string Format => "MagicISO UIF";
/// <inheritdoc />
public Guid Id => new("EF5CBF5E-0F9F-4C57-9F6B-ADE4F4D4C0B1");
/// <inheritdoc />
// ReSharper disable once ConvertToAutoProperty
public ImageInfo Info => _imageInfo;
/// <inheritdoc />
public string Name => Localization.MagicIso_disc_image;
/// <inheritdoc />
public List<Partition> Partitions { get; set; }
/// <inheritdoc />
public List<Track> Tracks { get; set; }
/// <inheritdoc />
public List<Session> Sessions { get; set; }
}

1294
Aaru.Images/MagicIso/Read.cs Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,129 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : Structs.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Disc image plugins.
//
// --[ Description ] ----------------------------------------------------------
//
// Contains structures for MagicISO UIF disc images.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2026 Natalia Portillo
// ****************************************************************************/
namespace Aaru.Images;
public sealed partial class MagicIso
{
#region Nested type: BbisFooter
/// <summary>
/// UIF footer located at the end of the file. 64 bytes, little-endian. The blhr field is 64-bit; with the
/// original packing (two-byte) it sits at offset 28 within the structure.
/// </summary>
struct BbisFooter
{
/// <summary>"bbis" signature.</summary>
public uint signature;
/// <summary>Declared footer size in bytes.</summary>
public uint footerSize;
/// <summary>Version number.</summary>
public ushort version;
/// <summary>Image variant: 8 for ISO, 9 for mixed/NRG-based layouts.</summary>
public ushort imageType;
public ushort unknown1;
public ushort padding;
/// <summary>Total number of virtual sectors in the decompressed image.</summary>
public uint sectors;
/// <summary>Sector size used by the BLHR entries. 2048 for ISO, 2352 for mixed.</summary>
public uint sectorSize;
public uint unknown2;
/// <summary>Absolute file offset of the BLHR descriptor.</summary>
public ulong blhrOffset;
/// <summary>Combined size of the BLHR and BBIS headers in bytes.</summary>
public uint blhrBbisSize;
/// <summary>Hash used for password validation (unused when not encrypted).</summary>
public byte[] hash;
public uint unknown3;
public uint unknown4;
}
#endregion
#region Nested type: BlhrHeader
/// <summary>BLHR / BLMS / BLSS descriptor header. 16 bytes, little-endian.</summary>
struct BlhrHeader
{
public uint signature;
/// <summary>Size of the payload that follows, including the version and num fields (minus the 8-byte header).</summary>
public uint size;
public uint version;
/// <summary>Number of BLHR entries (BLHR) or payload bytes (BLMS/BLSS).</summary>
public uint num;
}
#endregion
#region Nested type: BlhrEntry
/// <summary>
/// Single BLHR entry. 24 bytes, little-endian. Describes a contiguous run of output sectors and its compressed
/// representation inside the UIF file.
/// </summary>
struct BlhrEntry
{
/// <summary>Absolute offset within the UIF file where the compressed payload starts.</summary>
public ulong offset;
/// <summary>Compressed size in bytes.</summary>
public uint compressedSize;
/// <summary>First output sector covered by this entry, expressed in BbisFooter.sectorSize units.</summary>
public uint startSector;
/// <summary>Number of output sectors covered by this entry.</summary>
public uint sectorCount;
/// <summary>Block compression type (1 raw, 3 zero, 5 zlib).</summary>
public uint type;
}
#endregion
#region Nested type: MagicIsoTrack
/// <summary>In-memory track record mapping a disc track onto the decompressed linear stream.</summary>
struct MagicIsoTrack
{
public uint sequence;
public ushort session;
public ulong virtualByteOffset;
public uint sectorSize;
public uint cookedBytesPerSector;
public ulong startSector;
public ulong endSector;
public int index0;
public int index1;
public uint nrgMode;
public bool rawMode1;
public bool rawMode2;
}
#endregion
}

View File

@@ -0,0 +1,65 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : Verify.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Disc image plugins.
//
// --[ Description ] ----------------------------------------------------------
//
// Verifies MagicISO UIF disc images.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2026 Natalia Portillo
// ****************************************************************************/
using System.Collections.Generic;
namespace Aaru.Images;
public sealed partial class MagicIso
{
/// <inheritdoc />
public bool? VerifySector(ulong sectorAddress) => null;
/// <inheritdoc />
public bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
{
failingLbas = [];
unknownLbas = new List<ulong>((int)length);
for(ulong i = 0; i < length; i++) unknownLbas.Add(sectorAddress + i);
return null;
}
/// <inheritdoc />
public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
{
failingLbas = [];
unknownLbas = new List<ulong>((int)length);
for(ulong i = 0; i < length; i++) unknownLbas.Add(sectorAddress + i);
return null;
}
}

View File

@@ -102,6 +102,7 @@ Media image formats we can read
* Expert Witness Format (EWF)
* HD-Copy disk images
* HxCStream
* MagicISO (.UIF)
* MAME Compressed Hunks of Data (CHD)
* Microsoft VHDX
* Nero Burning ROM (both image formats)