// Decompiled with JetBrains decompiler // Type: GDRomExplorer.ImageFileFormat.CDI.CDITocConverter // Assembly: CDI, Version=1.0.1.0, Culture=neutral, PublicKeyToken=611be24fdeb07e08 // MVID: B71D3BB5-2FC4-43C2-853E-907E3A458120 // Assembly location: Formats\CDI.dll using ImageReader.DiscSectors; using SEGATools; using SEGATools.DiscFileSystem; using System; using System.Collections.Generic; using System.IO; namespace GDRomExplorer.ImageFileFormat.CDI { internal class CDITocConverter { private static readonly Logger.ILog logger = Logger.CreateLog(); private static readonly int NUMBER_OF_SESSIONS_OFFSET = 0; private static readonly int TRACK_INFO_LENGTH = 58; private static readonly int TRACK_INFO_TRACK_PREGAP_OFFSET = 0; private static readonly int TRACK_INFO_TRACK_LENGTH_OFFSET = 4; private static readonly int TRACK_INFO_TRACK_MODE_OFFSET = 14; private static readonly int TRACK_INFO_TRACK_LBA_OFFSET = 30; private static readonly int TRACK_INFO_TRACK_TOTAL_LENGTH_OFFSET = 34; private static readonly int TRACK_INFO_TRACK_SECTOR_SIZE_OFFSET = 54; private static readonly byte[] TRACK_START_MARKER = new byte[10] { (byte) 0, (byte) 0, (byte) 1, (byte) 0, (byte) 0, (byte) 0, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue }; private static readonly byte[] TRACK_END_MARKER = new byte[5] { (byte) 0, byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue }; internal static CDIToc ToCdiToc( CDIHeader cdiHeader, Stream imageStream, string imageFileName) { CDIToc cdiToc = new CDIToc(cdiHeader); imageStream.Seek((long) cdiHeader.headerOffset, SeekOrigin.Begin); cdiToc.numberOfSessions = CDITocConverter.ReadNumberOfSessions(imageStream); cdiToc.numberOfTracks = new ushort[(int) cdiToc.numberOfSessions]; ushort num1 = 0; uint startOffset = 0; for (; imageStream.Position < imageStream.Length && (int) num1 < (int) cdiToc.numberOfSessions; ++num1) { cdiToc.numberOfTracks[(int) num1] = CDITocConverter.ReadNumberOfTracks(imageStream); ushort trackIndex = 0; List tracks = new List(); byte[] buffer = new byte[4]; for (; (int) trackIndex < (int) cdiToc.numberOfTracks[(int) num1]; ++trackIndex) { imageStream.Read(buffer, 0, buffer.Length); if (BitConverter.ToUInt32(buffer, 0) != 0U) imageStream.Seek(8L, SeekOrigin.Current); if (!CDITocConverter.HasTrackStartMarkers(imageStream)) throw new DiscFormatException("Invalid start-of-track marker"); imageStream.Seek(4L, SeekOrigin.Current); int num2 = imageStream.ReadByte(); imageStream.Seek((long) (num2 + 1), SeekOrigin.Current); imageStream.Seek(10L, SeekOrigin.Current); imageStream.Read(buffer, 0, buffer.Length); uint uint32 = BitConverter.ToUInt32(buffer, 0); if (uint32 != 2U) throw new DiscFormatException(string.Format("Invalid marker: {0}", (object) uint32)); imageStream.Seek(4L, SeekOrigin.Current); if (cdiHeader.cdiVersion > CDIVersion.CDI_VERSION_3) { imageStream.Read(buffer, 0, buffer.Length); if (BitConverter.ToUInt32(buffer, 0) == 2147483648U) imageStream.Seek(8L, SeekOrigin.Current); } else imageStream.Seek(4L, SeekOrigin.Current); imageStream.Seek(2L, SeekOrigin.Current); uint totalLength; DiscTrack discTrack = CDITocConverter.ReadTrackInfo(imageStream, imageFileName, trackIndex, startOffset, out totalLength); tracks.Add((IDiscTrack) discTrack); startOffset += totalLength; imageStream.Seek(25L, SeekOrigin.Current); imageStream.Seek(4L, SeekOrigin.Current); if (cdiHeader.cdiVersion > CDIVersion.CDI_VERSION_2) { if (!CDITocConverter.CheckTrackEndMarkers(imageStream)) throw new DiscFormatException("Invalid end-of-track marker"); imageStream.Read(buffer, 0, buffer.Length); if (BitConverter.ToUInt32(buffer, 0) == uint.MaxValue) imageStream.Seek(78L, SeekOrigin.Current); } } if (tracks.Count > 0) cdiToc.sessions.Add((IDiscSession) new DiscSession((int) num1 + 1, string.Format(DiscSession.DEFAULT_SESSION_NAME_WITH_FORMAT, (object) ((int) num1 + 1)), tracks)); imageStream.Seek(12L, SeekOrigin.Current); if (cdiHeader.cdiVersion > CDIVersion.CDI_VERSION_2) imageStream.Seek(1L, SeekOrigin.Current); } return cdiToc; } private static ushort ReadNumberOfSessions(Stream imageStream) { byte[] buffer = new byte[2]; imageStream.Read(buffer, 0, buffer.Length); return BitConverter.ToUInt16(buffer, CDITocConverter.NUMBER_OF_SESSIONS_OFFSET); } private static ushort ReadNumberOfTracks(Stream imageStream) { byte[] buffer = new byte[2]; imageStream.Read(buffer, 0, buffer.Length); ushort uint16 = BitConverter.ToUInt16(buffer, 0); return uint16 <= (ushort) 99 ? uint16 : throw new DiscFormatException(string.Format("Too many tracks: maximum is 99, got {0}", (object) uint16)); } private static DiscTrack ReadTrackInfo( Stream imageStream, string imageFileName, ushort trackIndex, uint startOffset, out uint totalLength) { byte[] buffer1 = new byte[CDITocConverter.TRACK_INFO_LENGTH]; imageStream.Read(buffer1, 0, buffer1.Length); uint uint32_1 = BitConverter.ToUInt32(buffer1, CDITocConverter.TRACK_INFO_TRACK_PREGAP_OFFSET); uint uint32_2 = BitConverter.ToUInt32(buffer1, CDITocConverter.TRACK_INFO_TRACK_LENGTH_OFFSET); uint uint32_3 = BitConverter.ToUInt32(buffer1, CDITocConverter.TRACK_INFO_TRACK_MODE_OFFSET); uint uint32_4 = BitConverter.ToUInt32(buffer1, CDITocConverter.TRACK_INFO_TRACK_LBA_OFFSET); uint uint32_5 = BitConverter.ToUInt32(buffer1, CDITocConverter.TRACK_INFO_TRACK_TOTAL_LENGTH_OFFSET); uint uint32_6 = BitConverter.ToUInt32(buffer1, CDITocConverter.TRACK_INFO_TRACK_SECTOR_SIZE_OFFSET); if ((int) uint32_1 + (int) uint32_2 != (int) uint32_5) throw new DiscFormatException(string.Format("Truncated track {0}: expected {1} bytes, got {2} bytes", (object) ((int) trackIndex + 1), (object) uint32_5, (object) (uint) ((int) uint32_1 + (int) uint32_2))); uint trackSectorSize = CDITocConverter.GetTrackSectorSize(uint32_6); uint num = startOffset + uint32_1 * trackSectorSize; totalLength = uint32_5 * trackSectorSize; TrackModeType trackModeType = CDITocConverter.ValidateTrackMode(uint32_3); IDiscSector trackSector = (IDiscSector) null; try { using (FileStream fileStream = File.Open(imageFileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { byte[] buffer2 = new byte[DiscSectorCommon.RawSectorSize]; fileStream.Seek((long) num, SeekOrigin.Begin); fileStream.Read(buffer2, 0, buffer2.Length); trackSector = CDITocConverter.ValidateTrackSector(trackSectorSize, trackModeType, buffer2); } } catch (Exception ex) { logger.Error(ex); throw new DiscFormatException(string.Format("Unable to read the track {0} of the file {1}", (object) ((int) trackIndex + 1), (object) imageFileName)); } return new DiscTrack(imageFileName, (long) (int) num, (long) (uint32_2 * trackSectorSize), uint32_4, (int) trackIndex + 1, trackModeType, trackSector); } private static TrackModeType ValidateTrackMode(uint trackMode) { switch (trackMode) { case 0: return TrackModeType.Audio; case 2: return TrackModeType.Data; default: throw new DiscFormatException(string.Format("Invalid track mode: {0:X}", (object) trackMode)); } } private static uint GetTrackSectorSize(uint trackSectorType) { switch (trackSectorType) { case 0: return 2048; case 1: return 2336; case 2: return 2352; default: throw new DiscFormatException(string.Format("Invalid track sector: {0:X}", (object) trackSectorType)); } } private static IDiscSector ValidateTrackSector( uint trackSector, TrackModeType trackModeType, byte[] buffer) { switch (trackSector) { case 2048: return (IDiscSector) new ISO9660Sector(); case 2336: return (IDiscSector) new CDROMXAMode2Form1Sector(); case 2352: if (trackModeType == TrackModeType.Audio) return (IDiscSector) new RawSector(); return CDROMFrameHeaderConverter.ToCDROMFrameHeader(buffer, 0) == CDROMDataModeType.MODE1_RAW ? (IDiscSector) new CDROMMode1RawSector() : (IDiscSector) new CDROMXAMode2Form1RawSector(); default: throw new DiscFormatException(string.Format("Invalid track sector size: {0:X}", (object) trackSector)); } } private static bool HasTrackStartMarkers(Stream imageStream) { byte[] buffer = new byte[CDITocConverter.TRACK_START_MARKER.Length]; for (ushort index1 = 0; index1 < (ushort) 2; ++index1) { imageStream.Read(buffer, 0, buffer.Length); for (ushort index2 = 0; (int) index2 < buffer.Length; ++index2) { if ((int) buffer[(int) index2] != (int) CDITocConverter.TRACK_START_MARKER[(int) index2]) return false; } } return true; } private static bool CheckTrackEndMarkers(Stream imageStream) { byte[] buffer = new byte[CDITocConverter.TRACK_END_MARKER.Length]; imageStream.Read(buffer, 0, buffer.Length); for (ushort index = 0; (int) index < buffer.Length; ++index) { if ((int) buffer[(int) index] != (int) CDITocConverter.TRACK_END_MARKER[(int) index]) return false; } return true; } } }