// Decompiled with JetBrains decompiler // Type: GDRomExplorer.ImageFileFormat.GDI.GDIFileSystemValidator // Assembly: GDI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=611be24fdeb07e08 // MVID: F4295E7C-8421-4324-B5B1-F38932DD6235 // Assembly location: Formats\GDI.dll using SEGATools.DiscFileSystem; using SEGATools.Security; using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace GDRomExplorer.ImageFileFormat.GDI { internal class GDIFileSystemValidator : IGDIFileSystemValidator { private static readonly int TRACK_MINIMUM_SIZE_IN_SECTORS = 300; private IInitialProgramProvider IpProvider; public GDIFileSystemValidator(IInitialProgramProvider IpProvider) => this.IpProvider = IpProvider; public void CheckDiscFileSystem(IDiscFileSystem disc) { IDiscSession session1 = disc.Sessions[0]; IDiscSession session2 = disc.Sessions[1]; InitialProgram initialProgram = this.IpProvider.GetInitialProgram(session2.FirstDataTrack); this.CheckInitialProgramAndHighDensityTracksMatch(initialProgram, session2); this.CheckInitialProgramAndHighDensitySizesMatch(initialProgram, session2); List list = session1.Tracks.Concat((IEnumerable) session2.Tracks).ToList(); this.CheckTrackIndexesAreConsecutive((IList) list); this.CheckTrackGapAndOverlap((IList) list); } public void CheckDiscTrackSize(IDiscTrack track) { if (track.Length % (long) track.TrackSector.Size != 0L || track.Length / (long) track.TrackSector.Size < (long) GDIFileSystemValidator.TRACK_MINIMUM_SIZE_IN_SECTORS) throw new DiscFormatException(string.Format("Invalid track size: {0} must be at least {1} bytes long and its size must a multiple of {2}.", (object) Path.GetFileName(track.FileName), (object) GDIFileSystemValidator.TRACK_MINIMUM_SIZE_IN_SECTORS, (object) track.TrackSector.Size)); } private void CheckTrackIndexesAreConsecutive(IList tracks) { IDiscTrack discTrack = (IDiscTrack) null; foreach (IDiscTrack track in (IEnumerable) tracks) { if (discTrack != null && discTrack.Index + 1 != track.Index) throw new DiscFormatException(string.Format("Track indexes are not consecutive: track with index {0} is missing", (object) track.Index)); discTrack = track; } } private void CheckTrackGapAndOverlap(IList tracks) { IDiscTrack discTrack = (IDiscTrack) null; foreach (IDiscTrack track in (IEnumerable) tracks) { if (discTrack != null) { long num1 = (long) discTrack.LogicalBlockAddress + discTrack.Length / (long) discTrack.TrackSector.Size - 1L; int num2 = discTrack.TrackData != track.TrackData ? 150 : 0; if (this.AreTracksOverlapping(num1 + (long) num2, (long) track.LogicalBlockAddress)) throw new DiscFormatException(string.Format("Tracks overlap detected: track {0} overlaps track {1}", (object) Path.GetFileName(discTrack.FileName), (object) Path.GetFileName(track.FileName))); if (discTrack.Session == track.Session && !this.AreTracksContinuous(num1 + (long) num2, (long) track.LogicalBlockAddress)) throw new DiscFormatException(string.Format("Gap between tracks: tracks {0} and {1} are not continuous", (object) Path.GetFileName(discTrack.FileName), (object) Path.GetFileName(track.FileName))); } discTrack = track; } } private void CheckInitialProgramAndHighDensityTracksMatch( InitialProgram initialProgram, IDiscSession highDensity) { this.CheckInitialProgramAndHighDensityTrackCountsMatch(initialProgram, highDensity); for (int index = 0; index < initialProgram.TableOfContent.Tracks.Count; ++index) { InitialProgramTrackInfo track1 = initialProgram.TableOfContent.Tracks[index]; IDiscTrack track2 = highDensity.Tracks[index]; long track2size = track2.Length / (long)track2.TrackSector.Size; if (track2size != (long) track1.Size) throw new DiscFormatException(string.Format("Invalid track size: {0} must be {1} sectors long", (object) track2, (object) track1.Size)); } } private void CheckInitialProgramAndHighDensitySizesMatch( InitialProgram initialProgram, IDiscSession highDensity) { long num1 = 0; foreach (IDiscTrack track in highDensity.Tracks) num1 += track.Length / (long) track.TrackSector.Size; long num2 = initialProgram.TableOfContent.Tracks.Sum((Func) (track => (long) track.Size)); if (num1 != num2) throw new DiscFormatException(string.Format("Invalid session size: the high density session must be {0} sectors long", (object) num2)); } private void CheckInitialProgramAndHighDensityTrackCountsMatch( InitialProgram initialProgram, IDiscSession highDensity) { if (initialProgram.TableOfContent == null) throw new DiscFormatException("Invalid boot sector: the boot sector does not contain a valid TOC"); if (initialProgram.TableOfContent.Tracks.Count != highDensity.Tracks.Count) throw new DiscFormatException(string.Format("Invalid number of tracks: the boot sector indicates {0} tracks whereas the {1} contains {2}", (object) initialProgram.TableOfContent.Tracks.Count, (object) highDensity.Name, (object) highDensity.Tracks.Count)); } private bool AreTracksOverlapping(long firstTrackEndLBA, long secondTrackStartLBA) => firstTrackEndLBA >= secondTrackStartLBA; private bool AreTracksContinuous(long firstTrackEndLBA, long secondTrackStartLBA) => firstTrackEndLBA + 1L == secondTrackStartLBA; } }