GDROMExplorer/SEGATools/Security/InitialProgramTocConverter.cs

97 lines
4.4 KiB
C#

// Decompiled with JetBrains decompiler
// Type: SEGATools.Security.InitialProgramTocConverter
// Assembly: SEGATools, Version=1.0.3.0, Culture=neutral, PublicKeyToken=611be24fdeb07e08
// MVID: D631183F-57B1-40A1-B502-5364D288307A
// Assembly location: SEGATools.dll
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace SEGATools.Security
{
internal sealed class InitialProgramTocConverter
{
private const string TOC_ID = "TOC1";
private const int TOC_ID_LENGTH = 4;
private const int TOC_TRACKINFO_LENGTH = 4;
private const int TOC_NUMBER_OF_TRACKINFO = 97;
private const int TOC_TRACKINFO_SIZE = 388;
private const int TOC_DATA_SIZE = 392;
private const int TOC_TRACK_INDEX_OFFSET = 3;
private const int TOC_TRACK_POST_GAP = 150;
private static readonly Logger.ILog logger = Logger.CreateLog();
private static uint TocTrackNumber(uint n) => (n & 16711680U) >> 16;
private static uint TocTrackFAD(uint n) => n & 16777215U;
private static InitialProgramTrackInfo.ControlData TocTrackType(uint n) => (InitialProgramTrackInfo.ControlData) ((n & 4026531840U) >> 28);
internal static InitialProgramToc ToInitialProgramToc(
byte[] buffer,
int startIndex)
{
if (startIndex < 0 || buffer.Length - startIndex < 392)
{
InitialProgramTocConverter.logger.ErrorFormat("Buffer too small: {0} bytes", (object) (buffer.Length - startIndex));
throw new ArgumentOutOfRangeException();
}
string str = Encoding.ASCII.GetString(buffer, startIndex, "TOC1".Length);
if (!"TOC1".Equals(str))
{
InitialProgramTocConverter.logger.ErrorFormat("Expected TOC identifier \"{0}\", got \"{1}\"", (object) "TOC1", (object) str);
throw new InitialProgramTocIdentifierMissingException();
}
InitialProgramTocConverter.TOC structure = (InitialProgramTocConverter.TOC) Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement((Array) buffer, startIndex + 4), typeof (InitialProgramTocConverter.TOC));
int length = (int) InitialProgramTocConverter.TocTrackNumber(structure.LastTrack) - (int) InitialProgramTocConverter.TocTrackNumber(structure.FirstTrack) + 1;
InitialProgramTocConverter.logger.InfoFormat("Number Of Tracks = {0}", (object) length);
InitialProgramTrackInfo[] tracks = length > 0 ? new InitialProgramTrackInfo[length] : throw new InitialProgramTocWrongNumberOfTracksException();
int num = tracks.Length - 1;
for (int trackNumber = num; trackNumber >= 0; --trackNumber)
{
uint track1 = structure.Tracks[trackNumber];
uint StartFAD = InitialProgramTocConverter.TocTrackFAD(track1);
InitialProgramTrackInfo.ControlData controlData = InitialProgramTocConverter.TocTrackType(track1);
if (!Enum.IsDefined(typeof (InitialProgramTrackInfo.ControlData), (object) controlData))
{
InitialProgramTocConverter.logger.ErrorFormat("Track {0} control value is not supported: {1}", (object) trackNumber, (object) controlData);
throw new InitialProgramTocWrongControlDataException(trackNumber, controlData);
}
InitialProgramTocTrackBuilder programTocTrackBuilder = InitialProgramTocTrackBuilder.aTrackWithIndex(3 + trackNumber).WithStartFAD(StartFAD).WithCtrl(controlData);
uint LastFAD;
if (trackNumber == num)
{
LastFAD = InitialProgramTocConverter.TocTrackFAD(structure.LeadOut) - 1U;
}
else
{
uint track2 = structure.Tracks[trackNumber + 1];
LastFAD = InitialProgramTocConverter.TocTrackFAD(track2) - 1U;
if (controlData != InitialProgramTocConverter.TocTrackType(track2))
LastFAD -= 150U;
}
programTocTrackBuilder.WithLastFAD(LastFAD);
InitialProgramTrackInfo programTrackInfo = programTocTrackBuilder.Build();
tracks[trackNumber] = programTrackInfo;
InitialProgramTocConverter.logger.DebugFormat("IP TOC: found {0}", (object) programTrackInfo);
}
return new InitialProgramToc(tracks);
}
[StructLayout(LayoutKind.Explicit, Size = 388, Pack = 1)]
private struct TOC
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 97, ArraySubType = UnmanagedType.U4)]
[FieldOffset(0)]
public uint[] Tracks;
[FieldOffset(388)]
public uint FirstTrack;
[FieldOffset(392)]
public uint LastTrack;
[FieldOffset(396)]
public uint LeadOut;
}
}
}