[GDFX] Implement GetInformation and Identify.

This commit is contained in:
2026-07-07 02:10:44 +01:00
parent f70ea9e25c
commit 4338c3a4af
3 changed files with 199 additions and 2 deletions

View File

@@ -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
/// <inheritdoc />
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;
}
/// <inheritdoc />
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<VolumeDescriptor>(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
}

View File

@@ -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);

View File

@@ -2678,6 +2678,30 @@
</data>
<data name="GDFX_Name" xml:space="preserve">
<value>Xbox DVD File System</value>
</data>
<data name="Xbox_DVD_File_System" xml:space="preserve">
<value>Xbox DVD File System</value>
</data>
<data name="Disc_type_0" xml:space="preserve">
<value>Disc type: {0}</value>
</data>
<data name="Root_directory_sector_0" xml:space="preserve">
<value>Root directory sector: {0}</value>
</data>
<data name="Rebuilt_XISO" xml:space="preserve">
<value>Rebuilt XISO</value>
</data>
<data name="XGD1" xml:space="preserve">
<value>XGD1</value>
</data>
<data name="XGD2" xml:space="preserve">
<value>XGD2</value>
</data>
<data name="XGD3" xml:space="preserve">
<value>XGD3</value>
</data>
<data name="Standard_Xbox_image" xml:space="preserve">
<value>Standard Xbox image</value>
</data>
<data name="LIF_Name" xml:space="preserve">
<value>HP Logical Interchange Format Plugin</value>