mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
First commit to SVN
git-svn-id: svn://claunia.com/FileSystemIDandChk@1 17725271-3d32-4980-a8cb-9ff532f270ba
This commit is contained in:
24
FileSystemIDandChk.sln
Normal file
24
FileSystemIDandChk.sln
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual Studio 2008
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileSystemIDandChk", "FileSystemIDandChk\FileSystemIDandChk.csproj", "{7A4B05BE-73C9-4F34-87FE-E80CCF1F732D}"
|
||||
EndProject
|
||||
Project("{9344bdbb-3e7f-41fc-a0dd-8665d75ee146}") = "Packages", "Packages.mdproj", "{8996EF59-09B9-4920-A3DE-2F8EA2EBBCFF}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{7A4B05BE-73C9-4F34-87FE-E80CCF1F732D}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{7A4B05BE-73C9-4F34-87FE-E80CCF1F732D}.Debug|x86.Build.0 = Debug|x86
|
||||
{7A4B05BE-73C9-4F34-87FE-E80CCF1F732D}.Release|x86.ActiveCfg = Release|x86
|
||||
{7A4B05BE-73C9-4F34-87FE-E80CCF1F732D}.Release|x86.Build.0 = Release|x86
|
||||
{8996EF59-09B9-4920-A3DE-2F8EA2EBBCFF}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{8996EF59-09B9-4920-A3DE-2F8EA2EBBCFF}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(MonoDevelopProperties) = preSolution
|
||||
StartupItem = FileSystemIDandChk\FileSystemIDandChk.csproj
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
27
FileSystemIDandChk/AssemblyInfo.cs
Normal file
27
FileSystemIDandChk/AssemblyInfo.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// Information about this assembly is defined by the following attributes.
|
||||
// Change them to the values specific to your project.
|
||||
|
||||
[assembly: AssemblyTitle("FileSystemIDandChk")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
// The following attributes are used to specify the signing key for the assembly,
|
||||
// if desired. See the Mono documentation for more information about signing.
|
||||
|
||||
//[assembly: AssemblyDelaySign(false)]
|
||||
//[assembly: AssemblyKeyFile("")]
|
||||
|
||||
24
FileSystemIDandChk/CToString.cs
Normal file
24
FileSystemIDandChk/CToString.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace FileSystemIDandChk
|
||||
{
|
||||
public static class StringHandlers
|
||||
{
|
||||
public static string CToString (byte[] CString)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for(int i = 0; i<CString.Length; i++)
|
||||
{
|
||||
if(CString[i]==0)
|
||||
break;
|
||||
|
||||
sb.Append(Encoding.ASCII.GetString(CString, i, 1));
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
58
FileSystemIDandChk/FileSystemIDandChk.csproj
Normal file
58
FileSystemIDandChk/FileSystemIDandChk.csproj
Normal file
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<ProductVersion>9.0.21022</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{7A4B05BE-73C9-4F34-87FE-E80CCF1F732D}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>FileSystemIDandChk</RootNamespace>
|
||||
<AssemblyName>FileSystemIDandChk</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Main.cs" />
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
<Compile Include="Plugins\AppleMFS.cs" />
|
||||
<Compile Include="Swapping.cs" />
|
||||
<Compile Include="Plugins\Plugin.cs" />
|
||||
<Compile Include="Plugins.cs" />
|
||||
<Compile Include="Plugins\ISO9660.cs" />
|
||||
<Compile Include="Plugins\PCEngine.cs" />
|
||||
<Compile Include="Plugins\Opera.cs" />
|
||||
<Compile Include="Plugins\AppleHFS.cs" />
|
||||
<Compile Include="Plugins\FAT.cs" />
|
||||
<Compile Include="PartPlugins\PartPlugin.cs" />
|
||||
<Compile Include="PartPlugins\AppleMap.cs" />
|
||||
<Compile Include="CToString.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
<Folder Include="Plugins\" />
|
||||
<Folder Include="PartPlugins\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
230
FileSystemIDandChk/Main.cs
Normal file
230
FileSystemIDandChk/Main.cs
Normal file
@@ -0,0 +1,230 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using FileSystemIDandChk.Plugins;
|
||||
using FileSystemIDandChk.PartPlugins;
|
||||
|
||||
namespace FileSystemIDandChk
|
||||
{
|
||||
class MainClass
|
||||
{
|
||||
static PluginBase plugins;
|
||||
public static bool chkPartitions;
|
||||
public static bool chkFilesystems;
|
||||
public static bool isDebug;
|
||||
|
||||
public static void Main (string[] args)
|
||||
{
|
||||
plugins = new PluginBase();
|
||||
|
||||
chkPartitions = true;
|
||||
chkFilesystems = true;
|
||||
isDebug = false;
|
||||
|
||||
Console.WriteLine ("Filesystem Identificator and Checker");
|
||||
Console.WriteLine ("Copyright (C) Natalia Portillo, All Rights Reserved");
|
||||
|
||||
if(args.Length==0)
|
||||
{
|
||||
Usage();
|
||||
}
|
||||
else if(args.Length==1)
|
||||
{
|
||||
plugins.RegisterAllPlugins();
|
||||
|
||||
if(args[0]=="--formats")
|
||||
{
|
||||
Console.WriteLine("Supported filesystems:");
|
||||
foreach(KeyValuePair<string, Plugin> kvp in plugins.PluginsList)
|
||||
Console.WriteLine(kvp.Value.Name);
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Supported partitions:");
|
||||
foreach(KeyValuePair<string, PartPlugin> kvp in plugins.PartPluginsList)
|
||||
Console.WriteLine(kvp.Value.Name);
|
||||
}
|
||||
else
|
||||
Runner(args[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i = 0; i<args.Length-1; i++)
|
||||
{
|
||||
switch(args[i])
|
||||
{
|
||||
case "--filesystems":
|
||||
chkFilesystems = true;
|
||||
chkPartitions = false;
|
||||
break;
|
||||
case "--partitions":
|
||||
chkFilesystems = false;
|
||||
chkPartitions = true;
|
||||
break;
|
||||
case "--all":
|
||||
chkFilesystems = true;
|
||||
chkPartitions = true;
|
||||
break;
|
||||
case "--debug":
|
||||
isDebug = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Runner(args[args.Length-1]);
|
||||
}
|
||||
}
|
||||
|
||||
private static void Runner (string filename)
|
||||
{
|
||||
FileStream stream;
|
||||
List<string> id_plugins;
|
||||
Plugin _plugin;
|
||||
string information;
|
||||
bool checkraw = false;
|
||||
|
||||
try
|
||||
{
|
||||
stream = File.OpenRead(filename);
|
||||
|
||||
if(chkPartitions)
|
||||
{
|
||||
List<Partition> partitions = new List<Partition>();
|
||||
string partition_scheme = "";
|
||||
|
||||
foreach (PartPlugin _partplugin in plugins.PartPluginsList.Values)
|
||||
{
|
||||
List<Partition> _partitions;
|
||||
|
||||
if (_partplugin.GetInformation(stream, out _partitions))
|
||||
{
|
||||
partition_scheme=_partplugin.Name;
|
||||
partitions = _partitions;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(partition_scheme=="")
|
||||
{
|
||||
if(!chkFilesystems)
|
||||
{
|
||||
Console.WriteLine("No partitions founds, not searching for filesystems");
|
||||
return;
|
||||
}
|
||||
else
|
||||
checkraw = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Partition scheme identified as {0}", partition_scheme);
|
||||
Console.WriteLine("{0} partitions found.", partitions.Count);
|
||||
|
||||
for(int i = 0; i< partitions.Count; i++)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Partition {0}:", partitions[i].PartitionSequence);
|
||||
Console.WriteLine("Partition name: {0}", partitions[i].PartitionName);
|
||||
Console.WriteLine("Partition type: {0}", partitions[i].PartitionType);
|
||||
Console.WriteLine("Partition start: {0}", partitions[i].PartitionStart);
|
||||
Console.WriteLine("Partition length: {0}", partitions[i].PartitionLength);
|
||||
Console.WriteLine("Partition description:");
|
||||
Console.WriteLine(partitions[i].PartitionDescription);
|
||||
|
||||
if(chkFilesystems)
|
||||
{
|
||||
Console.WriteLine("Identifying filesystem on partition");
|
||||
|
||||
Identify(stream, out id_plugins, partitions[i].PartitionStart);
|
||||
if(id_plugins.Count==0)
|
||||
Console.WriteLine("Filesystem not identified");
|
||||
else if(id_plugins.Count>1)
|
||||
{
|
||||
Console.WriteLine(String.Format("Identified by {0} plugins", id_plugins.Count));
|
||||
|
||||
foreach(string plugin_name in id_plugins)
|
||||
{
|
||||
if(plugins.PluginsList.TryGetValue(plugin_name, out _plugin))
|
||||
{
|
||||
Console.WriteLine(String.Format("As identified by {0}.", _plugin.Name));
|
||||
_plugin.GetInformation(stream, partitions[i].PartitionStart, out information);
|
||||
Console.Write(information);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
plugins.PluginsList.TryGetValue(id_plugins[0], out _plugin);
|
||||
Console.WriteLine(String.Format("Identified by {0}.", _plugin.Name));
|
||||
_plugin.GetInformation(stream, partitions[i].PartitionStart, out information);
|
||||
Console.Write(information);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(checkraw)
|
||||
{
|
||||
Identify(stream, out id_plugins, 0);
|
||||
if(id_plugins.Count==0)
|
||||
Console.WriteLine("Filesystem not identified");
|
||||
else if(id_plugins.Count>1)
|
||||
{
|
||||
Console.WriteLine(String.Format("Identified by {0} plugins", id_plugins.Count));
|
||||
|
||||
foreach(string plugin_name in id_plugins)
|
||||
{
|
||||
if(plugins.PluginsList.TryGetValue(plugin_name, out _plugin))
|
||||
{
|
||||
Console.WriteLine(String.Format("As identified by {0}.", _plugin.Name));
|
||||
_plugin.GetInformation(stream, 0, out information);
|
||||
Console.Write(information);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
plugins.PluginsList.TryGetValue(id_plugins[0], out _plugin);
|
||||
Console.WriteLine(String.Format("Identified by {0}.", _plugin.Name));
|
||||
_plugin.GetInformation(stream, 0, out information);
|
||||
Console.Write(information);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Console.WriteLine(String.Format("Error reading file: {0}", ex.Message));
|
||||
if(isDebug)
|
||||
Console.WriteLine(ex.StackTrace);
|
||||
}
|
||||
finally
|
||||
{
|
||||
stream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private static void Identify (FileStream stream, out List<string> id_plugins, long offset)
|
||||
{
|
||||
id_plugins = new List<string>();
|
||||
|
||||
foreach (Plugin _plugin in plugins.PluginsList.Values)
|
||||
{
|
||||
if (_plugin.Identify(stream, offset))
|
||||
id_plugins.Add(_plugin.Name.ToLower());
|
||||
}
|
||||
}
|
||||
|
||||
private static void Usage ()
|
||||
{
|
||||
Console.WriteLine("Usage: filesystemidandchk [options] file");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine(" --formats List all suported partition and filesystems");
|
||||
Console.WriteLine(" --debug Show debug information");
|
||||
Console.WriteLine(" --partitions Check only for partitions");
|
||||
Console.WriteLine(" --filesystems Check only for filesystems");
|
||||
Console.WriteLine(" --all Check for partitions and filesystems (default)");
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
202
FileSystemIDandChk/PartPlugins/AppleMap.cs
Normal file
202
FileSystemIDandChk/PartPlugins/AppleMap.cs
Normal file
@@ -0,0 +1,202 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using FileSystemIDandChk;
|
||||
|
||||
namespace FileSystemIDandChk.PartPlugins
|
||||
{
|
||||
class AppleMap : PartPlugin
|
||||
{
|
||||
public AppleMap (PluginBase Core)
|
||||
{
|
||||
base.Name = "Apple Partition Map";
|
||||
base.PluginUUID = new Guid("ffe4b4e9-82ed-4761-af49-8bade4081d10");
|
||||
}
|
||||
|
||||
public override bool GetInformation (FileStream stream, out List<Partition> partitions)
|
||||
{
|
||||
byte[] sixteen_bits = new byte[2];
|
||||
byte[] thirtytwo_bits = new byte[4];
|
||||
byte[] sixteen_bytes = new byte[16];
|
||||
byte[] thirtytwo_bytes = new byte[32];
|
||||
|
||||
ulong apm_entries;
|
||||
|
||||
partitions = new List<Partition>();
|
||||
|
||||
AppleMapBootEntry APMB = new AppleMapBootEntry();
|
||||
AppleMapPartitionEntry APMEntry = new AppleMapPartitionEntry();
|
||||
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
stream.Read(sixteen_bits, 0, 2);
|
||||
sixteen_bits = Swapping.SwapTwoBytes(sixteen_bits);
|
||||
APMB.signature = BitConverter.ToUInt16(sixteen_bits, 0);
|
||||
|
||||
if(APMB.signature != 0x4552)
|
||||
return false; // Not an Apple Partition Map
|
||||
|
||||
stream.Read(sixteen_bits, 0, 2);
|
||||
sixteen_bits = Swapping.SwapTwoBytes(sixteen_bits);
|
||||
APMB.sector_size = BitConverter.ToUInt16(sixteen_bits, 0);
|
||||
|
||||
stream.Seek(APMB.sector_size, SeekOrigin.Begin); // Seek to first entry
|
||||
stream.Read(sixteen_bits, 0, 2);
|
||||
sixteen_bits = Swapping.SwapTwoBytes(sixteen_bits);
|
||||
APMEntry.signature = BitConverter.ToUInt16(sixteen_bits, 0);
|
||||
if(APMEntry.signature != 0x504D && APMEntry.signature != 0x5453) // It should have partition entry signature
|
||||
return false;
|
||||
|
||||
stream.Seek(2, SeekOrigin.Current); // Skip reserved1
|
||||
stream.Read(thirtytwo_bits, 0, 4);
|
||||
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits);
|
||||
APMEntry.entries = BitConverter.ToUInt32(thirtytwo_bits, 0);
|
||||
if(APMEntry.entries <= 1) // It should have more than one entry
|
||||
return false;
|
||||
|
||||
stream.Seek(4, SeekOrigin.Current); // Skip start, we don't need it
|
||||
stream.Seek(4, SeekOrigin.Current); // Skip sectors, we don't need it
|
||||
stream.Seek(32, SeekOrigin.Current); // Skip name, we don't ned it
|
||||
|
||||
stream.Read(thirtytwo_bytes, 0, 32);
|
||||
APMEntry.type = StringHandlers.CToString(thirtytwo_bytes);
|
||||
if(APMEntry.type != "Apple_partition_map") // APM self-describes, if not, this is incorrect
|
||||
return false;
|
||||
|
||||
apm_entries = APMEntry.entries;
|
||||
|
||||
for(ulong i = 2; i <= apm_entries; i++) // For each partition
|
||||
{
|
||||
APMEntry = new AppleMapPartitionEntry();
|
||||
|
||||
stream.Seek((long)(APMB.sector_size*i), SeekOrigin.Begin); // Seek to partition descriptor
|
||||
|
||||
stream.Read(sixteen_bits, 0, 2);
|
||||
sixteen_bits = Swapping.SwapTwoBytes(sixteen_bits);
|
||||
APMEntry.signature = BitConverter.ToUInt16(sixteen_bits, 0);
|
||||
if(APMEntry.signature == 0x504D || APMEntry.signature == 0x5453) // It should have partition entry signature
|
||||
{
|
||||
Partition _partition = new Partition();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
stream.Seek(2, SeekOrigin.Current); // Skip reserved1
|
||||
stream.Seek(4, SeekOrigin.Current); // Skip entries
|
||||
|
||||
stream.Read(thirtytwo_bits, 0, 4);
|
||||
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits);
|
||||
APMEntry.start = BitConverter.ToUInt32(thirtytwo_bits, 0);
|
||||
stream.Read(thirtytwo_bits, 0, 4);
|
||||
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits);
|
||||
APMEntry.sectors = BitConverter.ToUInt32(thirtytwo_bits, 0);
|
||||
stream.Read(thirtytwo_bytes, 0, 32);
|
||||
APMEntry.name = StringHandlers.CToString(thirtytwo_bytes);
|
||||
stream.Read(thirtytwo_bytes, 0, 32);
|
||||
APMEntry.type = StringHandlers.CToString(thirtytwo_bytes);
|
||||
stream.Read(thirtytwo_bits, 0, 4);
|
||||
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits);
|
||||
APMEntry.first_data_block = BitConverter.ToUInt32(thirtytwo_bits, 0);
|
||||
stream.Read(thirtytwo_bits, 0, 4);
|
||||
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits);
|
||||
APMEntry.data_sectors = BitConverter.ToUInt32(thirtytwo_bits, 0);
|
||||
stream.Read(thirtytwo_bits, 0, 4);
|
||||
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits);
|
||||
APMEntry.status = BitConverter.ToUInt32(thirtytwo_bits, 0);
|
||||
stream.Read(thirtytwo_bits, 0, 4);
|
||||
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits);
|
||||
APMEntry.first_boot_block = BitConverter.ToUInt32(thirtytwo_bits, 0);
|
||||
stream.Read(thirtytwo_bits, 0, 4);
|
||||
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits);
|
||||
APMEntry.boot_size = BitConverter.ToUInt32(thirtytwo_bits, 0);
|
||||
stream.Read(thirtytwo_bits, 0, 4);
|
||||
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits);
|
||||
APMEntry.load_address = BitConverter.ToUInt32(thirtytwo_bits, 0);
|
||||
stream.Seek(4, SeekOrigin.Current);
|
||||
stream.Read(thirtytwo_bits, 0, 4);
|
||||
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits);
|
||||
APMEntry.entry_point = BitConverter.ToUInt32(thirtytwo_bits, 0);
|
||||
stream.Seek(4, SeekOrigin.Current);
|
||||
stream.Read(thirtytwo_bits, 0, 4);
|
||||
thirtytwo_bits = Swapping.SwapFourBytes(thirtytwo_bits);
|
||||
APMEntry.checksum = BitConverter.ToUInt32(thirtytwo_bits, 0);
|
||||
stream.Read(sixteen_bytes, 0, 16);
|
||||
APMEntry.processor = StringHandlers.CToString(sixteen_bytes);
|
||||
|
||||
_partition.PartitionSequence = i;
|
||||
_partition.PartitionType = APMEntry.type;
|
||||
_partition.PartitionName = APMEntry.name;
|
||||
_partition.PartitionStart = APMEntry.start * APMB.sector_size;
|
||||
_partition.PartitionLength = APMEntry.sectors * APMB.sector_size;
|
||||
|
||||
sb.AppendLine("Partition flags:");
|
||||
if((APMEntry.status & 0x01) == 0x01)
|
||||
sb.AppendLine("Partition is valid.");
|
||||
if((APMEntry.status & 0x02) == 0x02)
|
||||
sb.AppendLine("Partition entry is not available.");
|
||||
if((APMEntry.status & 0x04) == 0x04)
|
||||
sb.AppendLine("Partition is mounted.");
|
||||
if((APMEntry.status & 0x08) == 0x08)
|
||||
sb.AppendLine("Partition is bootable.");
|
||||
if((APMEntry.status & 0x10) == 0x10)
|
||||
sb.AppendLine("Partition is readable.");
|
||||
if((APMEntry.status & 0x20) == 0x20)
|
||||
sb.AppendLine("Partition is writable.");
|
||||
if((APMEntry.status & 0x40) == 0x40)
|
||||
sb.AppendLine("Partition's boot code is position independent.");
|
||||
|
||||
if((APMEntry.status & 0x08) == 0x08)
|
||||
{
|
||||
sb.AppendFormat("First boot sector: {0}", APMEntry.first_boot_block).AppendLine();
|
||||
sb.AppendFormat("Boot is {0} bytes.", APMEntry.boot_size).AppendLine();
|
||||
sb.AppendFormat("Boot load address: 0x{0:X8}", APMEntry.load_address).AppendLine();
|
||||
sb.AppendFormat("Boot entry point: 0x{0:X8}", APMEntry.entry_point).AppendLine();
|
||||
sb.AppendFormat("Boot code checksum: 0x{0:X8}", APMEntry.checksum).AppendLine();
|
||||
sb.AppendFormat("Processor: {0}", APMEntry.processor).AppendLine();
|
||||
}
|
||||
|
||||
_partition.PartitionDescription = sb.ToString();
|
||||
|
||||
if((APMEntry.status & 0x01) == 0x01)
|
||||
partitions.Add(_partition);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public struct AppleMapBootEntry
|
||||
{
|
||||
public UInt16 signature; // Signature ("ER")
|
||||
public UInt16 sector_size; // Byter per sector
|
||||
public UInt32 sectors; // Sectors of the disk
|
||||
public UInt16 reserved1; // Reserved
|
||||
public UInt16 reserved2; // Reserved
|
||||
public UInt32 reserved3; // Reserved
|
||||
public UInt16 driver_entries; // Number of entries of the driver descriptor
|
||||
public UInt32 first_driver_blk; // First sector of the driver
|
||||
public UInt16 driver_size; // Size in 512bytes sectors of the driver
|
||||
public UInt16 operating_system; // Operating system (MacOS = 1)
|
||||
}
|
||||
|
||||
public struct AppleMapPartitionEntry
|
||||
{
|
||||
public UInt16 signature; // Signature ("PM" or "TS")
|
||||
public UInt16 reserved1; // Reserved
|
||||
public UInt32 entries; // Number of entries on the partition map, each one sector
|
||||
public UInt32 start; // First sector of the partition
|
||||
public UInt32 sectors; // Number of sectos of the partition
|
||||
public string name; // Partition name, 32 bytes, null-padded
|
||||
public string type; // Partition type. 32 bytes, null-padded
|
||||
public UInt32 first_data_block; // First sector of the data area
|
||||
public UInt32 data_sectors; // Number of sectors of the data area
|
||||
public UInt32 status; // Partition status
|
||||
public UInt32 first_boot_block; // First sector of the boot code
|
||||
public UInt32 boot_size; // Size in bytes of the boot code
|
||||
public UInt32 load_address; // Load address of the boot code
|
||||
public UInt32 reserved2; // Reserved
|
||||
public UInt32 entry_point; // Entry point of the boot code
|
||||
public UInt32 reserved3; // Reserved
|
||||
public UInt32 checksum; // Boot code checksum
|
||||
public string processor; // Processor type, 16 bytes, null-padded
|
||||
}
|
||||
}
|
||||
}
|
||||
28
FileSystemIDandChk/PartPlugins/PartPlugin.cs
Normal file
28
FileSystemIDandChk/PartPlugins/PartPlugin.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FileSystemIDandChk.PartPlugins
|
||||
{
|
||||
public abstract class PartPlugin
|
||||
{
|
||||
public string Name;
|
||||
public Guid PluginUUID;
|
||||
|
||||
protected PartPlugin ()
|
||||
{
|
||||
}
|
||||
|
||||
public abstract bool GetInformation(FileStream stream, out List<Partition> partitions);
|
||||
}
|
||||
|
||||
public struct Partition
|
||||
{
|
||||
public ulong PartitionSequence; // Partition number, 0-started
|
||||
public string PartitionType; // Partition type
|
||||
public string PartitionName; // Partition name (if the scheme supports it)
|
||||
public long PartitionStart; // Start of the partition, in bytes
|
||||
public long PartitionLength; // Length in bytes of the partition
|
||||
public string PartitionDescription; // Information that does not find space in this struct
|
||||
}
|
||||
}
|
||||
64
FileSystemIDandChk/Plugins.cs
Normal file
64
FileSystemIDandChk/Plugins.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Collections.Generic;
|
||||
using FileSystemIDandChk.Plugins;
|
||||
using FileSystemIDandChk.PartPlugins;
|
||||
|
||||
namespace FileSystemIDandChk
|
||||
{
|
||||
public class PluginBase
|
||||
{
|
||||
public Dictionary<string, Plugin> PluginsList;
|
||||
public Dictionary<string, PartPlugin> PartPluginsList;
|
||||
|
||||
public PluginBase ()
|
||||
{
|
||||
this.PluginsList = new Dictionary<string, Plugin>();
|
||||
this.PartPluginsList = new Dictionary<string, PartPlugin>();
|
||||
}
|
||||
|
||||
public void RegisterAllPlugins()
|
||||
{
|
||||
Assembly assembly = Assembly.GetExecutingAssembly();
|
||||
|
||||
foreach (Type type in assembly.GetTypes())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (type.IsSubclassOf(typeof(Plugin)))
|
||||
{
|
||||
Plugin plugin = (Plugin)type.GetConstructor(new Type[] { typeof(PluginBase) }).Invoke(new object[] { this });
|
||||
this.RegisterPlugin(plugin);
|
||||
}
|
||||
else if (type.IsSubclassOf(typeof(PartPlugin)))
|
||||
{
|
||||
PartPlugin partplugin = (PartPlugin)type.GetConstructor(new Type[] { typeof(PluginBase) }).Invoke(new object[] { this });
|
||||
this.RegisterPartPlugin(partplugin);
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Console.WriteLine(exception.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RegisterPlugin(Plugin plugin)
|
||||
{
|
||||
if (!this.PluginsList.ContainsKey(plugin.Name.ToLower()))
|
||||
{
|
||||
this.PluginsList.Add(plugin.Name.ToLower(), plugin);
|
||||
}
|
||||
}
|
||||
|
||||
private void RegisterPartPlugin(PartPlugin partplugin)
|
||||
{
|
||||
if (!this.PartPluginsList.ContainsKey(partplugin.Name.ToLower()))
|
||||
{
|
||||
this.PartPluginsList.Add(partplugin.Name.ToLower(), partplugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
401
FileSystemIDandChk/Plugins/AppleHFS.cs
Normal file
401
FileSystemIDandChk/Plugins/AppleHFS.cs
Normal file
@@ -0,0 +1,401 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using FileSystemIDandChk;
|
||||
|
||||
// Information from Inside Macintosh
|
||||
|
||||
namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
class AppleHFS : Plugin
|
||||
{
|
||||
private DateTime HFSDateDelta = new DateTime(1904, 01, 01, 00, 00, 00);
|
||||
|
||||
public AppleHFS(PluginBase Core)
|
||||
{
|
||||
base.Name = "Apple Hierarchical File System";
|
||||
base.PluginUUID = new Guid("8f4ee9d5-6820-4d7a-ae6b-3a4a49e7a88f");
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream stream, long offset)
|
||||
{
|
||||
byte[] signature = new byte[2];
|
||||
ushort drSigWord;
|
||||
|
||||
stream.Seek(0x400 + offset, SeekOrigin.Begin);
|
||||
|
||||
stream.Read(signature, 0, 2);
|
||||
signature = Swapping.SwapTwoBytes(signature);
|
||||
|
||||
drSigWord = BitConverter.ToUInt16(signature, 0);
|
||||
|
||||
if(drSigWord == 0x4244)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream stream, long offset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
HFS_MasterDirectoryBlock MDB = new HFS_MasterDirectoryBlock();
|
||||
HFS_BootBlock BB = new HFS_BootBlock();
|
||||
|
||||
byte[] sixteen_bit = new byte[2];
|
||||
byte[] thirtytwo_bit = new byte[4];
|
||||
byte[] fifthteen_bytes = new byte[15];
|
||||
|
||||
stream.Seek(0x400 + offset, SeekOrigin.Begin);
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
MDB.drSigWord = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
if(MDB.drSigWord != 0x4244)
|
||||
return;
|
||||
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drCrDate = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drLsMod = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
MDB.drAtrb = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
MDB.drNmFls = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
MDB.drVBMSt = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
MDB.drAllocPtr = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
MDB.drNmAlBlks = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drAlBlkSiz = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drClpSiz = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
MDB.drAlBlSt = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drNxtCNID = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
MDB.drFreeBks = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
MDB.drVN = new byte[28];
|
||||
stream.Read(MDB.drVN, 0, 28);
|
||||
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drVolBkUp = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
MDB.drVSeqNum = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drWrCnt = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drXTClpSiz = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drCTClpSiz = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
MDB.drNmRtDirs = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drFilCnt = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drDirCnt = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drFndrInfo0 = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drFndrInfo1 = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drFndrInfo2 = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drFndrInfo3 = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drFndrInfo4 = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drFndrInfo5 = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drFndrInfo6 = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drFndrInfo7 = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
MDB.drEmbedSigWord = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
MDB.xdrStABNt = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
MDB.xdrNumABlks = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drXTFlSize = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Seek(12, SeekOrigin.Current);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drCTFlSize = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Seek(12, SeekOrigin.Current);
|
||||
|
||||
stream.Seek(0 + offset, SeekOrigin.Begin);
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
BB.signature = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
|
||||
if(BB.signature == 0x4C4B)
|
||||
{
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
BB.branch = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
BB.boot_flags = (byte)stream.ReadByte();
|
||||
BB.boot_version = (byte)stream.ReadByte();
|
||||
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
BB.sec_sv_pages = BitConverter.ToInt16(sixteen_bit, 0);
|
||||
|
||||
stream.Seek(1, SeekOrigin.Current);
|
||||
stream.Read(fifthteen_bytes, 0, 15);
|
||||
BB.system_name = Encoding.ASCII.GetString(fifthteen_bytes);
|
||||
stream.Seek(1, SeekOrigin.Current);
|
||||
stream.Read(fifthteen_bytes, 0, 15);
|
||||
BB.finder_name = Encoding.ASCII.GetString(fifthteen_bytes);
|
||||
stream.Seek(1, SeekOrigin.Current);
|
||||
stream.Read(fifthteen_bytes, 0, 15);
|
||||
BB.debug_name = Encoding.ASCII.GetString(fifthteen_bytes);
|
||||
stream.Seek(1, SeekOrigin.Current);
|
||||
stream.Read(fifthteen_bytes, 0, 15);
|
||||
BB.disasm_name = Encoding.ASCII.GetString(fifthteen_bytes);
|
||||
stream.Seek(1, SeekOrigin.Current);
|
||||
stream.Read(fifthteen_bytes, 0, 15);
|
||||
BB.stupscr_name = Encoding.ASCII.GetString(fifthteen_bytes);
|
||||
stream.Seek(1, SeekOrigin.Current);
|
||||
stream.Read(fifthteen_bytes, 0, 15);
|
||||
BB.bootup_name = Encoding.ASCII.GetString(fifthteen_bytes);
|
||||
stream.Seek(1, SeekOrigin.Current);
|
||||
stream.Read(fifthteen_bytes, 0, 15);
|
||||
BB.clipbrd_name = Encoding.ASCII.GetString(fifthteen_bytes);
|
||||
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
BB.max_files = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
BB.queue_size = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
BB.heap_128k = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
BB.heap_256k = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
BB.heap_512k = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
}
|
||||
else
|
||||
BB.signature = 0x0000;
|
||||
|
||||
sb.AppendLine("Apple Hierarchical File System");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("Master Directory Block:");
|
||||
sb.AppendFormat("Creation date: {0}", HFSDateDelta.AddTicks((long)(MDB.drCrDate*10000000))).AppendLine();
|
||||
sb.AppendFormat("Last modification date: {0}", HFSDateDelta.AddTicks((long)(MDB.drLsMod*10000000))).AppendLine();
|
||||
sb.AppendFormat("Last backup date: {0}", HFSDateDelta.AddTicks((long)(MDB.drVolBkUp*10000000))).AppendLine();
|
||||
sb.AppendFormat("Backup sequence number: {0}", MDB.drVSeqNum).AppendLine();
|
||||
|
||||
if((MDB.drAtrb & 0x80) == 0x80)
|
||||
sb.AppendLine("Volume is locked by hardware.");
|
||||
if((MDB.drAtrb & 0x100) == 0x100)
|
||||
sb.AppendLine("Volume was unmonted.");
|
||||
else
|
||||
sb.AppendLine("Volume is mounted.");
|
||||
if((MDB.drAtrb & 0x200) == 0x200)
|
||||
sb.AppendLine("Volume has spared bad blocks.");
|
||||
if((MDB.drAtrb & 0x400) == 0x400)
|
||||
sb.AppendLine("Volume does not need cache.");
|
||||
if((MDB.drAtrb & 0x800) == 0x800)
|
||||
sb.AppendLine("Boot volume is inconsistent.");
|
||||
if((MDB.drAtrb & 0x1000) == 0x1000)
|
||||
sb.AppendLine("There are reused CNIDs.");
|
||||
if((MDB.drAtrb & 0x2000) == 0x2000)
|
||||
sb.AppendLine("Volume is journaled.");
|
||||
if((MDB.drAtrb & 0x4000) == 0x4000)
|
||||
sb.AppendLine("Volume is seriously inconsistent.");
|
||||
if((MDB.drAtrb & 0x8000) == 0x8000)
|
||||
sb.AppendLine("Volume is locked by software.");
|
||||
|
||||
sb.AppendFormat("{0} files on root directory", MDB.drNmFls).AppendLine();
|
||||
sb.AppendFormat("{0} directories on root directory", MDB.drNmRtDirs).AppendLine();
|
||||
sb.AppendFormat("{0} files on volume", MDB.drFilCnt).AppendLine();
|
||||
sb.AppendFormat("{0} directories on volume", MDB.drDirCnt).AppendLine();
|
||||
sb.AppendFormat("Volume write count: {0}", MDB.drWrCnt).AppendLine();
|
||||
|
||||
sb.AppendFormat("Volume bitmap starting sector (in 512-bytes): {0}", MDB.drVBMSt).AppendLine();
|
||||
sb.AppendFormat("Next allocation block: {0}.", MDB.drAllocPtr).AppendLine();
|
||||
sb.AppendFormat("{0} volume allocation blocks.", MDB.drNmAlBlks).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per allocation block.", MDB.drAlBlkSiz).AppendLine();
|
||||
sb.AppendFormat("{0} bytes to allocate when extending a file.", MDB.drClpSiz).AppendLine();
|
||||
sb.AppendFormat("{0} bytes to allocate when extending a Extents B-Tree.", MDB.drXTClpSiz).AppendLine();
|
||||
sb.AppendFormat("{0} bytes to allocate when extending a Catalog B-Tree.", MDB.drCTClpSiz).AppendLine();
|
||||
sb.AppendFormat("Sector of first allocation block: {0}", MDB.drAlBlSt).AppendLine();
|
||||
sb.AppendFormat("Next unused CNID: {0}", MDB.drNxtCNID).AppendLine();
|
||||
sb.AppendFormat("{0} unused allocation blocks.", MDB.drFreeBks).AppendLine();
|
||||
|
||||
sb.AppendFormat("{0} bytes in the Extents B-Tree", MDB.drXTFlSize).AppendLine();
|
||||
sb.AppendFormat("{0} bytes in the Catalog B-Tree", MDB.drCTFlSize).AppendLine();
|
||||
|
||||
StringBuilder volumeName = new StringBuilder();
|
||||
for(int i = 1; i < 28; i++)
|
||||
{
|
||||
if(MDB.drVN[i] == 0)
|
||||
break;
|
||||
|
||||
volumeName.Append(Encoding.ASCII.GetString(MDB.drVN, i, 1));
|
||||
}
|
||||
sb.AppendFormat("Volume name: {0}", volumeName.ToString()).AppendLine();
|
||||
|
||||
sb.AppendLine("Finder info:");
|
||||
sb.AppendFormat("CNID of bootable system's directory: {0}", MDB.drFndrInfo0).AppendLine();
|
||||
sb.AppendFormat("CNID of first-run application's directory: {0}", MDB.drFndrInfo1).AppendLine();
|
||||
sb.AppendFormat("CNID of previously opened directory: {0}", MDB.drFndrInfo2).AppendLine();
|
||||
sb.AppendFormat("CNID of bootable Mac OS 8 or 9 directory: {0}", MDB.drFndrInfo3).AppendLine();
|
||||
sb.AppendFormat("CNID of bootable Mac OS X directory: {0}", MDB.drFndrInfo5).AppendLine();
|
||||
sb.AppendFormat("Mac OS X Volume ID: {0:X8}{1:X8}", MDB.drFndrInfo6, MDB.drFndrInfo7).AppendLine();
|
||||
|
||||
if(MDB.drEmbedSigWord == 0x482B)
|
||||
{
|
||||
sb.AppendLine("Volume wraps a HFS+ volume.");
|
||||
sb.AppendFormat("Starting block of the HFS+ volume: {0}", MDB.xdrStABNt).AppendLine();
|
||||
sb.AppendFormat("Allocations blocks of the HFS+ volume: {0}", MDB.xdrNumABlks).AppendLine();
|
||||
}
|
||||
|
||||
if(BB.signature == 0x4C4B)
|
||||
{
|
||||
sb.AppendLine("Volume is bootable.");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("Boot Block:");
|
||||
if((BB.boot_flags & 0x40) == 0x40)
|
||||
sb.AppendLine("Boot block should be executed.");
|
||||
if((BB.boot_flags & 0x80) == 0x80)
|
||||
{
|
||||
sb.AppendLine("Boot block is in new unknown format.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(BB.sec_sv_pages > 0)
|
||||
sb.AppendLine("Allocate secondary sound buffer at boot.");
|
||||
else if(BB.sec_sv_pages < 0)
|
||||
sb.AppendLine("Allocate secondary sound and video buffers at boot.");
|
||||
|
||||
sb.AppendFormat("System filename: {0}", BB.system_name).AppendLine();
|
||||
sb.AppendFormat("Finder filename: {0}", BB.finder_name).AppendLine();
|
||||
sb.AppendFormat("Debugger filename: {0}", BB.debug_name).AppendLine();
|
||||
sb.AppendFormat("Disassembler filename: {0}", BB.disasm_name).AppendLine();
|
||||
sb.AppendFormat("Startup screen filename: {0}", BB.stupscr_name).AppendLine();
|
||||
sb.AppendFormat("First program to execute at boot: {0}", BB.bootup_name).AppendLine();
|
||||
sb.AppendFormat("Clipboard filename: {0}", BB.clipbrd_name).AppendLine();
|
||||
sb.AppendFormat("Maximum opened files: {0}", BB.max_files*4).AppendLine();
|
||||
sb.AppendFormat("Event queue size: {0}", BB.queue_size).AppendLine();
|
||||
sb.AppendFormat("Heap size with 128KiB of RAM: {0} bytes", BB.heap_128k).AppendLine();
|
||||
sb.AppendFormat("Heap size with 256KiB of RAM: {0} bytes", BB.heap_256k).AppendLine();
|
||||
sb.AppendFormat("Heap size with 512KiB of RAM or more: {0} bytes", BB.heap_512k).AppendLine();
|
||||
}
|
||||
}
|
||||
else
|
||||
sb.AppendLine("Volume is not bootable.");
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
private struct HFS_MasterDirectoryBlock // Should be offset 0x0400 bytes in volume
|
||||
{
|
||||
public UInt16 drSigWord; // Signature, 0x4244
|
||||
public UInt32 drCrDate; // Volume creation date
|
||||
public UInt32 drLsMod; // Volume last modification date
|
||||
public UInt16 drAtrb; // Volume attributes
|
||||
public UInt16 drNmFls; // Files in root directory
|
||||
public UInt16 drVBMSt; // Start 512-byte sector of volume bitmap
|
||||
public UInt16 drAllocPtr; // Allocation block to begin next allocation
|
||||
public UInt16 drNmAlBlks; // Allocation blocks
|
||||
public UInt32 drAlBlkSiz; // Bytes per allocation block
|
||||
public UInt32 drClpSiz; // Bytes to allocate when extending a file
|
||||
public UInt16 drAlBlSt; // Start 512-byte sector of first allocation block
|
||||
public UInt32 drNxtCNID; // CNID for next file
|
||||
public UInt16 drFreeBks; // Free allocation blocks
|
||||
public byte[] drVN; // Volume name (28 bytes)
|
||||
public UInt32 drVolBkUp; // Volume last backup time
|
||||
public UInt16 drVSeqNum; // Volume backup sequence number
|
||||
public UInt32 drWrCnt; // Filesystem write count
|
||||
public UInt32 drXTClpSiz; // Bytes to allocate when extending the extents B-Tree
|
||||
public UInt32 drCTClpSiz; // Bytes to allocate when extending the catalog B-Tree
|
||||
public UInt16 drNmRtDirs; // Number of directories in root directory
|
||||
public UInt32 drFilCnt; // Number of files in the volume
|
||||
public UInt32 drDirCnt; // Number of directories in the volume
|
||||
public UInt32 drFndrInfo0; // finderInfo[0], CNID for bootable system's directory
|
||||
public UInt32 drFndrInfo1; // finderInfo[1], CNID of the directory containing the boot application
|
||||
public UInt32 drFndrInfo2; // finderInfo[2], CNID of the directory that should be opened on boot
|
||||
public UInt32 drFndrInfo3; // finderInfo[3], CNID for Mac OS 8 or 9 directory
|
||||
public UInt32 drFndrInfo4; // finderInfo[4], Reserved
|
||||
public UInt32 drFndrInfo5; // finderInfo[5], CNID for Mac OS X directory
|
||||
public UInt32 drFndrInfo6; // finderInfo[6], first part of Mac OS X volume ID
|
||||
public UInt32 drFndrInfo7; // finderInfo[7], second part of Mac OS X volume ID
|
||||
public UInt16 drEmbedSigWord; // Embedded volume signature, "H+" if HFS+ is embedded ignore following two fields if not
|
||||
public UInt16 xdrStABNt; // Starting block number of embedded HFS+ volume
|
||||
public UInt16 xdrNumABlks; // Allocation blocks used by embedded volume
|
||||
public UInt32 drXTFlSize; // Bytes in the extents B-Tree
|
||||
// 3 HFS extents following, 32 bits each
|
||||
public UInt32 drCTFlSize; // Bytes in the catalog B-Tree
|
||||
// 3 HFS extents following, 32 bits each
|
||||
}
|
||||
|
||||
private struct HFS_BootBlock // Should be offset 0x0000 bytes in volume
|
||||
{
|
||||
public UInt16 signature; // Signature, 0x4C4B if bootable
|
||||
public UInt32 branch; // Branch
|
||||
public byte boot_flags; // Boot block flags
|
||||
public byte boot_version; // Boot block version
|
||||
public Int16 sec_sv_pages; // Allocate secondary buffers
|
||||
public string system_name; // System file name (10 bytes)
|
||||
public string finder_name; // Finder file name (10 bytes)
|
||||
public string debug_name; // Debugger file name (10 bytes)
|
||||
public string disasm_name; // Disassembler file name (10 bytes)
|
||||
public string stupscr_name; // Startup screen file name (10 bytes)
|
||||
public string bootup_name; // First program to execute on boot (10 bytes)
|
||||
public string clipbrd_name; // Clipboard file name (10 bytes)
|
||||
public UInt16 max_files; // 1/4 of maximum opened at a time files
|
||||
public UInt16 queue_size; // Event queue size
|
||||
public UInt32 heap_128k; // Heap size on a Mac with 128KiB of RAM
|
||||
public UInt32 heap_256k; // Heap size on a Mac with 256KiB of RAM
|
||||
public UInt32 heap_512k; // Heap size on a Mac with 512KiB of RAM or more
|
||||
} // Follows boot code
|
||||
}
|
||||
}
|
||||
|
||||
259
FileSystemIDandChk/Plugins/AppleMFS.cs
Normal file
259
FileSystemIDandChk/Plugins/AppleMFS.cs
Normal file
@@ -0,0 +1,259 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using FileSystemIDandChk;
|
||||
|
||||
// Information from Inside Macintosh
|
||||
|
||||
namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
class AppleMFS : Plugin
|
||||
{
|
||||
private DateTime MFSDateDelta = new DateTime(1904, 01, 01, 00, 00, 00);
|
||||
|
||||
public AppleMFS(PluginBase Core)
|
||||
{
|
||||
base.Name = "Apple Macintosh File System";
|
||||
base.PluginUUID = new Guid("67591456-90fa-49bd-ac89-14ef750b8af3");
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream stream, long offset)
|
||||
{
|
||||
byte[] signature = new byte[2];
|
||||
ushort drSigWord;
|
||||
|
||||
stream.Seek(0x400 + offset, SeekOrigin.Begin);
|
||||
|
||||
stream.Read(signature, 0, 2);
|
||||
signature = Swapping.SwapTwoBytes(signature);
|
||||
|
||||
drSigWord = BitConverter.ToUInt16(signature, 0);
|
||||
|
||||
if(drSigWord == 0xD2D7)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream stream, long offset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
MFS_MasterDirectoryBlock MDB = new MFS_MasterDirectoryBlock();
|
||||
MFS_BootBlock BB = new MFS_BootBlock();
|
||||
|
||||
byte[] sixteen_bit = new byte[2];
|
||||
byte[] thirtytwo_bit = new byte[4];
|
||||
byte[] fifthteen_bytes = new byte[15];
|
||||
byte[] variable_size;
|
||||
|
||||
stream.Seek(0x400 + offset, SeekOrigin.Begin);
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
MDB.drSigWord = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
if(MDB.drSigWord != 0xD2D7)
|
||||
return;
|
||||
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drCrDate = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drLsBkUp = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
MDB.drAtrb = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
MDB.drNmFls = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
MDB.drDirSt = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
MDB.drBlLen = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
MDB.drNmAlBlks = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drAlBlkSiz = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drClpSiz = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
MDB.drAlBlSt = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
MDB.drNxtFNum = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
MDB.drFreeBks = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
MDB.drVNSiz = (byte)stream.ReadByte();
|
||||
variable_size = new byte[MDB.drVNSiz];
|
||||
stream.Read(variable_size, 0, MDB.drVNSiz);
|
||||
MDB.drVN = Encoding.ASCII.GetString(variable_size);
|
||||
|
||||
stream.Seek(0 + offset, SeekOrigin.Begin);
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
BB.signature = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
|
||||
if(BB.signature == 0x4C4B)
|
||||
{
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
BB.branch = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
BB.boot_flags = (byte)stream.ReadByte();
|
||||
BB.boot_version = (byte)stream.ReadByte();
|
||||
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
BB.sec_sv_pages = BitConverter.ToInt16(sixteen_bit, 0);
|
||||
|
||||
stream.Seek(1, SeekOrigin.Current);
|
||||
stream.Read(fifthteen_bytes, 0, 15);
|
||||
BB.system_name = Encoding.ASCII.GetString(fifthteen_bytes);
|
||||
stream.Seek(1, SeekOrigin.Current);
|
||||
stream.Read(fifthteen_bytes, 0, 15);
|
||||
BB.finder_name = Encoding.ASCII.GetString(fifthteen_bytes);
|
||||
stream.Seek(1, SeekOrigin.Current);
|
||||
stream.Read(fifthteen_bytes, 0, 15);
|
||||
BB.debug_name = Encoding.ASCII.GetString(fifthteen_bytes);
|
||||
stream.Seek(1, SeekOrigin.Current);
|
||||
stream.Read(fifthteen_bytes, 0, 15);
|
||||
BB.disasm_name = Encoding.ASCII.GetString(fifthteen_bytes);
|
||||
stream.Seek(1, SeekOrigin.Current);
|
||||
stream.Read(fifthteen_bytes, 0, 15);
|
||||
BB.stupscr_name = Encoding.ASCII.GetString(fifthteen_bytes);
|
||||
stream.Seek(1, SeekOrigin.Current);
|
||||
stream.Read(fifthteen_bytes, 0, 15);
|
||||
BB.bootup_name = Encoding.ASCII.GetString(fifthteen_bytes);
|
||||
stream.Seek(1, SeekOrigin.Current);
|
||||
stream.Read(fifthteen_bytes, 0, 15);
|
||||
BB.clipbrd_name = Encoding.ASCII.GetString(fifthteen_bytes);
|
||||
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
BB.max_files = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
stream.Read(sixteen_bit, 0, 2);
|
||||
sixteen_bit = Swapping.SwapTwoBytes(sixteen_bit);
|
||||
BB.queue_size = BitConverter.ToUInt16(sixteen_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
BB.heap_128k = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
BB.heap_256k = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
stream.Read(thirtytwo_bit, 0, 4);
|
||||
thirtytwo_bit = Swapping.SwapFourBytes(thirtytwo_bit);
|
||||
BB.heap_512k = BitConverter.ToUInt32(thirtytwo_bit, 0);
|
||||
}
|
||||
else
|
||||
BB.signature = 0x0000;
|
||||
|
||||
sb.AppendLine("Apple Macintosh File System");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("Master Directory Block:");
|
||||
sb.AppendFormat("Creation date: {0}", MFSDateDelta.AddTicks((long)(MDB.drCrDate*10000000))).AppendLine();
|
||||
sb.AppendFormat("Last backup date: {0}", MFSDateDelta.AddTicks((long)(MDB.drLsBkUp*10000000))).AppendLine();
|
||||
if((MDB.drAtrb & 0x80) == 0x80)
|
||||
sb.AppendLine("Volume is locked by hardware.");
|
||||
if((MDB.drAtrb & 0x8000) == 0x8000)
|
||||
sb.AppendLine("Volume is locked by software.");
|
||||
sb.AppendFormat("{0} files on volume", MDB.drNmFls).AppendLine();
|
||||
sb.AppendFormat("First directory block: {0}", MDB.drDirSt).AppendLine();
|
||||
sb.AppendFormat("{0} blocks in directory.", MDB.drBlLen).AppendLine();
|
||||
sb.AppendFormat("{0} volume allocation blocks.", MDB.drNmAlBlks).AppendLine();
|
||||
sb.AppendFormat("Size of allocation blocks: {0}", MDB.drAlBlkSiz).AppendLine();
|
||||
sb.AppendFormat("{0} bytes to allocate.", MDB.drClpSiz).AppendLine();
|
||||
sb.AppendFormat("{0} first allocation block.", MDB.drAlBlSt).AppendLine();
|
||||
sb.AppendFormat("Next unused file number: {0}", MDB.drNxtFNum).AppendLine();
|
||||
sb.AppendFormat("{0} unused allocation blocks.", MDB.drFreeBks).AppendLine();
|
||||
sb.AppendFormat("Volume name: {0}", MDB.drVN).AppendLine();
|
||||
|
||||
if(BB.signature == 0x4C4B)
|
||||
{
|
||||
sb.AppendLine("Volume is bootable.");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("Boot Block:");
|
||||
if((BB.boot_flags & 0x40) == 0x40)
|
||||
sb.AppendLine("Boot block should be executed.");
|
||||
if((BB.boot_flags & 0x80) == 0x80)
|
||||
{
|
||||
sb.AppendLine("Boot block is in new unknown format.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(BB.sec_sv_pages > 0)
|
||||
sb.AppendLine("Allocate secondary sound buffer at boot.");
|
||||
else if(BB.sec_sv_pages < 0)
|
||||
sb.AppendLine("Allocate secondary sound and video buffers at boot.");
|
||||
|
||||
sb.AppendFormat("System filename: {0}", BB.system_name).AppendLine();
|
||||
sb.AppendFormat("Finder filename: {0}", BB.finder_name).AppendLine();
|
||||
sb.AppendFormat("Debugger filename: {0}", BB.debug_name).AppendLine();
|
||||
sb.AppendFormat("Disassembler filename: {0}", BB.disasm_name).AppendLine();
|
||||
sb.AppendFormat("Startup screen filename: {0}", BB.stupscr_name).AppendLine();
|
||||
sb.AppendFormat("First program to execute at boot: {0}", BB.bootup_name).AppendLine();
|
||||
sb.AppendFormat("Clipboard filename: {0}", BB.clipbrd_name).AppendLine();
|
||||
sb.AppendFormat("Maximum opened files: {0}", BB.max_files*4).AppendLine();
|
||||
sb.AppendFormat("Event queue size: {0}", BB.queue_size).AppendLine();
|
||||
sb.AppendFormat("Heap size with 128KiB of RAM: {0} bytes", BB.heap_128k).AppendLine();
|
||||
sb.AppendFormat("Heap size with 256KiB of RAM: {0} bytes", BB.heap_256k).AppendLine();
|
||||
sb.AppendFormat("Heap size with 512KiB of RAM or more: {0} bytes", BB.heap_512k).AppendLine();
|
||||
}
|
||||
}
|
||||
else
|
||||
sb.AppendLine("Volume is not bootable.");
|
||||
|
||||
information = sb.ToString();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
private struct MFS_MasterDirectoryBlock // Should be offset 0x0400 bytes in volume
|
||||
{
|
||||
public UInt16 drSigWord; // Signature, 0xD2D7
|
||||
public UInt32 drCrDate; // Volume creation date
|
||||
public UInt32 drLsBkUp; // Volume last backup date
|
||||
public UInt16 drAtrb; // Volume attributes
|
||||
public UInt16 drNmFls; // Volume number of files
|
||||
public UInt16 drDirSt; // First directory block
|
||||
public UInt16 drBlLen; // Length of directory in blocks
|
||||
public UInt16 drNmAlBlks; // Volume allocation blocks
|
||||
public UInt32 drAlBlkSiz; // Size of allocation blocks
|
||||
public UInt32 drClpSiz; // Number of bytes to allocate
|
||||
public UInt16 drAlBlSt; // First allocation block in block map
|
||||
public UInt32 drNxtFNum; // Next unused file number
|
||||
public UInt16 drFreeBks; // Number of unused allocation blocks
|
||||
public byte drVNSiz; // Length of volume name
|
||||
public string drVN; // Characters of volume name
|
||||
}
|
||||
|
||||
private struct MFS_BootBlock // Should be offset 0x0000 bytes in volume
|
||||
{
|
||||
public UInt16 signature; // Signature, 0x4C4B if bootable
|
||||
public UInt32 branch; // Branch
|
||||
public byte boot_flags; // Boot block flags
|
||||
public byte boot_version; // Boot block version
|
||||
public short sec_sv_pages; // Allocate secondary buffers
|
||||
public string system_name; // System file name (10 bytes)
|
||||
public string finder_name; // Finder file name (10 bytes)
|
||||
public string debug_name; // Debugger file name (10 bytes)
|
||||
public string disasm_name; // Disassembler file name (10 bytes)
|
||||
public string stupscr_name; // Startup screen file name (10 bytes)
|
||||
public string bootup_name; // First program to execute on boot (10 bytes)
|
||||
public string clipbrd_name; // Clipboard file name (10 bytes)
|
||||
public UInt16 max_files; // 1/4 of maximum opened at a time files
|
||||
public UInt16 queue_size; // Event queue size
|
||||
public UInt32 heap_128k; // Heap size on a Mac with 128KiB of RAM
|
||||
public UInt32 heap_256k; // Heap size on a Mac with 256KiB of RAM
|
||||
public UInt32 heap_512k; // Heap size on a Mac with 512KiB of RAM or more
|
||||
} // Follows boot code
|
||||
}
|
||||
}
|
||||
|
||||
263
FileSystemIDandChk/Plugins/FAT.cs
Normal file
263
FileSystemIDandChk/Plugins/FAT.cs
Normal file
@@ -0,0 +1,263 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using FileSystemIDandChk;
|
||||
|
||||
// Information from Inside Macintosh
|
||||
|
||||
namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
class FAT : Plugin
|
||||
{
|
||||
public FAT(PluginBase Core)
|
||||
{
|
||||
base.Name = "Microsoft File Allocation Table";
|
||||
base.PluginUUID = new Guid("67591456-90fa-49bd-ac89-14ef750b8af3");
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream stream, long offset)
|
||||
{
|
||||
byte media_descriptor; // Not present on DOS <= 3, present on TOS but != of first FAT entry
|
||||
byte[] fat32_signature = new byte[8]; // "FAT32 "
|
||||
byte[] first_fat_entry_b = new byte[4]; // No matter FAT size we read 2 bytes for checking
|
||||
ulong first_fat_entry;
|
||||
|
||||
stream.Seek(0x15 + offset, SeekOrigin.Begin); // Media Descriptor if present is in 0x15
|
||||
media_descriptor = (byte)stream.ReadByte();
|
||||
stream.Seek(0x52 + offset, SeekOrigin.Begin); // FAT32 signature, if present, is in 0x52
|
||||
stream.Read(fat32_signature, 0, 8);
|
||||
stream.Seek(0x200 + offset, SeekOrigin.Begin); // First FAT entry is always at 0x200 in pre-FAT32
|
||||
stream.Read(first_fat_entry_b, 0, 4);
|
||||
|
||||
first_fat_entry = BitConverter.ToUInt32(first_fat_entry_b, 0); // Easier to manage
|
||||
|
||||
// Let's start the fun
|
||||
if(Encoding.ASCII.GetString(fat32_signature) == "FAT32 ")
|
||||
return true; // Seems easy, check reading
|
||||
|
||||
if((first_fat_entry & 0xFFFFFFF0) == 0xFFFFFFF0) // Seems to be FAT16
|
||||
{
|
||||
if((first_fat_entry & 0xFF) == media_descriptor)
|
||||
return true; // It MUST be FAT16, or... maybe not :S
|
||||
}
|
||||
else if((first_fat_entry & 0x00FFFFF0) == 0x00FFFFF0)
|
||||
{
|
||||
//if((first_fat_entry & 0xFF) == media_descriptor) // Pre DOS<4 does not implement this, TOS does and is !=
|
||||
return true; // It MUST be FAT12, or... maybe not :S
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream stream, long offset, out string information)
|
||||
{
|
||||
information = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
byte media_descriptor; // Not present on DOS <= 3, present on TOS but != of first FAT entry
|
||||
byte[] fat32_signature = new byte[8]; // "FAT32 "
|
||||
byte[] first_fat_entry_b = new byte[4]; // No matter FAT size we read 2 bytes for checking
|
||||
ulong first_fat_entry;
|
||||
|
||||
stream.Seek(0x15 + offset, SeekOrigin.Begin); // Media Descriptor if present is in 0x15
|
||||
media_descriptor =(byte) stream.ReadByte();
|
||||
stream.Seek(0x52 + offset, SeekOrigin.Begin); // FAT32 signature, if present, is in 0x52
|
||||
stream.Read(fat32_signature, 0, 8);
|
||||
stream.Seek(0x200 + offset, SeekOrigin.Begin); // First FAT entry is always at 0x200 in pre-FAT32
|
||||
stream.Read(first_fat_entry_b, 0, 4);
|
||||
|
||||
first_fat_entry = BitConverter.ToUInt32(first_fat_entry_b, 0); // Easier to manage
|
||||
|
||||
// Let's start the fun
|
||||
if(Encoding.ASCII.GetString(fat32_signature) == "FAT32 ")
|
||||
sb.AppendLine("Microsoft FAT32"); // Seems easy, check reading
|
||||
else if((first_fat_entry & 0xFFFFFFF0) == 0xFFFFFFF0) // Seems to be FAT16
|
||||
{
|
||||
if((first_fat_entry & 0xFF) == media_descriptor)
|
||||
sb.AppendLine("Microsoft FAT16"); // It MUST be FAT16, or... maybe not :S
|
||||
}
|
||||
else if((first_fat_entry & 0x00FFFFF0) == 0x00FFFFF0)
|
||||
{
|
||||
//if((first_fat_entry & 0xFF) == media_descriptor) // Pre DOS<4 does not implement this, TOS does and is !=
|
||||
sb.AppendLine("Microsoft FAT12"); // It MUST be FAT12, or... maybe not :S
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
BIOSParameterBlock BPB = new BIOSParameterBlock();
|
||||
ExtendedParameterBlock EPB = new ExtendedParameterBlock();
|
||||
FAT32ParameterBlock FAT32PB = new FAT32ParameterBlock();
|
||||
|
||||
byte[] eight_bytes = new byte[8];
|
||||
byte[] eleven_bytes = new byte[11];
|
||||
byte[] sixteen_bits = new byte[2];
|
||||
byte[] thirtytwo_bits = new byte[4];
|
||||
|
||||
stream.Seek(3 + offset, SeekOrigin.Begin);
|
||||
stream.Read(eight_bytes, 0, 8);
|
||||
BPB.OEMName = Encoding.ASCII.GetString(eight_bytes);
|
||||
stream.Read(sixteen_bits, 0, 2);
|
||||
BPB.bps = BitConverter.ToUInt16(sixteen_bits, 0);
|
||||
BPB.spc = (byte)stream.ReadByte();
|
||||
stream.Read(sixteen_bits, 0, 2);
|
||||
BPB.rsectors = BitConverter.ToUInt16(sixteen_bits, 0);
|
||||
BPB.fats_no = (byte)stream.ReadByte();
|
||||
stream.Read(sixteen_bits, 0, 2);
|
||||
BPB.root_ent = BitConverter.ToUInt16(sixteen_bits, 0);
|
||||
stream.Read(sixteen_bits, 0, 2);
|
||||
BPB.sectors = BitConverter.ToUInt16(sixteen_bits, 0);
|
||||
BPB.media = (byte)stream.ReadByte();
|
||||
stream.Read(sixteen_bits, 0, 2);
|
||||
BPB.spfat = BitConverter.ToUInt16(sixteen_bits, 0);
|
||||
stream.Read(sixteen_bits, 0, 2);
|
||||
BPB.sptrk = BitConverter.ToUInt16(sixteen_bits, 0);
|
||||
stream.Read(sixteen_bits, 0, 2);
|
||||
BPB.heads = BitConverter.ToUInt16(sixteen_bits, 0);
|
||||
stream.Read(thirtytwo_bits, 0, 4);
|
||||
BPB.hsectors = BitConverter.ToUInt32(thirtytwo_bits, 0);
|
||||
stream.Read(thirtytwo_bits, 0, 4);
|
||||
BPB.big_sectors = BitConverter.ToUInt32(thirtytwo_bits, 0);
|
||||
|
||||
if(Encoding.ASCII.GetString(fat32_signature) == "FAT32 ")
|
||||
{
|
||||
stream.Read(thirtytwo_bits, 0, 4);
|
||||
FAT32PB.spfat = BitConverter.ToUInt32(thirtytwo_bits, 0);
|
||||
stream.Read(sixteen_bits, 0, 2);
|
||||
FAT32PB.fat_flags = BitConverter.ToUInt16(sixteen_bits, 0);
|
||||
stream.Read(sixteen_bits, 0, 2);
|
||||
FAT32PB.version = BitConverter.ToUInt16(sixteen_bits, 0);
|
||||
stream.Read(thirtytwo_bits, 0, 4);
|
||||
FAT32PB.root_cluster = BitConverter.ToUInt32(thirtytwo_bits, 0);
|
||||
stream.Read(sixteen_bits, 0, 2);
|
||||
FAT32PB.fsinfo_sector = BitConverter.ToUInt16(sixteen_bits, 0);
|
||||
stream.Read(sixteen_bits, 0, 2);
|
||||
FAT32PB.backup_sector = BitConverter.ToUInt16(sixteen_bits, 0);
|
||||
FAT32PB.drive_no = (byte)stream.ReadByte();
|
||||
FAT32PB.nt_flags = (byte)stream.ReadByte();
|
||||
FAT32PB.signature = (byte)stream.ReadByte();
|
||||
stream.Read(thirtytwo_bits, 0, 4);
|
||||
FAT32PB.serial_no = BitConverter.ToUInt32(thirtytwo_bits, 0);
|
||||
stream.Read(eleven_bytes, 0, 11);
|
||||
FAT32PB.volume_label = Encoding.ASCII.GetString(eleven_bytes);
|
||||
stream.Read(eight_bytes, 0, 8);
|
||||
FAT32PB.fs_type = Encoding.ASCII.GetString(eight_bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
EPB.drive_no = (byte)stream.ReadByte();
|
||||
EPB.nt_flags = (byte)stream.ReadByte();
|
||||
EPB.signature = (byte)stream.ReadByte();
|
||||
stream.Read(thirtytwo_bits, 0, 4);
|
||||
EPB.serial_no = BitConverter.ToUInt32(thirtytwo_bits, 0);
|
||||
stream.Read(eleven_bytes, 0, 11);
|
||||
EPB.volume_label = Encoding.ASCII.GetString(eleven_bytes);
|
||||
stream.Read(eight_bytes, 0, 8);
|
||||
EPB.fs_type = Encoding.ASCII.GetString(eight_bytes);
|
||||
}
|
||||
|
||||
sb.AppendFormat("OEM Name: {0}", BPB.OEMName).AppendLine();
|
||||
sb.AppendFormat("{0} bytes per sector.", BPB.bps).AppendLine();
|
||||
sb.AppendFormat("{0} sectors per cluster.", BPB.spc).AppendLine();
|
||||
sb.AppendFormat("{0} sectors reserved between BPB and FAT.", BPB.rsectors).AppendLine();
|
||||
sb.AppendFormat("{0} FATs.", BPB.fats_no).AppendLine();
|
||||
sb.AppendFormat("{0} entires on root directory.", BPB.root_ent).AppendLine();
|
||||
if(BPB.sectors==0)
|
||||
sb.AppendFormat("{0} sectors on volume.", BPB.big_sectors).AppendLine();
|
||||
else
|
||||
sb.AppendFormat("{0} sectors on volume.", BPB.sectors).AppendLine();
|
||||
if((BPB.media & 0xF0) == 0xF0)
|
||||
sb.AppendFormat("Media format: 0x{0:X2}", BPB.media).AppendLine();
|
||||
if(Encoding.ASCII.GetString(fat32_signature) == "FAT32 ")
|
||||
sb.AppendFormat("{0} sectors per FAT.", FAT32PB.spfat).AppendLine();
|
||||
else
|
||||
sb.AppendFormat("{0} sectors per FAT.", BPB.spfat).AppendLine();
|
||||
sb.AppendFormat("{0} sectors per track.", BPB.sptrk).AppendLine();
|
||||
sb.AppendFormat("{0} heads.", BPB.heads).AppendLine();
|
||||
sb.AppendFormat("{0} hidden sectors before BPB.", BPB.hsectors).AppendLine();
|
||||
|
||||
if(Encoding.ASCII.GetString(fat32_signature) == "FAT32 ")
|
||||
{
|
||||
sb.AppendFormat("Cluster of root directory: {0}", FAT32PB.root_cluster).AppendLine();
|
||||
sb.AppendFormat("Sector of FSINFO structure: {0}", FAT32PB.fsinfo_sector).AppendLine();
|
||||
sb.AppendFormat("Sector of backup FAT32 parameter block: {0}", FAT32PB.backup_sector).AppendLine();
|
||||
sb.AppendFormat("Drive number: 0x{0:X2}", FAT32PB.drive_no).AppendLine();
|
||||
sb.AppendFormat("Volume Serial Number: 0x{0:X8}", FAT32PB.serial_no).AppendLine();
|
||||
if((FAT32PB.nt_flags & 0x01) == 0x01)
|
||||
{
|
||||
sb.AppendLine("Volume should be checked on next mount.");
|
||||
if((EPB.nt_flags & 0x02) == 0x02)
|
||||
sb.AppendLine("Disk surface should be checked also.");
|
||||
}
|
||||
|
||||
sb.AppendFormat("Volume label: {0}", EPB.volume_label).AppendLine();
|
||||
sb.AppendFormat("Filesystem type: {0}", EPB.fs_type).AppendLine();
|
||||
}
|
||||
else if(EPB.signature == 0x28 || EPB.signature == 0x29)
|
||||
{
|
||||
sb.AppendFormat("Drive number: 0x{0:X2}", EPB.drive_no).AppendLine();
|
||||
sb.AppendFormat("Volume Serial Number: 0x{0:X8}", EPB.serial_no).AppendLine();
|
||||
if(EPB.signature==0x29)
|
||||
{
|
||||
if((EPB.nt_flags & 0x01) == 0x01)
|
||||
{
|
||||
sb.AppendLine("Volume should be checked on next mount.");
|
||||
if((EPB.nt_flags & 0x02) == 0x02)
|
||||
sb.AppendLine("Disk surface should be checked also.");
|
||||
}
|
||||
|
||||
sb.AppendFormat("Volume label: {0}", EPB.volume_label).AppendLine();
|
||||
sb.AppendFormat("Filesystem type: {0}", EPB.fs_type).AppendLine();
|
||||
}
|
||||
}
|
||||
|
||||
information = sb.ToString();
|
||||
}
|
||||
|
||||
public struct BIOSParameterBlock
|
||||
{
|
||||
public string OEMName; // OEM Name, 8 bytes, space-padded
|
||||
public UInt16 bps; // Bytes per sector
|
||||
public byte spc; // Sectors per cluster
|
||||
public UInt16 rsectors; // Reserved sectors between BPB and FAT
|
||||
public byte fats_no; // Number of FATs
|
||||
public UInt16 root_ent; // Number of entries on root directory
|
||||
public UInt16 sectors; // Sectors in volume
|
||||
public byte media; // Media descriptor
|
||||
public UInt16 spfat; // Sectors per FAT
|
||||
public UInt16 sptrk; // Sectors per track
|
||||
public UInt16 heads; // Heads
|
||||
public UInt32 hsectors; // Hidden sectors before BPB
|
||||
public UInt32 big_sectors; // Sectors in volume if > 65535
|
||||
}
|
||||
|
||||
public struct ExtendedParameterBlock
|
||||
{
|
||||
public byte drive_no; // Drive number
|
||||
public byte nt_flags; // Volume flags if NT (must be 0x29 signature)
|
||||
public byte signature; // EPB signature, 0x28 or 0x29
|
||||
public UInt32 serial_no; // Volume serial number
|
||||
/* Present only if signature == 0x29 */
|
||||
public string volume_label; // Volume label, 11 bytes, space-padded
|
||||
public string fs_type; // Filesystem type, 8 bytes, space-padded
|
||||
}
|
||||
|
||||
public struct FAT32ParameterBlock
|
||||
{
|
||||
public UInt32 spfat; // Sectors per FAT
|
||||
public UInt16 fat_flags; // FAT flags
|
||||
public UInt16 version; // FAT32 version
|
||||
public UInt32 root_cluster; // Cluster of root directory
|
||||
public UInt16 fsinfo_sector; // Sector of FSINFO structure
|
||||
public UInt16 backup_sector; // Secfor of FAT32PB bacup
|
||||
byte[] reserved; // 12 reserved bytes
|
||||
public byte drive_no; // Drive number
|
||||
public byte nt_flags; // Volume flags
|
||||
public byte signature; // FAT32PB signature, should be 0x29
|
||||
public UInt32 serial_no; // Volume serial number
|
||||
public string volume_label; // Volume label, 11 bytes, space-padded
|
||||
public string fs_type; // Filesystem type, 8 bytes, space-padded, must be "FAT32 "
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
927
FileSystemIDandChk/Plugins/ISO9660.cs
Normal file
927
FileSystemIDandChk/Plugins/ISO9660.cs
Normal file
@@ -0,0 +1,927 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
using FileSystemIDandChk;
|
||||
|
||||
// This is coded following ECMA-119.
|
||||
// TODO: Differentiate ISO Level 1, 2, 3 and ISO 9660:1999
|
||||
// TODO: Apple extensiones, requires XA or advance RR interpretation.
|
||||
|
||||
namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
class ISO9660Plugin : Plugin
|
||||
{
|
||||
public ISO9660Plugin(PluginBase Core)
|
||||
{
|
||||
base.Name = "ISO9660 Filesystem";
|
||||
base.PluginUUID = new Guid("d812f4d3-c357-400d-90fd-3b22ef786aa8");
|
||||
}
|
||||
|
||||
private struct DecodedVolumeDescriptor
|
||||
{
|
||||
public string SystemIdentifier;
|
||||
public string VolumeIdentifier;
|
||||
public string VolumeSetIdentifier;
|
||||
public string PublisherIdentifier;
|
||||
public string DataPreparerIdentifier;
|
||||
public string ApplicationIdentifier;
|
||||
public DateTime CreationTime;
|
||||
public bool HasModificationTime;
|
||||
public DateTime ModificationTime;
|
||||
public bool HasExpirationTime;
|
||||
public DateTime ExpirationTime;
|
||||
public bool HasEffectiveTime;
|
||||
public DateTime EffectiveTime;
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream fileStream, long offset)
|
||||
{
|
||||
byte VDType;
|
||||
|
||||
// ISO9660 Primary Volume Descriptor starts at 32768, so that's minimal size.
|
||||
if (fileStream.Length < 32768)
|
||||
return false;
|
||||
|
||||
// Seek to Volume Descriptor
|
||||
fileStream.Seek(32768 + offset, SeekOrigin.Begin);
|
||||
|
||||
VDType = (byte)fileStream.ReadByte();
|
||||
byte[] VDMagic = new byte[5];
|
||||
|
||||
if (VDType == 255) // Supposedly we are in the PVD.
|
||||
return false;
|
||||
|
||||
if (fileStream.Read(VDMagic, 0, 5) != 5)
|
||||
return false; // Something bad happened
|
||||
|
||||
if (Encoding.ASCII.GetString(VDMagic) != "CD001") // Recognized, it is an ISO9660, now check for rest of data.
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream fileStream, long offset, out string information)
|
||||
{
|
||||
information = "";
|
||||
StringBuilder ISOMetadata = new StringBuilder();
|
||||
bool Joliet = false;
|
||||
bool Bootable = false;
|
||||
bool RockRidge = false;
|
||||
byte VDType; // Volume Descriptor Type, should be 1 or 2.
|
||||
byte[] VDMagic = new byte[5]; // Volume Descriptor magic "CD001"
|
||||
byte[] VDSysId = new byte[32]; // System Identifier
|
||||
byte[] VDVolId = new byte[32]; // Volume Identifier
|
||||
byte[] VDVolSetId = new byte[128]; // Volume Set Identifier
|
||||
byte[] VDPubId = new byte[128]; // Publisher Identifier
|
||||
byte[] VDDataPrepId = new byte[128]; // Data Preparer Identifier
|
||||
byte[] VDAppId = new byte[128]; // Application Identifier
|
||||
byte[] VCTime = new byte[17]; // Volume Creation Date and Time
|
||||
byte[] VMTime = new byte[17]; // Volume Modification Date and Time
|
||||
byte[] VXTime = new byte[17]; // Volume Expiration Date and Time
|
||||
byte[] VETime = new byte[17]; // Volume Effective Date and Time
|
||||
|
||||
byte[] JolietMagic = new byte[3];
|
||||
byte[] JolietSysId = new byte[32]; // System Identifier
|
||||
byte[] JolietVolId = new byte[32]; // Volume Identifier
|
||||
byte[] JolietVolSetId = new byte[128]; // Volume Set Identifier
|
||||
byte[] JolietPubId = new byte[128]; // Publisher Identifier
|
||||
byte[] JolietDataPrepId = new byte[128]; // Data Preparer Identifier
|
||||
byte[] JolietAppId = new byte[128]; // Application Identifier
|
||||
byte[] JolietCTime = new byte[17]; // Volume Creation Date and Time
|
||||
byte[] JolietMTime = new byte[17]; // Volume Modification Date and Time
|
||||
byte[] JolietXTime = new byte[17]; // Volume Expiration Date and Time
|
||||
byte[] JolietETime = new byte[17]; // Volume Effective Date and Time
|
||||
|
||||
byte[] BootSysId = new byte[32];
|
||||
string BootSpec = "";
|
||||
|
||||
byte[] VDPathTableStart = new byte[4];
|
||||
byte[] RootDirectoryLocation = new byte[4];
|
||||
|
||||
fileStream.Seek(0 + offset, SeekOrigin.Begin);
|
||||
|
||||
// ISO9660 Primary Volume Descriptor starts at 32768, so that's minimal size.
|
||||
if (fileStream.Length < 32768)
|
||||
return;
|
||||
|
||||
int counter = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
// Seek to Volume Descriptor
|
||||
fileStream.Seek(32768+(2048*counter) + offset, SeekOrigin.Begin);
|
||||
|
||||
VDType = (byte)fileStream.ReadByte();
|
||||
|
||||
if (VDType == 255) // Supposedly we are in the PVD.
|
||||
{
|
||||
if (counter == 0)
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
if (fileStream.Read(VDMagic, 0, 5) != 5)
|
||||
{
|
||||
if (counter == 0)
|
||||
return; // Something bad happened
|
||||
break;
|
||||
}
|
||||
|
||||
if (Encoding.ASCII.GetString(VDMagic) != "CD001") // Recognized, it is an ISO9660, now check for rest of data.
|
||||
{
|
||||
if (counter == 0)
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(VDType)
|
||||
{
|
||||
case 0: // TODO
|
||||
{
|
||||
Bootable = true;
|
||||
BootSpec = "Unknown";
|
||||
|
||||
// Seek to boot system identifier
|
||||
fileStream.Seek(32775 + (2048 * counter) + offset, SeekOrigin.Begin);
|
||||
|
||||
if (fileStream.Read(BootSysId, 0, 32) != 32)
|
||||
break; // Something bad happened
|
||||
|
||||
if (Encoding.ASCII.GetString(BootSysId).Substring(0, 23) == "EL TORITO SPECIFICATION")
|
||||
BootSpec = "El Torito";
|
||||
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
// Seek to first identifiers
|
||||
fileStream.Seek(32776 + (2048 * counter) + offset, SeekOrigin.Begin);
|
||||
|
||||
if (fileStream.Read(VDSysId, 0, 32) != 32)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(VDVolId, 0, 32) != 32)
|
||||
break; // Something bad happened
|
||||
|
||||
// Get path table start
|
||||
fileStream.Seek(32908 + (2048 * counter) + offset, SeekOrigin.Begin);
|
||||
|
||||
if (fileStream.Read(VDPathTableStart, 0, 4) != 4)
|
||||
break; // Something bad happened
|
||||
|
||||
// Seek to next identifiers
|
||||
fileStream.Seek(32958 + (2048 * counter) + offset, SeekOrigin.Begin);
|
||||
|
||||
if (fileStream.Read(VDVolSetId, 0, 128) != 128)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(VDPubId, 0, 128) != 128)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(VDDataPrepId, 0, 128) != 128)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(VDAppId, 0, 128) != 128)
|
||||
break; // Something bad happened
|
||||
|
||||
// Seek to dates
|
||||
fileStream.Seek(33581 + (2048 * counter) + offset, SeekOrigin.Begin);
|
||||
|
||||
if (fileStream.Read(VCTime, 0, 17) != 17)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(VMTime, 0, 17) != 17)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(VXTime, 0, 17) != 17)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(VETime, 0, 17) != 17)
|
||||
break; // Something bad happened
|
||||
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
// Check if this is Joliet
|
||||
fileStream.Seek(32856 + (2048 * counter) + offset, SeekOrigin.Begin);
|
||||
|
||||
if (fileStream.Read(JolietMagic, 0, 3) != 3)
|
||||
{
|
||||
break; // Something bad happened
|
||||
}
|
||||
|
||||
if (JolietMagic[0] == '%' && JolietMagic[1] == '/')
|
||||
{
|
||||
if (JolietMagic[2] == '@' || JolietMagic[2] == 'C' || JolietMagic[2] == 'E')
|
||||
{
|
||||
Joliet = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
||||
// Seek to first identifiers
|
||||
fileStream.Seek(32776 + (2048 * counter) + offset, SeekOrigin.Begin);
|
||||
|
||||
if (fileStream.Read(JolietSysId, 0, 32) != 32)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(JolietVolId, 0, 32) != 32)
|
||||
break; // Something bad happened
|
||||
|
||||
// Seek to next identifiers
|
||||
fileStream.Seek(32958 + (2048 * counter) + offset, SeekOrigin.Begin);
|
||||
|
||||
if (fileStream.Read(JolietVolSetId, 0, 128) != 128)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(JolietPubId, 0, 128) != 128)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(JolietDataPrepId, 0, 128) != 128)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(JolietAppId, 0, 128) != 128)
|
||||
break; // Something bad happened
|
||||
|
||||
// Seek to dates
|
||||
fileStream.Seek(33581 + (2048 * counter) + offset, SeekOrigin.Begin);
|
||||
|
||||
if (fileStream.Read(JolietCTime, 0, 17) != 17)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(JolietMTime, 0, 17) != 17)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(JolietXTime, 0, 17) != 17)
|
||||
break; // Something bad happened
|
||||
if (fileStream.Read(JolietETime, 0, 17) != 17)
|
||||
break; // Something bad happened
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
counter++;
|
||||
}
|
||||
|
||||
DecodedVolumeDescriptor decodedVD = new DecodedVolumeDescriptor();
|
||||
if(!Joliet)
|
||||
decodedVD = DecodeVolumeDescriptor(VDSysId, VDVolId, VDVolSetId, VDPubId, VDDataPrepId, VDAppId, VCTime, VMTime, VXTime, VETime);
|
||||
else
|
||||
decodedVD = DecodeJolietDescriptor(JolietSysId, JolietVolId, JolietVolSetId, JolietPubId, JolietDataPrepId, JolietAppId, JolietCTime, JolietMTime, JolietXTime, JolietETime);
|
||||
|
||||
int i = BitConverter.ToInt32(VDPathTableStart, 0);
|
||||
|
||||
fileStream.Seek((i * 2048)+2 + offset, SeekOrigin.Begin); // Seek to first path table location field
|
||||
|
||||
// Check for Rock Ridge
|
||||
if (fileStream.Read(RootDirectoryLocation, 0, 4) == 4)
|
||||
{
|
||||
fileStream.Seek((BitConverter.ToInt32(RootDirectoryLocation,0) * 2048)+34 + offset, SeekOrigin.Begin); // Seek to root directory, first entry, system use field
|
||||
|
||||
byte[] SUSPMagic = new byte[2];
|
||||
byte[] RRMagic = new byte[2];
|
||||
|
||||
fileStream.Read(SUSPMagic, 0, 2);
|
||||
if (Encoding.ASCII.GetString(SUSPMagic) == "SP")
|
||||
{
|
||||
fileStream.Seek(5, SeekOrigin.Current); // Seek for rock ridge magic
|
||||
fileStream.Read(RRMagic, 0, 2);
|
||||
if (Encoding.ASCII.GetString(RRMagic) == "RR")
|
||||
{
|
||||
RockRidge = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region SEGA IP.BIN Read and decoding
|
||||
|
||||
bool SegaCD = false;
|
||||
bool Saturn = false;
|
||||
bool Dreamcast = false;
|
||||
StringBuilder IPBinInformation = new StringBuilder();
|
||||
|
||||
byte[] SegaHardwareID = new byte[16];
|
||||
fileStream.Seek(0 + offset, SeekOrigin.Begin); // Seek to start (again)
|
||||
fileStream.Read(SegaHardwareID, 0, 16);
|
||||
|
||||
switch (Encoding.ASCII.GetString(SegaHardwareID))
|
||||
{
|
||||
case "SEGADISCSYSTEM ":
|
||||
case "SEGADATADISC ":
|
||||
case "SEGAOS ":
|
||||
{
|
||||
SegaCD = true; // Ok, this contains SegaCD IP.BIN
|
||||
|
||||
IPBinInformation.AppendLine("--------------------------------");
|
||||
IPBinInformation.AppendLine("SEGA IP.BIN INFORMATION:");
|
||||
IPBinInformation.AppendLine("--------------------------------");
|
||||
|
||||
// Definitions following
|
||||
byte[] volume_name = new byte[11]; // Varies
|
||||
byte[] spare_space1 = new byte[1]; // 0x00
|
||||
byte[] volume_version = new byte[2]; // Volume version in BCD. <100 = Prerelease.
|
||||
byte[] volume_type = new byte[2]; // Bit 0 = 1 => CD-ROM. Rest should be 0.
|
||||
byte[] system_name = new byte[11]; // Unknown, varies!
|
||||
byte[] spare_space2 = new byte[1]; // 0x00
|
||||
byte[] system_version = new byte[2]; // Should be 1
|
||||
byte[] spare_space3 = new byte[2]; // 0x0000
|
||||
byte[] ip_address = new byte[4]; // Initial program address
|
||||
byte[] ip_loadsize = new byte[4]; // Load size of initial program
|
||||
byte[] ip_entry_address = new byte[4]; // Initial program entry address
|
||||
byte[] ip_work_ram_size = new byte[4]; // Initial program work RAM size in bytes
|
||||
byte[] sp_address = new byte[4]; // System program address
|
||||
byte[] sp_loadsize = new byte[4]; // Load size of system program
|
||||
byte[] sp_entry_address = new byte[4]; // System program entry address
|
||||
byte[] sp_work_ram_size = new byte[4]; // System program work RAM size in bytes
|
||||
byte[] release_date = new byte[8]; // MMDDYYYY
|
||||
byte[] unknown1 = new byte[7]; // Seems to be all 0x20s
|
||||
byte[] spare_space4 = new byte[1]; // 0x00 ?
|
||||
byte[] system_reserved = new byte[160]; // System Reserved Area
|
||||
byte[] hardware_id = new byte[16]; // Hardware ID
|
||||
byte[] copyright = new byte[3]; // "(C)" -- Can be the developer code directly!, if that is the code release date will be displaced
|
||||
byte[] developer_code = new byte[5]; // "SEGA" or "T-xx"
|
||||
byte[] unknown2 = new byte[1]; // Seems to be part of developer code, need to get a SEGA disc to check
|
||||
byte[] release_date2 = new byte[8]; // Another release date, this with month in letters?
|
||||
byte[] domestic_title = new byte[48]; // Domestic version of the game title
|
||||
byte[] overseas_title = new byte[48]; // Overseas version of the game title
|
||||
byte[] application_type = new byte[2]; // Application type
|
||||
byte[] space_space5 = new byte[1]; // 0x20
|
||||
byte[] product_code = new byte[13]; // Official product code
|
||||
byte[] peripherals = new byte[16]; // Supported peripherals, see above
|
||||
byte[] spare_space6 = new byte[16]; // 0x20
|
||||
byte[] spare_space7 = new byte[64]; // Inside here should be modem information, but I need to get a modem-enabled game
|
||||
byte[] region_codes = new byte[16]; // Region codes, space-filled
|
||||
//Reading all data
|
||||
fileStream.Read(volume_name, 0, 11); // Varies
|
||||
fileStream.Read(spare_space1, 0, 1); // 0x00
|
||||
fileStream.Read(volume_version, 0, 2); // Volume version in BCD. <100 = Prerelease.
|
||||
fileStream.Read(volume_type, 0, 2); // Bit 0 = 1 => CD-ROM. Rest should be 0.
|
||||
fileStream.Read(system_name, 0, 11); // Unknown, varies!
|
||||
fileStream.Read(spare_space2, 0, 1); // 0x00
|
||||
fileStream.Read(system_version, 0, 2); // Should be 1
|
||||
fileStream.Read(spare_space3, 0, 2); // 0x0000
|
||||
fileStream.Read(ip_address, 0, 4); // Initial program address
|
||||
fileStream.Read(ip_loadsize, 0, 4); // Load size of initial program
|
||||
fileStream.Read(ip_entry_address, 0, 4); // Initial program entry address
|
||||
fileStream.Read(ip_work_ram_size, 0, 4); // Initial program work RAM size in bytes
|
||||
fileStream.Read(sp_address, 0, 4); // System program address
|
||||
fileStream.Read(sp_loadsize, 0, 4); // Load size of system program
|
||||
fileStream.Read(sp_entry_address, 0, 4); // System program entry address
|
||||
fileStream.Read(sp_work_ram_size, 0, 4); // System program work RAM size in bytes
|
||||
fileStream.Read(release_date, 0, 8); // MMDDYYYY
|
||||
fileStream.Read(unknown1, 0, 7); // Seems to be all 0x20s
|
||||
fileStream.Read(spare_space4, 0, 1); // 0x00 ?
|
||||
fileStream.Read(system_reserved, 0, 160); // System Reserved Area
|
||||
fileStream.Read(hardware_id, 0, 16); // Hardware ID
|
||||
fileStream.Read(copyright, 0, 3); // "(C)" -- Can be the developer code directly!, if that is the code release date will be displaced
|
||||
if (Encoding.ASCII.GetString(copyright) != "(C)")
|
||||
fileStream.Seek(-3, SeekOrigin.Current);
|
||||
fileStream.Read(developer_code, 0, 5); // "SEGA" or "T-xx"
|
||||
if (Encoding.ASCII.GetString(copyright) != "(C)")
|
||||
fileStream.Seek(1, SeekOrigin.Current);
|
||||
fileStream.Read(release_date2, 0, 8); // Another release date, this with month in letters?
|
||||
if (Encoding.ASCII.GetString(copyright) != "(C)")
|
||||
fileStream.Seek(2, SeekOrigin.Current);
|
||||
fileStream.Read(domestic_title, 0, 48); // Domestic version of the game title
|
||||
fileStream.Read(overseas_title, 0, 48); // Overseas version of the game title
|
||||
fileStream.Read(application_type, 0, 2); // Application type
|
||||
fileStream.Read(space_space5, 0, 1); // 0x20
|
||||
fileStream.Read(product_code, 0, 13); // Official product code
|
||||
fileStream.Read(peripherals, 0, 16); // Supported peripherals, see above
|
||||
fileStream.Read(spare_space6, 0, 16); // 0x20
|
||||
fileStream.Read(spare_space7, 0, 64); // Inside here should be modem information, but I need to get a modem-enabled game
|
||||
fileStream.Read(region_codes, 0, 16); // Region codes, space-filled
|
||||
// Decoding all data
|
||||
DateTime ipbindate = new DateTime();
|
||||
CultureInfo provider = CultureInfo.InvariantCulture;
|
||||
ipbindate = DateTime.ParseExact(Encoding.ASCII.GetString(release_date), "MMddyyyy", provider);
|
||||
|
||||
switch (Encoding.ASCII.GetString(application_type))
|
||||
{
|
||||
case "GM":
|
||||
IPBinInformation.AppendLine("Disc is a game.");
|
||||
break;
|
||||
case "AI":
|
||||
IPBinInformation.AppendLine("Disc is an application.");
|
||||
break;
|
||||
default:
|
||||
IPBinInformation.AppendLine("Disc is from unknown type.");
|
||||
break;
|
||||
}
|
||||
|
||||
IPBinInformation.AppendFormat("Volume name: {0}", Encoding.ASCII.GetString(volume_name)).AppendLine();
|
||||
//IPBinInformation.AppendFormat("Volume version: {0}", Encoding.ASCII.GetString(volume_version)).AppendLine();
|
||||
//IPBinInformation.AppendFormat("{0}", Encoding.ASCII.GetString(volume_type)).AppendLine();
|
||||
IPBinInformation.AppendFormat("System name: {0}", Encoding.ASCII.GetString(system_name)).AppendLine();
|
||||
//IPBinInformation.AppendFormat("System version: {0}", Encoding.ASCII.GetString(system_version)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Initial program address: 0x{0}", BitConverter.ToInt32(ip_address, 0).ToString("X")).AppendLine();
|
||||
IPBinInformation.AppendFormat("Initial program load size: {0} bytes", BitConverter.ToInt32(ip_loadsize, 0)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Initial program entry address: 0x{0}", BitConverter.ToInt32(ip_entry_address, 0).ToString("X")).AppendLine();
|
||||
IPBinInformation.AppendFormat("Initial program work RAM: {0} bytes", BitConverter.ToInt32(ip_work_ram_size, 0)).AppendLine();
|
||||
IPBinInformation.AppendFormat("System program address: 0x{0}", BitConverter.ToInt32(sp_address, 0).ToString("X")).AppendLine();
|
||||
IPBinInformation.AppendFormat("System program load size: {0} bytes", BitConverter.ToInt32(sp_loadsize, 0)).AppendLine();
|
||||
IPBinInformation.AppendFormat("System program entry address: 0x{0}", BitConverter.ToInt32(sp_entry_address, 0).ToString("X")).AppendLine();
|
||||
IPBinInformation.AppendFormat("System program work RAM: {0} bytes", BitConverter.ToInt32(sp_work_ram_size, 0)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Release date: {0}", ipbindate.ToString()).AppendLine();
|
||||
IPBinInformation.AppendFormat("Release date (other format): {0}", Encoding.ASCII.GetString(release_date2)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Hardware ID: {0}", Encoding.ASCII.GetString(hardware_id)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Developer code: {0}", Encoding.ASCII.GetString(developer_code)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Domestic title: {0}", Encoding.ASCII.GetString(domestic_title)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Overseas title: {0}", Encoding.ASCII.GetString(overseas_title)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Product code: {0}", Encoding.ASCII.GetString(product_code)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Peripherals:").AppendLine();
|
||||
foreach(byte peripheral in peripherals)
|
||||
{
|
||||
switch((char)peripheral)
|
||||
{
|
||||
case 'A':
|
||||
IPBinInformation.AppendLine("Game supports analog controller.");
|
||||
break;
|
||||
case 'B':
|
||||
IPBinInformation.AppendLine("Game supports trackball.");
|
||||
break;
|
||||
case 'G':
|
||||
IPBinInformation.AppendLine("Game supports light gun.");
|
||||
break;
|
||||
case 'J':
|
||||
IPBinInformation.AppendLine("Game supports JoyPad.");
|
||||
break;
|
||||
case 'K':
|
||||
IPBinInformation.AppendLine("Game supports keyboard.");
|
||||
break;
|
||||
case 'M':
|
||||
IPBinInformation.AppendLine("Game supports mouse.");
|
||||
break;
|
||||
case 'O':
|
||||
IPBinInformation.AppendLine("Game supports Master System's JoyPad.");
|
||||
break;
|
||||
case 'P':
|
||||
IPBinInformation.AppendLine("Game supports printer interface.");
|
||||
break;
|
||||
case 'R':
|
||||
IPBinInformation.AppendLine("Game supports serial (RS-232C) interface.");
|
||||
break;
|
||||
case 'T':
|
||||
IPBinInformation.AppendLine("Game supports tablet interface.");
|
||||
break;
|
||||
case 'V':
|
||||
IPBinInformation.AppendLine("Game supports paddle controller.");
|
||||
break;
|
||||
case ' ':
|
||||
break;
|
||||
default:
|
||||
IPBinInformation.AppendFormat("Game supports unknown peripheral {0}.", peripheral.ToString()).AppendLine();
|
||||
break;
|
||||
}
|
||||
}
|
||||
IPBinInformation.AppendLine("Regions supported:");
|
||||
foreach (byte region in region_codes)
|
||||
{
|
||||
switch ((char)region)
|
||||
{
|
||||
case 'J':
|
||||
IPBinInformation.AppendLine("Japanese NTSC.");
|
||||
break;
|
||||
case 'U':
|
||||
IPBinInformation.AppendLine("USA NTSC.");
|
||||
break;
|
||||
case 'E':
|
||||
IPBinInformation.AppendLine("Europe PAL.");
|
||||
break;
|
||||
case ' ':
|
||||
break;
|
||||
default:
|
||||
IPBinInformation.AppendFormat("Game supports unknown region {0}.", region.ToString()).AppendLine();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case "SEGA SEGASATURN ":
|
||||
{
|
||||
Saturn = true;
|
||||
|
||||
IPBinInformation.AppendLine("--------------------------------");
|
||||
IPBinInformation.AppendLine("SEGA IP.BIN INFORMATION:");
|
||||
IPBinInformation.AppendLine("--------------------------------");
|
||||
|
||||
// Definitions following
|
||||
byte[] maker_id = new byte[16]; // "SEGA ENTERPRISES"
|
||||
byte[] product_no = new byte[10]; // Product number
|
||||
byte[] product_version = new byte[6]; // Product version
|
||||
byte[] release_date = new byte[8]; // YYYYMMDD
|
||||
byte[] saturn_media = new byte[3]; // "CD-"
|
||||
byte[] disc_no = new byte[1]; // Disc number
|
||||
byte[] disc_no_separator = new byte[1]; // '/'
|
||||
byte[] disc_total_nos = new byte[1]; // Total number of discs
|
||||
byte[] spare_space1 = new byte[2]; // " "
|
||||
byte[] region_codes = new byte[10]; // Region codes, space-filled
|
||||
byte[] spare_space2 = new byte[6]; // " "
|
||||
byte[] peripherals = new byte[16]; // Supported peripherals, see above
|
||||
byte[] product_name = new byte[112]; // Game name, space-filled
|
||||
// Reading all data
|
||||
fileStream.Read(maker_id, 0, 16); // "SEGA ENTERPRISES"
|
||||
fileStream.Read(product_no, 0, 10); // Product number
|
||||
fileStream.Read(product_version, 0, 6); // Product version
|
||||
fileStream.Read(release_date, 0, 8); // YYYYMMDD
|
||||
fileStream.Read(saturn_media, 0, 3); // "CD-"
|
||||
fileStream.Read(disc_no, 0, 1); // Disc number
|
||||
fileStream.Read(disc_no_separator, 0, 1); // '/'
|
||||
fileStream.Read(disc_total_nos, 0, 1); // Total number of discs
|
||||
fileStream.Read(spare_space1, 0, 2); // " "
|
||||
fileStream.Read(region_codes, 0, 10); // Region codes, space-filled
|
||||
fileStream.Read(spare_space2, 0, 6); // " "
|
||||
fileStream.Read(peripherals, 0, 16); // Supported peripherals, see above
|
||||
fileStream.Read(product_name, 0, 112); // Game name, space-filled
|
||||
// Decoding all data
|
||||
DateTime ipbindate = new DateTime();
|
||||
CultureInfo provider = CultureInfo.InvariantCulture;
|
||||
ipbindate = DateTime.ParseExact(Encoding.ASCII.GetString(release_date), "yyyyMMdd", provider);
|
||||
IPBinInformation.AppendFormat("Product name: {0}", Encoding.ASCII.GetString(product_name)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Product number: {0}", Encoding.ASCII.GetString(product_no)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Product version: {0}", Encoding.ASCII.GetString(product_version)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Release date: {0}", ipbindate.ToString()).AppendLine();
|
||||
IPBinInformation.AppendFormat("Disc number {0} of {1}", Encoding.ASCII.GetString(disc_no), Encoding.ASCII.GetString(disc_total_nos)).AppendLine();
|
||||
|
||||
IPBinInformation.AppendFormat("Peripherals:").AppendLine();
|
||||
foreach (byte peripheral in peripherals)
|
||||
{
|
||||
switch ((char)peripheral)
|
||||
{
|
||||
case 'A':
|
||||
IPBinInformation.AppendLine("Game supports analog controller.");
|
||||
break;
|
||||
case 'J':
|
||||
IPBinInformation.AppendLine("Game supports JoyPad.");
|
||||
break;
|
||||
case 'K':
|
||||
IPBinInformation.AppendLine("Game supports keyboard.");
|
||||
break;
|
||||
case 'M':
|
||||
IPBinInformation.AppendLine("Game supports mouse.");
|
||||
break;
|
||||
case 'S':
|
||||
IPBinInformation.AppendLine("Game supports analog steering controller.");
|
||||
break;
|
||||
case 'T':
|
||||
IPBinInformation.AppendLine("Game supports multitap.");
|
||||
break;
|
||||
case ' ':
|
||||
break;
|
||||
default:
|
||||
IPBinInformation.AppendFormat("Game supports unknown peripheral {0}.", peripheral.ToString()).AppendLine();
|
||||
break;
|
||||
}
|
||||
}
|
||||
IPBinInformation.AppendLine("Regions supported:");
|
||||
foreach (byte region in region_codes)
|
||||
{
|
||||
switch ((char)region)
|
||||
{
|
||||
case 'J':
|
||||
IPBinInformation.AppendLine("Japanese NTSC.");
|
||||
break;
|
||||
case 'U':
|
||||
IPBinInformation.AppendLine("North America NTSC.");
|
||||
break;
|
||||
case 'E':
|
||||
IPBinInformation.AppendLine("Europe PAL.");
|
||||
break;
|
||||
case 'T':
|
||||
IPBinInformation.AppendLine("Asia NTSC.");
|
||||
break;
|
||||
case ' ':
|
||||
break;
|
||||
default:
|
||||
IPBinInformation.AppendFormat("Game supports unknown region {0}.", region.ToString()).AppendLine();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case "SEGA SEGAKATANA ":
|
||||
{
|
||||
Dreamcast = true;
|
||||
|
||||
IPBinInformation.AppendLine("--------------------------------");
|
||||
IPBinInformation.AppendLine("SEGA IP.BIN INFORMATION:");
|
||||
IPBinInformation.AppendLine("--------------------------------");
|
||||
|
||||
// Declarations following
|
||||
byte[] maker_id = new byte[16]; // "SEGA ENTERPRISES"
|
||||
byte[] dreamcast_crc = new byte[4]; // CRC of product_no and product_version
|
||||
byte[] spare_space1 = new byte[1]; // " "
|
||||
byte[] dreamcast_media = new byte[6]; // "GD-ROM"
|
||||
byte[] disc_no = new byte[1]; // Disc number
|
||||
byte[] disc_no_separator = new byte[1]; // '/'
|
||||
byte[] disc_total_nos = new byte[1]; // Total number of discs
|
||||
byte[] spare_space2 = new byte[2]; // " "
|
||||
byte[] region_codes = new byte[8]; // Region codes, space-filled
|
||||
byte[] peripherals = new byte[4]; // Supported peripherals, bitwise
|
||||
byte[] product_no = new byte[10]; // Product number
|
||||
byte[] product_version = new byte[6]; // Product version
|
||||
byte[] release_date = new byte[8]; // YYYYMMDD
|
||||
byte[] spare_space3 = new byte[8]; // " "
|
||||
byte[] boot_filename = new byte[12]; // Usually "1ST_READ.BIN" or "0WINCE.BIN "
|
||||
byte[] producer = new byte[16]; // Game producer, space-filled
|
||||
byte[] product_name = new byte[128]; // Game name, space-filled
|
||||
// Reading all data
|
||||
fileStream.Read(maker_id, 0, 16); // "SEGA ENTERPRISES"
|
||||
fileStream.Read(dreamcast_crc, 0, 4); // CRC of product_no and product_version
|
||||
fileStream.Read(spare_space1, 0, 1); // " "
|
||||
fileStream.Read(dreamcast_media, 0, 6); // "GD-ROM"
|
||||
fileStream.Read(disc_no, 0, 1); // Disc number
|
||||
fileStream.Read(disc_no_separator, 0, 1); // '/'
|
||||
fileStream.Read(disc_total_nos, 0, 1); // Total number of discs
|
||||
fileStream.Read(spare_space2, 0, 2); // " "
|
||||
fileStream.Read(region_codes, 0, 8); // Region codes, space-filled
|
||||
fileStream.Read(peripherals, 0, 4); // Supported peripherals, bitwise
|
||||
fileStream.Read(product_no, 0, 10); // Product number
|
||||
fileStream.Read(product_version, 0, 6); // Product version
|
||||
fileStream.Read(release_date, 0, 8); // YYYYMMDD
|
||||
fileStream.Read(spare_space3, 0, 8); // " "
|
||||
fileStream.Read(boot_filename, 0, 12); // Usually "1ST_READ.BIN" or "0WINCE.BIN "
|
||||
fileStream.Read(producer, 0, 16); // Game producer, space-filled
|
||||
fileStream.Read(product_name, 0, 128); // Game name, space-filled
|
||||
// Decoding all data
|
||||
DateTime ipbindate = new DateTime();
|
||||
CultureInfo provider = CultureInfo.InvariantCulture;
|
||||
ipbindate = DateTime.ParseExact(Encoding.ASCII.GetString(release_date), "yyyyMMdd", provider);
|
||||
IPBinInformation.AppendFormat("Product name: {0}", Encoding.ASCII.GetString(product_name)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Product version: {0}", Encoding.ASCII.GetString(product_version)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Producer: {0}", Encoding.ASCII.GetString(producer)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Disc media: {0}", Encoding.ASCII.GetString(dreamcast_media)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Disc number {0} of {1}", Encoding.ASCII.GetString(disc_no), Encoding.ASCII.GetString(disc_total_nos)).AppendLine();
|
||||
IPBinInformation.AppendFormat("Release date: {0}", ipbindate.ToString()).AppendLine();
|
||||
switch (Encoding.ASCII.GetString(boot_filename))
|
||||
{
|
||||
case "1ST_READ.BIN":
|
||||
IPBinInformation.AppendLine("Disc boots natively.");
|
||||
break;
|
||||
case "0WINCE.BIN ":
|
||||
IPBinInformation.AppendLine("Disc boots using Windows CE.");
|
||||
break;
|
||||
default:
|
||||
IPBinInformation.AppendFormat("Disc boots using unknown loader: {0}.", Encoding.ASCII.GetString(boot_filename)).AppendLine();
|
||||
break;
|
||||
}
|
||||
IPBinInformation.AppendLine("Regions supported:");
|
||||
foreach (byte region in region_codes)
|
||||
{
|
||||
switch ((char)region)
|
||||
{
|
||||
case 'J':
|
||||
IPBinInformation.AppendLine("Japanese NTSC.");
|
||||
break;
|
||||
case 'U':
|
||||
IPBinInformation.AppendLine("North America NTSC.");
|
||||
break;
|
||||
case 'E':
|
||||
IPBinInformation.AppendLine("Europe PAL.");
|
||||
break;
|
||||
case ' ':
|
||||
break;
|
||||
default:
|
||||
IPBinInformation.AppendFormat("Game supports unknown region {0}.", region.ToString()).AppendLine();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int iPeripherals = BitConverter.ToInt32(peripherals, 0);
|
||||
|
||||
if((iPeripherals & 0x00000010) == 0x00000010)
|
||||
IPBinInformation.AppendLine("Game uses Windows CE.");
|
||||
|
||||
IPBinInformation.AppendFormat("Peripherals:").AppendLine();
|
||||
|
||||
if ((iPeripherals & 0x00000100) == 0x00000100)
|
||||
IPBinInformation.AppendLine("Game supports the VGA Box.");
|
||||
if ((iPeripherals & 0x00001000) == 0x00001000)
|
||||
IPBinInformation.AppendLine("Game supports other expansion.");
|
||||
if ((iPeripherals & 0x00002000) == 0x00002000)
|
||||
IPBinInformation.AppendLine("Game supports Puru Puru pack.");
|
||||
if ((iPeripherals & 0x00004000) == 0x00004000)
|
||||
IPBinInformation.AppendLine("Game supports Mike Device.");
|
||||
if ((iPeripherals & 0x00008000) == 0x00008000)
|
||||
IPBinInformation.AppendLine("Game supports Memory Card.");
|
||||
if ((iPeripherals & 0x00010000) == 0x00010000)
|
||||
IPBinInformation.AppendLine("Game requires A + B + Start buttons and D-Pad.");
|
||||
if ((iPeripherals & 0x00020000) == 0x00020000)
|
||||
IPBinInformation.AppendLine("Game requires C button.");
|
||||
if ((iPeripherals & 0x00040000) == 0x00040000)
|
||||
IPBinInformation.AppendLine("Game requires D button.");
|
||||
if ((iPeripherals & 0x00080000) == 0x00080000)
|
||||
IPBinInformation.AppendLine("Game requires X button.");
|
||||
if ((iPeripherals & 0x00100000) == 0x00100000)
|
||||
IPBinInformation.AppendLine("Game requires Y button.");
|
||||
if ((iPeripherals & 0x00200000) == 0x00200000)
|
||||
IPBinInformation.AppendLine("Game requires Z button.");
|
||||
if ((iPeripherals & 0x00400000) == 0x00400000)
|
||||
IPBinInformation.AppendLine("Game requires expanded direction buttons.");
|
||||
if ((iPeripherals & 0x00800000) == 0x00800000)
|
||||
IPBinInformation.AppendLine("Game requires analog R trigger.");
|
||||
if ((iPeripherals & 0x01000000) == 0x01000000)
|
||||
IPBinInformation.AppendLine("Game requires analog L trigger.");
|
||||
if ((iPeripherals & 0x02000000) == 0x02000000)
|
||||
IPBinInformation.AppendLine("Game requires analog horizontal controller.");
|
||||
if ((iPeripherals & 0x04000000) == 0x04000000)
|
||||
IPBinInformation.AppendLine("Game requires analog vertical controller.");
|
||||
if ((iPeripherals & 0x08000000) == 0x08000000)
|
||||
IPBinInformation.AppendLine("Game requires expanded analog horizontal controller.");
|
||||
if ((iPeripherals & 0x10000000) == 0x10000000)
|
||||
IPBinInformation.AppendLine("Game requires expanded analog vertical controller.");
|
||||
if ((iPeripherals & 0x20000000) == 0x20000000)
|
||||
IPBinInformation.AppendLine("Game supports Gun.");
|
||||
if ((iPeripherals & 0x40000000) == 0x40000000)
|
||||
IPBinInformation.AppendLine("Game supports Keyboard.");
|
||||
if ((iPeripherals & 0x80000000) == 0x80000000)
|
||||
IPBinInformation.AppendLine("Game supports Mouse.");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
ISOMetadata.AppendFormat("ISO9660 file system").AppendLine();
|
||||
if(Joliet)
|
||||
ISOMetadata.AppendFormat("Joliet extensions present.").AppendLine();
|
||||
if (RockRidge)
|
||||
ISOMetadata.AppendFormat("Rock Ridge Interchange Protocol present.").AppendLine();
|
||||
if (Bootable)
|
||||
ISOMetadata.AppendFormat("Disc bootable following {0} specifications.", BootSpec).AppendLine();
|
||||
if (SegaCD)
|
||||
{
|
||||
ISOMetadata.AppendLine("This is a SegaCD / MegaCD disc.");
|
||||
ISOMetadata.AppendLine(IPBinInformation.ToString());
|
||||
}
|
||||
if (Saturn)
|
||||
{
|
||||
ISOMetadata.AppendLine("This is a Sega Saturn disc.");
|
||||
ISOMetadata.AppendLine(IPBinInformation.ToString());
|
||||
}
|
||||
if (Dreamcast)
|
||||
{
|
||||
ISOMetadata.AppendLine("This is a Sega Dreamcast disc.");
|
||||
ISOMetadata.AppendLine(IPBinInformation.ToString());
|
||||
}
|
||||
ISOMetadata.AppendLine("--------------------------------");
|
||||
ISOMetadata.AppendLine("VOLUME DESCRIPTOR INFORMATION:");
|
||||
ISOMetadata.AppendLine("--------------------------------");
|
||||
ISOMetadata.AppendFormat("System identifier: {0}", decodedVD.SystemIdentifier).AppendLine();
|
||||
ISOMetadata.AppendFormat("Volume identifier: {0}", decodedVD.VolumeIdentifier).AppendLine();
|
||||
ISOMetadata.AppendFormat("Volume set identifier: {0}", decodedVD.VolumeSetIdentifier).AppendLine();
|
||||
ISOMetadata.AppendFormat("Publisher identifier: {0}", decodedVD.PublisherIdentifier).AppendLine();
|
||||
ISOMetadata.AppendFormat("Data preparer identifier: {0}", decodedVD.DataPreparerIdentifier).AppendLine();
|
||||
ISOMetadata.AppendFormat("Application identifier: {0}", decodedVD.ApplicationIdentifier).AppendLine();
|
||||
ISOMetadata.AppendFormat("Volume creation date: {0}", decodedVD.CreationTime.ToString()).AppendLine();
|
||||
if (decodedVD.HasModificationTime)
|
||||
ISOMetadata.AppendFormat("Volume modification date: {0}", decodedVD.ModificationTime.ToString()).AppendLine();
|
||||
else
|
||||
ISOMetadata.AppendFormat("Volume has not been modified.").AppendLine();
|
||||
if (decodedVD.HasExpirationTime)
|
||||
ISOMetadata.AppendFormat("Volume expiration date: {0}", decodedVD.ExpirationTime.ToString()).AppendLine();
|
||||
else
|
||||
ISOMetadata.AppendFormat("Volume does not expire.").AppendLine();
|
||||
if (decodedVD.HasEffectiveTime)
|
||||
ISOMetadata.AppendFormat("Volume effective date: {0}", decodedVD.EffectiveTime.ToString()).AppendLine();
|
||||
else
|
||||
ISOMetadata.AppendFormat("Volume has always been effective.").AppendLine();
|
||||
|
||||
information = ISOMetadata.ToString();
|
||||
}
|
||||
|
||||
private DecodedVolumeDescriptor DecodeJolietDescriptor(byte[] VDSysId, byte[] VDVolId, byte[] VDVolSetId, byte[] VDPubId, byte[] VDDataPrepId, byte[] VDAppId, byte[] VCTime, byte[] VMTime, byte[] VXTime, byte[] VETime)
|
||||
{
|
||||
DecodedVolumeDescriptor decodedVD = new DecodedVolumeDescriptor();
|
||||
|
||||
decodedVD.SystemIdentifier = Encoding.BigEndianUnicode.GetString(VDSysId);
|
||||
decodedVD.VolumeIdentifier = Encoding.BigEndianUnicode.GetString(VDVolId);
|
||||
decodedVD.VolumeSetIdentifier = Encoding.BigEndianUnicode.GetString(VDVolSetId);
|
||||
decodedVD.PublisherIdentifier = Encoding.BigEndianUnicode.GetString(VDPubId);
|
||||
decodedVD.DataPreparerIdentifier = Encoding.BigEndianUnicode.GetString(VDDataPrepId);
|
||||
decodedVD.ApplicationIdentifier = Encoding.BigEndianUnicode.GetString(VDAppId);
|
||||
if (VCTime[0] == '0' || VCTime[0] == 0x00)
|
||||
decodedVD.CreationTime = DateTime.MinValue;
|
||||
else
|
||||
decodedVD.CreationTime = DecodeVDDateTime(VCTime);
|
||||
|
||||
if (VMTime[0] == '0' || VMTime[0] == 0x00)
|
||||
{
|
||||
decodedVD.HasModificationTime = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
decodedVD.HasModificationTime = true;
|
||||
decodedVD.ModificationTime = DecodeVDDateTime(VMTime);
|
||||
}
|
||||
|
||||
if (VXTime[0] == '0' || VXTime[0] == 0x00)
|
||||
{
|
||||
decodedVD.HasExpirationTime = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
decodedVD.HasExpirationTime = true;
|
||||
decodedVD.ExpirationTime = DecodeVDDateTime(VXTime);
|
||||
}
|
||||
|
||||
if (VETime[0] == '0' || VETime[0] == 0x00)
|
||||
{
|
||||
decodedVD.HasEffectiveTime = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
decodedVD.HasEffectiveTime = true;
|
||||
decodedVD.EffectiveTime = DecodeVDDateTime(VETime);
|
||||
}
|
||||
|
||||
return decodedVD;
|
||||
}
|
||||
|
||||
private DecodedVolumeDescriptor DecodeVolumeDescriptor(byte[] VDSysId, byte[] VDVolId, byte[] VDVolSetId, byte[] VDPubId, byte[] VDDataPrepId, byte[] VDAppId, byte[] VCTime, byte[] VMTime, byte[] VXTime, byte[] VETime)
|
||||
{
|
||||
DecodedVolumeDescriptor decodedVD = new DecodedVolumeDescriptor();
|
||||
|
||||
decodedVD.SystemIdentifier = Encoding.ASCII.GetString(VDSysId);
|
||||
decodedVD.VolumeIdentifier = Encoding.ASCII.GetString(VDVolId);
|
||||
decodedVD.VolumeSetIdentifier = Encoding.ASCII.GetString(VDVolSetId);
|
||||
decodedVD.PublisherIdentifier = Encoding.ASCII.GetString(VDPubId);
|
||||
decodedVD.DataPreparerIdentifier = Encoding.ASCII.GetString(VDDataPrepId);
|
||||
decodedVD.ApplicationIdentifier = Encoding.ASCII.GetString(VDAppId);
|
||||
if (VCTime[0] == '0' || VCTime[0] == 0x00)
|
||||
decodedVD.CreationTime = DateTime.MinValue;
|
||||
else
|
||||
decodedVD.CreationTime = DecodeVDDateTime(VCTime);
|
||||
|
||||
if (VMTime[0] == '0' || VMTime[0] == 0x00)
|
||||
{
|
||||
decodedVD.HasModificationTime = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
decodedVD.HasModificationTime = true;
|
||||
decodedVD.ModificationTime = DecodeVDDateTime(VMTime);
|
||||
}
|
||||
|
||||
if (VXTime[0] == '0' || VXTime[0] == 0x00)
|
||||
{
|
||||
decodedVD.HasExpirationTime = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
decodedVD.HasExpirationTime = true;
|
||||
decodedVD.ExpirationTime = DecodeVDDateTime(VXTime);
|
||||
}
|
||||
|
||||
if (VETime[0] == '0' || VETime[0] == 0x00)
|
||||
{
|
||||
decodedVD.HasEffectiveTime = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
decodedVD.HasEffectiveTime = true;
|
||||
decodedVD.EffectiveTime = DecodeVDDateTime(VETime);
|
||||
}
|
||||
|
||||
return decodedVD;
|
||||
}
|
||||
|
||||
private DateTime DecodeVDDateTime(byte[] VDDateTime)
|
||||
{
|
||||
int year, month, day, hour, minute, second, hundredths;
|
||||
byte[] twocharvalue = new byte[2];
|
||||
byte[] fourcharvalue = new byte[4];
|
||||
|
||||
fourcharvalue[0] = VDDateTime[0];
|
||||
fourcharvalue[1] = VDDateTime[1];
|
||||
fourcharvalue[2] = VDDateTime[2];
|
||||
fourcharvalue[3] = VDDateTime[3];
|
||||
year = Convert.ToInt32(Encoding.ASCII.GetString(fourcharvalue));
|
||||
|
||||
twocharvalue[0] = VDDateTime[4];
|
||||
twocharvalue[1] = VDDateTime[5];
|
||||
month = Convert.ToInt32(Encoding.ASCII.GetString(twocharvalue));
|
||||
|
||||
twocharvalue[0] = VDDateTime[6];
|
||||
twocharvalue[1] = VDDateTime[7];
|
||||
day = Convert.ToInt32(Encoding.ASCII.GetString(twocharvalue));
|
||||
|
||||
twocharvalue[0] = VDDateTime[8];
|
||||
twocharvalue[1] = VDDateTime[9];
|
||||
hour = Convert.ToInt32(Encoding.ASCII.GetString(twocharvalue));
|
||||
|
||||
twocharvalue[0] = VDDateTime[10];
|
||||
twocharvalue[1] = VDDateTime[11];
|
||||
minute = Convert.ToInt32(Encoding.ASCII.GetString(twocharvalue));
|
||||
|
||||
twocharvalue[0] = VDDateTime[12];
|
||||
twocharvalue[1] = VDDateTime[13];
|
||||
second = Convert.ToInt32(Encoding.ASCII.GetString(twocharvalue));
|
||||
|
||||
twocharvalue[0] = VDDateTime[14];
|
||||
twocharvalue[1] = VDDateTime[15];
|
||||
hundredths = Convert.ToInt32(Encoding.ASCII.GetString(twocharvalue));
|
||||
|
||||
DateTime decodedDT = new DateTime(year, month, day, hour, minute, second, hundredths * 10, DateTimeKind.Unspecified);
|
||||
|
||||
return decodedDT;
|
||||
}
|
||||
}
|
||||
}
|
||||
134
FileSystemIDandChk/Plugins/Opera.cs
Normal file
134
FileSystemIDandChk/Plugins/Opera.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using FileSystemIDandChk;
|
||||
|
||||
// Information from Inside Macintosh
|
||||
|
||||
namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
class OperaFS : Plugin
|
||||
{
|
||||
public OperaFS(PluginBase Core)
|
||||
{
|
||||
base.Name = "Opera Filesystem Plugin";
|
||||
base.PluginUUID = new Guid("0ec84ec7-eae6-4196-83fe-943b3fe46dbd");
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream fileStream, long offset)
|
||||
{
|
||||
fileStream.Seek(0 + offset, SeekOrigin.Begin);
|
||||
|
||||
byte record_type;
|
||||
byte[] sync_bytes = new byte[5];
|
||||
byte record_version;
|
||||
|
||||
record_type = (byte)fileStream.ReadByte();
|
||||
fileStream.Read(sync_bytes, 0, 5);
|
||||
record_version = (byte)fileStream.ReadByte();
|
||||
|
||||
if (record_type != 1 || record_version != 1)
|
||||
return false;
|
||||
if(Encoding.ASCII.GetString(sync_bytes) != "ZZZZZ")
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream fileStream, long offset, out string information)
|
||||
{
|
||||
information = "";
|
||||
StringBuilder SuperBlockMetadata = new StringBuilder();
|
||||
|
||||
fileStream.Seek(0 + offset, SeekOrigin.Begin);
|
||||
|
||||
byte[] record_type = new byte[1];
|
||||
byte[] sync_bytes = new byte[5];
|
||||
byte[] record_version = new byte[1];
|
||||
byte[] volume_flags = new byte[1];
|
||||
byte[] volume_comment = new byte[32];
|
||||
byte[] volume_label = new byte[32];
|
||||
byte[] volume_id = new byte[4];
|
||||
byte[] block_size = new byte[4];
|
||||
byte[] block_count = new byte[4];
|
||||
byte[] root_dirid = new byte[4];
|
||||
byte[] rootdir_blocks = new byte[4];
|
||||
byte[] rootdir_bsize = new byte[4];
|
||||
byte[] last_root_copy = new byte[4];
|
||||
|
||||
fileStream.Read(record_type, 0, 1);
|
||||
fileStream.Read(sync_bytes, 0, 5);
|
||||
fileStream.Read(record_version, 0, 1);
|
||||
fileStream.Read(volume_flags, 0, 1);
|
||||
fileStream.Read(volume_comment, 0, 32);
|
||||
fileStream.Read(volume_label, 0, 32);
|
||||
fileStream.Read(volume_id, 0, 4);
|
||||
fileStream.Read(block_size, 0, 4);
|
||||
fileStream.Read(block_count, 0, 4);
|
||||
fileStream.Read(root_dirid, 0, 4);
|
||||
fileStream.Read(rootdir_blocks, 0, 4);
|
||||
fileStream.Read(rootdir_bsize, 0, 4);
|
||||
fileStream.Read(last_root_copy, 0, 4);
|
||||
|
||||
if (record_type[0] != 1 || record_version[0] != 1)
|
||||
return;
|
||||
if(Encoding.ASCII.GetString(sync_bytes) != "ZZZZZ")
|
||||
return;
|
||||
|
||||
// Swapping data (C# is LE, Opera is BE)
|
||||
volume_id = Swapping.SwapFourBytes(volume_id);
|
||||
block_size = Swapping.SwapFourBytes(block_size);
|
||||
block_count = Swapping.SwapFourBytes(block_count);
|
||||
root_dirid = Swapping.SwapFourBytes(root_dirid);
|
||||
rootdir_blocks = Swapping.SwapFourBytes(rootdir_blocks);
|
||||
rootdir_bsize = Swapping.SwapFourBytes(rootdir_bsize);
|
||||
last_root_copy = Swapping.SwapFourBytes(last_root_copy);
|
||||
|
||||
int vid = BitConverter.ToInt32(volume_id, 0);
|
||||
int rdid = BitConverter.ToInt32(root_dirid, 0);
|
||||
|
||||
StringBuilder VolumeComment = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < volume_comment.Length; i++)
|
||||
{
|
||||
if (volume_comment[i] != 0x00)
|
||||
VolumeComment.Append((char)volume_comment[i]);
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (VolumeComment.Length == 0)
|
||||
VolumeComment.Append("Not set.");
|
||||
|
||||
StringBuilder VolumeLabel = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < volume_label.Length; i++)
|
||||
{
|
||||
if (volume_label[i] != 0x00)
|
||||
VolumeLabel.Append((char)volume_label[i]);
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (VolumeLabel.Length == 0)
|
||||
VolumeLabel.Append("Not set.");
|
||||
|
||||
int bs = BitConverter.ToInt32(block_size, 0);
|
||||
int vblocks = BitConverter.ToInt32(block_count, 0);
|
||||
int rbs = BitConverter.ToInt32(rootdir_bsize, 0);
|
||||
int rblocks = BitConverter.ToInt32(rootdir_blocks, 0);
|
||||
|
||||
SuperBlockMetadata.AppendFormat("Opera filesystem disc.").AppendLine();
|
||||
SuperBlockMetadata.AppendFormat("Volume label: {0}", VolumeLabel.ToString()).AppendLine();
|
||||
SuperBlockMetadata.AppendFormat("Volume comment: {0}", VolumeComment.ToString()).AppendLine();
|
||||
SuperBlockMetadata.AppendFormat("Volume identifier: 0x{0}", vid.ToString("X")).AppendLine();
|
||||
SuperBlockMetadata.AppendFormat("Block size: {0} bytes", bs).AppendLine();
|
||||
SuperBlockMetadata.AppendFormat("Volume size: {0} blocks, {1} bytes", vblocks, bs*vblocks).AppendLine();
|
||||
SuperBlockMetadata.AppendFormat("Root directory identifier: 0x{0}", rdid.ToString("X")).AppendLine();
|
||||
SuperBlockMetadata.AppendFormat("Root directory block size: {0} bytes", rbs).AppendLine();
|
||||
SuperBlockMetadata.AppendFormat("Root directory size: {0} blocks, {1} bytes", rblocks, rbs*rblocks).AppendLine();
|
||||
SuperBlockMetadata.AppendFormat("Last root directory copy: {0}", BitConverter.ToInt32(last_root_copy, 0)).AppendLine();
|
||||
|
||||
information = SuperBlockMetadata.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
38
FileSystemIDandChk/Plugins/PCEngine.cs
Normal file
38
FileSystemIDandChk/Plugins/PCEngine.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using FileSystemIDandChk;
|
||||
|
||||
// Information from Inside Macintosh
|
||||
|
||||
namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
class PCEnginePlugin : Plugin
|
||||
{
|
||||
public PCEnginePlugin(PluginBase Core)
|
||||
{
|
||||
base.Name = "PC Engine CD Plugin";
|
||||
base.PluginUUID = new Guid("e5ee6d7c-90fa-49bd-ac89-14ef750b8af3");
|
||||
}
|
||||
|
||||
public override bool Identify(FileStream stream, long offset)
|
||||
{
|
||||
byte[] system_descriptor = new byte[23];
|
||||
|
||||
stream.Seek(2080 + offset, SeekOrigin.Begin);
|
||||
|
||||
stream.Read(system_descriptor, 0, 23);
|
||||
|
||||
if(Encoding.ASCII.GetString(system_descriptor) == "PC Engine CD-ROM SYSTEM")
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetInformation (FileStream stream, long offset, out string information)
|
||||
{
|
||||
information = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
19
FileSystemIDandChk/Plugins/Plugin.cs
Normal file
19
FileSystemIDandChk/Plugins/Plugin.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace FileSystemIDandChk.Plugins
|
||||
{
|
||||
public abstract class Plugin
|
||||
{
|
||||
public string Name;
|
||||
public Guid PluginUUID;
|
||||
|
||||
protected Plugin()
|
||||
{
|
||||
}
|
||||
|
||||
public abstract bool Identify(FileStream stream, long offset);
|
||||
public abstract void GetInformation(FileStream stream, long offset, out string information);
|
||||
}
|
||||
}
|
||||
|
||||
63
FileSystemIDandChk/Swapping.cs
Normal file
63
FileSystemIDandChk/Swapping.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
|
||||
namespace FileSystemIDandChk
|
||||
{
|
||||
static class Swapping
|
||||
{
|
||||
public static byte[] SwapTenBytes(byte[] source)
|
||||
{
|
||||
byte[] destination = new byte[8];
|
||||
|
||||
destination[0] = source[9];
|
||||
destination[1] = source[8];
|
||||
destination[2] = source[7];
|
||||
destination[3] = source[6];
|
||||
destination[4] = source[5];
|
||||
destination[5] = source[4];
|
||||
destination[6] = source[3];
|
||||
destination[7] = source[2];
|
||||
destination[8] = source[1];
|
||||
destination[9] = source[0];
|
||||
|
||||
return destination;
|
||||
}
|
||||
|
||||
public static byte[] SwapEightBytes(byte[] source)
|
||||
{
|
||||
byte[] destination = new byte[8];
|
||||
|
||||
destination[0] = source[7];
|
||||
destination[1] = source[6];
|
||||
destination[2] = source[5];
|
||||
destination[3] = source[4];
|
||||
destination[4] = source[3];
|
||||
destination[5] = source[2];
|
||||
destination[6] = source[1];
|
||||
destination[7] = source[0];
|
||||
|
||||
return destination;
|
||||
}
|
||||
|
||||
public static byte[] SwapFourBytes(byte[] source)
|
||||
{
|
||||
byte[] destination = new byte[4];
|
||||
|
||||
destination[0] = source[3];
|
||||
destination[1] = source[2];
|
||||
destination[2] = source[1];
|
||||
destination[3] = source[0];
|
||||
|
||||
return destination;
|
||||
}
|
||||
|
||||
public static byte[] SwapTwoBytes(byte[] source)
|
||||
{
|
||||
byte[] destination = new byte[2];
|
||||
|
||||
destination[0] = source[1];
|
||||
destination[1] = source[0];
|
||||
|
||||
return destination;
|
||||
}
|
||||
}
|
||||
}
|
||||
1
Packages.mdproj
Normal file
1
Packages.mdproj
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
Reference in New Issue
Block a user