initial commit

This commit is contained in:
what 2021-07-26 13:04:16 -07:00
commit 1b60743303
274 changed files with 25866 additions and 0 deletions

View file

@ -0,0 +1,14 @@
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("2014 - 2016")]
[assembly: AssemblyTitle("GD-ROM Explorer GDI File Format")]
[assembly: AssemblyDescription("GDI File Format Plugin")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Japanese Cake")]
[assembly: AssemblyProduct("GD-ROM Explorer - GDI File Format Plugin")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(true)]
[assembly: Guid("d7bec06d-acf2-4d01-a319-8978bb4c951a")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]

67
Formats/GDI/GDI.csproj Normal file
View file

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!--Project was exported from assembly: C:\Games\gdrom\Formats\GDI.dll-->
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{F2CB9EB0-0934-48B0-952F-8BFC5DC97BAA}</ProjectGuid>
<OutputType>Library</OutputType>
<AssemblyName>GDI</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<ApplicationVersion>1.0.0.0</ApplicationVersion>
<FileAlignment>512</FileAlignment>
<RootNamespace>GDRomExplorer.ImageFileFormat.GDI</RootNamespace>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>3.5</OldToolsVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\bin\Debug\Formats\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\..\bin\Release\Formats\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="IGDIFileSystemValidator.cs" />
<Compile Include="GDIFileSystemValidator.cs" />
<Compile Include="GDImageBuilder.cs" />
<Compile Include="GDImageFormat.cs" />
<Compile Include="IInitialProgramProvider.cs" />
<Compile Include="InitialProgramProvider.cs" />
<Compile Include="AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\ImageReader\ImageReader.csproj">
<Project>{2185f55e-a4da-486f-acc8-3ee955205ce4}</Project>
<Name>ImageReader</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\SEGATools\SEGATools.csproj">
<Project>{4d3ab913-88d2-4dd1-a403-ea46d14c98e6}</Project>
<Name>SEGATools</Name>
<Private>False</Private>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View file

@ -0,0 +1,111 @@
// 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<IDiscTrack> list = session1.Tracks.Concat<IDiscTrack>((IEnumerable<IDiscTrack>) session2.Tracks).ToList<IDiscTrack>();
this.CheckTrackIndexesAreConsecutive((IList<IDiscTrack>) list);
this.CheckTrackGapAndOverlap((IList<IDiscTrack>) 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<IDiscTrack> tracks)
{
IDiscTrack discTrack = (IDiscTrack) null;
foreach (IDiscTrack track in (IEnumerable<IDiscTrack>) 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<IDiscTrack> tracks)
{
IDiscTrack discTrack = (IDiscTrack) null;
foreach (IDiscTrack track in (IEnumerable<IDiscTrack>) 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<InitialProgramTrackInfo>((Func<InitialProgramTrackInfo, long>) (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;
}
}

View file

@ -0,0 +1,117 @@
// Decompiled with JetBrains decompiler
// Type: GDRomExplorer.ImageFileFormat.GDI.GDImageBuilder
// Assembly: GDI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=611be24fdeb07e08
// MVID: F4295E7C-8421-4324-B5B1-F38932DD6235
// Assembly location: Formats\GDI.dll
using ImageReader.DiscSectors;
using SEGATools.DiscFileSystem;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
namespace GDRomExplorer.ImageFileFormat.GDI
{
public class GDImageBuilder : IDiscFileSystemConverter
{
private static readonly Regex gdiRegex = new Regex("^(?<index>[1-9]|[1-9][0-9]?)[ \\t]+(?<lba>[0-9]{1,6}?)[ \\t]+(?<type>0|4?)[ \\t]+(?<mode>2352|2048?)[ \\t]+(?<filename>\".+\\.\\S{1,4}\"|\\S+\\.\\S{1,4}?)[ \\t]+(?<offset>[+-]*[0-9]{1,6}?)[ \\t]*$", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant);
private static readonly string FIRST_SESSION_NAME = "Single Density";
private static readonly string SECOND_SESSION_NAME = "High Density";
private static readonly int HIGH_DENSITY_START_LBA = 45000;
private static readonly bool SUPPORT_DATA_EXTRACTION = true;
private static readonly bool SUPPORT_CUE_EXPORT = true;
private static readonly bool SUPPORT_GDI_EXPORT = true;
protected IGDIFileSystemValidator Validator;
protected IInitialProgramProvider IpProvider;
public GDImageBuilder()
{
this.IpProvider = (IInitialProgramProvider) new InitialProgramProvider();
this.Validator = (IGDIFileSystemValidator) new GDIFileSystemValidator(this.IpProvider);
}
public IDiscFileSystem ToDiscFileSystem(string imageFileName)
{
short result1 = 0;
short num1 = 0;
List<IDiscTrack> tracks1 = new List<IDiscTrack>();
List<IDiscTrack> tracks2 = new List<IDiscTrack>();
short num2 = 1;
using (StreamReader streamReader = new StreamReader(imageFileName))
{
if (!short.TryParse(streamReader.ReadLine().Trim(), out result1))
throw new DiscFormatException(string.Format("Wrong track index at line {0}", (object) num2));
short num3 = (short) ((int) num2 + 1);
if (result1 > (short) 99)
throw new DiscFormatException(string.Format("Too many tracks: maximum is 99, got {0}", (object) result1));
while (!streamReader.EndOfStream)
{
string input = streamReader.ReadLine().Trim();
if (string.IsNullOrEmpty(input))
{
++num3;
}
else
{
Match match = GDImageBuilder.gdiRegex.Match(input);
if (!match.Success)
throw new DiscFormatException(string.Format("Unable to parse track at line {0}", (object) num3));
TrackModeType trackData;
if (match.Groups["type"].Value == "4")
{
trackData = TrackModeType.Data;
}
else
{
if (!(match.Groups["type"].Value == "0"))
throw new DiscFormatException(string.Format("Wrong track type: got {0} whereas 0 for audio or 4 for data was expected", (object) match.Groups["type"].Value));
trackData = TrackModeType.Audio;
}
IDiscSector trackSector;
if (match.Groups["mode"].Value == "2352")
{
trackSector = trackData != TrackModeType.Data ? (IDiscSector) new RawSector() : (IDiscSector) new CDROMMode1RawSector();
}
else
{
if (!(match.Groups["mode"].Value == "2048"))
throw new DiscFormatException(string.Format("Wrong track mode: got {0} whereas 2352 or 2048 was expected", (object) match.Groups["mode"].Value));
trackSector = (IDiscSector) new ISO9660Sector();
}
int result2;
if (!int.TryParse(match.Groups["index"].Value, out result2))
throw new DiscFormatException(string.Format("Wrong track index: {0}", (object) match.Groups["index"].Value));
uint result3;
if (!uint.TryParse(match.Groups["lba"].Value, out result3))
throw new DiscFormatException(string.Format("Wrong logical block address: {0}", (object) match.Groups["lba"].Value));
int result4;
if (!int.TryParse(match.Groups["offset"].Value, out result4))
throw new DiscFormatException(string.Format("Wrong offset: {0}", (object) match.Groups["offset"].Value));
string str = match.Groups["filename"].Value.Trim().Replace("\"", "");
if (!Path.IsPathRooted(str))
str = Path.Combine(Path.GetDirectoryName(imageFileName), str);
FileInfo fileInfo = File.Exists(str) ? new FileInfo(str) : throw new DiscFormatException(string.Format("File missing: {0}", (object) str));
IDiscTrack track = (IDiscTrack) new DiscTrack(str, (long) result4, fileInfo.Length, result3, result2, trackData, trackSector);
this.Validator.CheckDiscTrackSize(track);
if ((long) track.LogicalBlockAddress < (long) GDImageBuilder.HIGH_DENSITY_START_LBA)
tracks1.Add(track);
else
tracks2.Add(track);
++num1;
++num3;
}
}
if ((int) result1 != (int) num1)
throw new DiscFormatException(string.Format("Number of tracks doesn't match: expected {0}, got {1}", (object) result1, (object) num1));
}
List<IDiscSession> sessions = new List<IDiscSession>()
{
(IDiscSession) new DiscSession(1, GDImageBuilder.FIRST_SESSION_NAME, tracks1),
(IDiscSession) new DiscSession(2, GDImageBuilder.SECOND_SESSION_NAME, tracks2)
};
SEGATools.DiscFileSystem.DiscFileSystem discFileSystem = new SEGATools.DiscFileSystem.DiscFileSystem(imageFileName, sessions, GDImageBuilder.SUPPORT_DATA_EXTRACTION, GDImageBuilder.SUPPORT_CUE_EXPORT, GDImageBuilder.SUPPORT_GDI_EXPORT);
this.Validator.CheckDiscFileSystem((IDiscFileSystem) discFileSystem);
return (IDiscFileSystem) discFileSystem;
}
}
}

View file

@ -0,0 +1,26 @@
// Decompiled with JetBrains decompiler
// Type: GDRomExplorer.ImageFileFormat.GDI.GDImageFormat
// 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.FileFormat;
namespace GDRomExplorer.ImageFileFormat.GDI
{
internal class GDImageFormat : AbstractImageFileFormat
{
public override string[] FileExtentions => new string[1]
{
".gdi"
};
public override string[] FileExtentionDescriptions => new string[1]
{
"GDROM image file"
};
public override IDiscFileSystemConverter ImageFileConverter => (IDiscFileSystemConverter) new GDImageBuilder();
}
}

View file

@ -0,0 +1,17 @@
// Decompiled with JetBrains decompiler
// Type: GDRomExplorer.ImageFileFormat.GDI.IGDIFileSystemValidator
// 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;
namespace GDRomExplorer.ImageFileFormat.GDI
{
public interface IGDIFileSystemValidator
{
void CheckDiscTrackSize(IDiscTrack track);
void CheckDiscFileSystem(IDiscFileSystem disc);
}
}

View file

@ -0,0 +1,16 @@
// Decompiled with JetBrains decompiler
// Type: GDRomExplorer.ImageFileFormat.GDI.IInitialProgramProvider
// 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;
namespace GDRomExplorer.ImageFileFormat.GDI
{
public interface IInitialProgramProvider
{
InitialProgram GetInitialProgram(IDiscTrack track);
}
}

View file

@ -0,0 +1,34 @@
// Decompiled with JetBrains decompiler
// Type: GDRomExplorer.ImageFileFormat.GDI.InitialProgramProvider
// Assembly: GDI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=611be24fdeb07e08
// MVID: F4295E7C-8421-4324-B5B1-F38932DD6235
// Assembly location: Formats\GDI.dll
using ImageReader.Stream;
using SEGATools.DiscFileSystem;
using SEGATools.Security;
using System;
namespace GDRomExplorer.ImageFileFormat.GDI
{
public class InitialProgramProvider : IInitialProgramProvider
{
public InitialProgram GetInitialProgram(IDiscTrack track)
{
try
{
byte[] buffer;
using (DiscSectorStream discSectorStream = new DiscSectorStream(track.FileInputStream, track.TrackSector))
{
buffer = new byte[(int) InitialProgram.IP_FILESIZE];
discSectorStream.Read(buffer, 0, buffer.Length);
}
return InitialProgramConverter.ToInitialProgram(buffer, 0);
}
catch (Exception ex)
{
throw new DiscFormatException(string.Format("Invalid boot sector: {0} does not contain a valid boot sector (IP)", (object) track), ex);
}
}
}
}