diff --git a/Aaru.Filesystems/GDFX/Info.cs b/Aaru.Filesystems/GDFX/Info.cs index 163b8e291..c860d5062 100644 --- a/Aaru.Filesystems/GDFX/Info.cs +++ b/Aaru.Filesystems/GDFX/Info.cs @@ -29,7 +29,10 @@ using System; using System.Text; using Aaru.CommonTypes.AaruMetadata; +using Aaru.CommonTypes.Enums; using Aaru.CommonTypes.Interfaces; +using Aaru.Logging; +using Marshal = Aaru.Helpers.Marshal; using Partition = Aaru.CommonTypes.Partition; namespace Aaru.Filesystems; @@ -39,11 +42,133 @@ public sealed partial class GDFX #region IFilesystem Members /// - public bool Identify(IMediaImage imagePlugin, Partition partition) => throw new NotImplementedException(); + public bool Identify(IMediaImage imagePlugin, Partition partition) + { + (ulong baseOffset, uint vdSector)[] probes = + [ + (STANDARD_OFFSET, VD_SECTOR), (GLOBAL_PARTITION_OFFSET, VD_SECTOR), (XGD3_PARTITION_OFFSET, VD_SECTOR), + (XGD1_PARTITION_OFFSET, VD_SECTOR), (STANDARD_OFFSET, REBUILT_VD_SECTOR) + ]; + + byte[] magicBytes = Encoding.ASCII.GetBytes(MAGIC); + + foreach((ulong baseOffset, uint vdSector) in probes) + { + ulong absoluteSector = baseOffset / SECTOR_SIZE + vdSector + partition.Start; + + if(absoluteSector >= partition.End) continue; + + ErrorNumber errno = imagePlugin.ReadSector(absoluteSector, false, out byte[] sector, out _); + + if(errno != ErrorNumber.NoError) continue; + + if(sector.Length < MAGIC1_OFFSET + MAGIC.Length) continue; + + var magic0Match = true; + var magic1Match = true; + + for(var i = 0; i < magicBytes.Length; i++) + { + if(sector[i] != magicBytes[i]) magic0Match = false; + + if(sector[MAGIC1_OFFSET + i] != magicBytes[i]) magic1Match = false; + } + + if(!magic0Match || !magic1Match) continue; + + AaruLogging.Debug(MODULE_NAME, + "Found XDVDFS volume descriptor at base offset 0x{0:X8}, VD sector {1}", + baseOffset, + vdSector); + + return true; + } + + return false; + } /// public void GetInformation(IMediaImage imagePlugin, Partition partition, Encoding encoding, out string information, - out FileSystem metadata) => throw new NotImplementedException(); + out FileSystem metadata) + { + information = ""; + metadata = new FileSystem(); + + (ulong baseOffset, uint vdSector)[] probes = + [ + (STANDARD_OFFSET, VD_SECTOR), (GLOBAL_PARTITION_OFFSET, VD_SECTOR), (XGD3_PARTITION_OFFSET, VD_SECTOR), + (XGD1_PARTITION_OFFSET, VD_SECTOR), (STANDARD_OFFSET, REBUILT_VD_SECTOR) + ]; + + byte[] magicBytes = Encoding.ASCII.GetBytes(MAGIC); + byte[] sector = null; + ulong matchBaseOffset = 0; + uint matchVdSector = VD_SECTOR; + + foreach((ulong baseOffset, uint vdSector) in probes) + { + ulong absoluteSector = baseOffset / SECTOR_SIZE + vdSector + partition.Start; + + if(absoluteSector >= partition.End) continue; + + ErrorNumber errno = imagePlugin.ReadSector(absoluteSector, false, out byte[] s, out _); + + if(errno != ErrorNumber.NoError) continue; + + if(s.Length < MAGIC1_OFFSET + MAGIC.Length) continue; + + var magic0Match = true; + var magic1Match = true; + + for(var i = 0; i < magicBytes.Length; i++) + { + if(s[i] != magicBytes[i]) magic0Match = false; + + if(s[MAGIC1_OFFSET + i] != magicBytes[i]) magic1Match = false; + } + + if(!magic0Match || !magic1Match) continue; + + sector = s; + matchBaseOffset = baseOffset; + matchVdSector = vdSector; + + break; + } + + if(sector is null) return; + + VolumeDescriptor vd = Marshal.ByteArrayToStructureLittleEndian(sector); + + var sb = new StringBuilder(); + sb.AppendLine(Localization.Xbox_DVD_File_System); + + string discType = (matchBaseOffset, matchVdSector) switch + { + (var b, REBUILT_VD_SECTOR) when b == STANDARD_OFFSET => Localization.Rebuilt_XISO, + var (b, _) when b == XGD1_PARTITION_OFFSET => Localization.XGD1, + var (b, _) when b == GLOBAL_PARTITION_OFFSET => Localization.XGD2, + var (b, _) when b == XGD3_PARTITION_OFFSET => Localization.XGD3, + _ => Localization.Standard_Xbox_image + }; + + sb.AppendFormat(Localization.Disc_type_0, discType).AppendLine(); + sb.AppendFormat(Localization.Root_directory_sector_0, vd.rootDirSector).AppendLine(); + sb.AppendFormat(Localization.Root_directory_size_0_bytes, vd.rootDirSize).AppendLine(); + + if(vd.fileTime > 0) + { + var creationDate = DateTime.FromFileTimeUtc((long)vd.fileTime); + sb.AppendFormat(Localization.Volume_created_on_0, creationDate).AppendLine(); + metadata.CreationDate = creationDate; + } + + information = sb.ToString(); + + metadata.Type = FS_TYPE; + metadata.ClusterSize = SECTOR_SIZE; + metadata.Clusters = partition.Size / SECTOR_SIZE; + } #endregion } \ No newline at end of file diff --git a/Aaru.Filesystems/Localization/Localization.Designer.cs b/Aaru.Filesystems/Localization/Localization.Designer.cs index 387742be6..fd90c85b3 100644 --- a/Aaru.Filesystems/Localization/Localization.Designer.cs +++ b/Aaru.Filesystems/Localization/Localization.Designer.cs @@ -5349,6 +5349,54 @@ namespace Aaru.Filesystems { } } + internal static string Xbox_DVD_File_System { + get { + return ResourceManager.GetString("Xbox_DVD_File_System", resourceCulture); + } + } + + internal static string Disc_type_0 { + get { + return ResourceManager.GetString("Disc_type_0", resourceCulture); + } + } + + internal static string Root_directory_sector_0 { + get { + return ResourceManager.GetString("Root_directory_sector_0", resourceCulture); + } + } + + internal static string Rebuilt_XISO { + get { + return ResourceManager.GetString("Rebuilt_XISO", resourceCulture); + } + } + + internal static string XGD1 { + get { + return ResourceManager.GetString("XGD1", resourceCulture); + } + } + + internal static string XGD2 { + get { + return ResourceManager.GetString("XGD2", resourceCulture); + } + } + + internal static string XGD3 { + get { + return ResourceManager.GetString("XGD3", resourceCulture); + } + } + + internal static string Standard_Xbox_image { + get { + return ResourceManager.GetString("Standard_Xbox_image", resourceCulture); + } + } + internal static string LIF_Name { get { return ResourceManager.GetString("LIF_Name", resourceCulture); diff --git a/Aaru.Filesystems/Localization/Localization.resx b/Aaru.Filesystems/Localization/Localization.resx index f34c91229..f75af5753 100644 --- a/Aaru.Filesystems/Localization/Localization.resx +++ b/Aaru.Filesystems/Localization/Localization.resx @@ -2678,6 +2678,30 @@ Xbox DVD File System + + + Xbox DVD File System + + + Disc type: {0} + + + Root directory sector: {0} + + + Rebuilt XISO + + + XGD1 + + + XGD2 + + + XGD3 + + + Standard Xbox image HP Logical Interchange Format Plugin