mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
* FileSystemIDandChk/ArrayFill.cs:
* FileSystemIDandChk/FileSystemIDandChk.csproj: Added array filling class from mykohsu. * FileSystemIDandChk/Main.cs: Print disk type as identified by image plugin * FileSystemIDandChk/ImagePlugins/ImagePlugin.cs: Added more disk types * FileSystemIDandChk/ImagePlugins/TeleDisk.cs: Added link to Dave's document. Completely implemented OpenImage() for standard (non-compressed) teledisk images. Implemented GetImageSize(), GetSectors(), GetSectorSize(), ReadSectors(), GetImageVersion(), GetImageApplicationVersion(), GetImageCreationTime(), GetImageLastModificationtime(), GetImageName(), GetDiskType(), data sector decoders. * FileSystemIDandChk/TODO: Discovered a filesystem specification present on ECMA-67. Dunno if CP/M, FAT or a different one, must check. Teledisk plugin is working, but lacks "advanced compression" and variable sectors per track support.
This commit is contained in:
70
FileSystemIDandChk/ArrayFill.cs
Normal file
70
FileSystemIDandChk/ArrayFill.cs
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
FileSystem identifier and checker
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Filename : ArrayFill.cs
|
||||||
|
Version : 1.0
|
||||||
|
Author(s) : https://github.com/mykohsu
|
||||||
|
|
||||||
|
Component : Helpers
|
||||||
|
|
||||||
|
Revision : $Revision$
|
||||||
|
Last change by : $Author$
|
||||||
|
Date : $Date$
|
||||||
|
|
||||||
|
--[ Description ] ----------------------------------------------------------
|
||||||
|
|
||||||
|
Fills an array with a
|
||||||
|
|
||||||
|
--[ License ] --------------------------------------------------------------
|
||||||
|
|
||||||
|
No license specified by creator.
|
||||||
|
|
||||||
|
Published on https://github.com/mykohsu/Extensions/blob/master/ArrayExtensions.cs
|
||||||
|
|
||||||
|
Assuming open source.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2014 mykohsu
|
||||||
|
****************************************************************************/
|
||||||
|
//$Id$
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace FileSystemIDandChk
|
||||||
|
{
|
||||||
|
public static class ArrayHelpers
|
||||||
|
{
|
||||||
|
public static void ArrayFill<T>(T[] destinationArray, T value)
|
||||||
|
{
|
||||||
|
// if called with a single value, wrap the value in an array and call the main function
|
||||||
|
ArrayFill<T>(destinationArray, new T[] { value });
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ArrayFill<T>(T[] destinationArray, T[] value)
|
||||||
|
{
|
||||||
|
if (destinationArray == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("destinationArray");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.Length > destinationArray.Length)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Length of value array must not be more than length of destination");
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the initial array value
|
||||||
|
Array.Copy(value, destinationArray, value.Length);
|
||||||
|
|
||||||
|
int arrayToFillHalfLength = destinationArray.Length / 2;
|
||||||
|
int copyLength;
|
||||||
|
|
||||||
|
for(copyLength = value.Length; copyLength < arrayToFillHalfLength; copyLength <<= 1)
|
||||||
|
{
|
||||||
|
Array.Copy(destinationArray, 0, destinationArray, copyLength, copyLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
Array.Copy(destinationArray, 0, destinationArray, copyLength, destinationArray.Length - copyLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||||
<ProductVersion>9.0.21022</ProductVersion>
|
<ProductVersion>8.0.30703</ProductVersion>
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
<ProjectGuid>{7A4B05BE-73C9-4F34-87FE-E80CCF1F732D}</ProjectGuid>
|
<ProjectGuid>{7A4B05BE-73C9-4F34-87FE-E80CCF1F732D}</ProjectGuid>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
@@ -73,6 +73,7 @@
|
|||||||
<Compile Include="ImagePlugins\DiskCopy42.cs" />
|
<Compile Include="ImagePlugins\DiskCopy42.cs" />
|
||||||
<Compile Include="Plugins\LisaFS.cs" />
|
<Compile Include="Plugins\LisaFS.cs" />
|
||||||
<Compile Include="ImagePlugins\TeleDisk.cs" />
|
<Compile Include="ImagePlugins\TeleDisk.cs" />
|
||||||
|
<Compile Include="ArrayFill.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -365,7 +365,94 @@ namespace FileSystemIDandChk.ImagePlugins
|
|||||||
// 8", SS, DD, 77 tracks, 26 spt, 128 bytes/sector, FM
|
// 8", SS, DD, 77 tracks, 26 spt, 128 bytes/sector, FM
|
||||||
RX01,
|
RX01,
|
||||||
// 8", SS, DD, 77 tracks, 26 spt, 256 bytes/sector, FM/MFM
|
// 8", SS, DD, 77 tracks, 26 spt, 256 bytes/sector, FM/MFM
|
||||||
RX02
|
RX02,
|
||||||
|
// Acorn standard floppy formats
|
||||||
|
// 5,25", SS, SD, 40 tracks, 10 spt, 256 bytes/sector, FM
|
||||||
|
ACORN_525_SS_SD_40,
|
||||||
|
// 5,25", SS, SD, 80 tracks, 10 spt, 256 bytes/sector, FM
|
||||||
|
ACORN_525_SS_SD_80,
|
||||||
|
// 5,25", SS, DD, 40 tracks, 16 spt, 256 bytes/sector, MFM
|
||||||
|
ACORN_525_SS_DD_40,
|
||||||
|
// 5,25", SS, DD, 80 tracks, 16 spt, 256 bytes/sector, MFM
|
||||||
|
ACORN_525_SS_DD_80,
|
||||||
|
// 5,25", DS, DD, 80 tracks, 16 spt, 256 bytes/sector, MFM
|
||||||
|
ACORN_525_DS_DD,
|
||||||
|
// Atari standard floppy formats
|
||||||
|
// 5,25", SS, SD, 40 tracks, 18 spt, 128 bytes/sector, FM
|
||||||
|
ATARI_525_SD,
|
||||||
|
// 5,25", SS, ED, 40 tracks, 26 spt, 128 bytes/sector, MFM
|
||||||
|
ATARI_525_ED,
|
||||||
|
// 5,25", SS, DD, 40 tracks, 18 spt, 256 bytes/sector, MFM
|
||||||
|
ATARI_525_DD,
|
||||||
|
// Commodore standard floppy formats
|
||||||
|
// 3,5", DS, DD, 80 tracks, 10 spt, 512 bytes/sector, MFM
|
||||||
|
CBM_35_DD,
|
||||||
|
// 3,5", DS, DD, 80 tracks, 11 spt, 512 bytes/sector, MFM (Amiga)
|
||||||
|
CBM_AMIGA_35_DD,
|
||||||
|
// 3,5", DS, HD, 80 tracks, 22 spt, 512 bytes/sector, MFM (Amiga)
|
||||||
|
CBM_AMIGA_35_HD,
|
||||||
|
// NEC standard floppy formats
|
||||||
|
// 8", SS, SD, 77 tracks, 26 spt, 128 bytes/sector, FM
|
||||||
|
NEC_8_SD,
|
||||||
|
// 8", DS, DD, 77 tracks, 8 spt, 1024 bytes/sector, MFM
|
||||||
|
NEC_8_DD,
|
||||||
|
// 5,25", DS, HD, 80 tracks, 8 spt, 1024 bytes/sector, MFM
|
||||||
|
NEC_525_HD,
|
||||||
|
// 3,5", DS, HD, 80 tracks, 8 spt, 1024 bytes/sector, MFM
|
||||||
|
NEC_35_HD_8,
|
||||||
|
// 3,5", DS, HD, 80 tracks, 15 spt, 512 bytes/sector, MFM
|
||||||
|
NEC_35_HD_15,
|
||||||
|
// SHARP standard floppy formats
|
||||||
|
// 5,25", DS, DD, 77 tracks, 8 spt, 1024 bytes/sector, FM
|
||||||
|
SHARP_525,
|
||||||
|
// 3,5", DS, DD, 77 tracks, 8 spt, 1024 bytes/sector, FM
|
||||||
|
SHARP_35,
|
||||||
|
// ECMA standards
|
||||||
|
// 5,25", DS, DD, 80 tracks, 8 spt, 1024 bytes/sector, MFM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector
|
||||||
|
ECMA_99_8,
|
||||||
|
// 5,25", DS, DD, 77 tracks, 15 spt, 512 bytes/sector, MFM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector
|
||||||
|
ECMA_99_15,
|
||||||
|
// 5,25", DS, DD, 77 tracks, 26 spt, 256 bytes/sector, MFM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector
|
||||||
|
ECMA_99_26,
|
||||||
|
// 3,5", DS, DD, 80 tracks, 9 spt, 512 bytes/sector, MFM
|
||||||
|
ECMA_100,
|
||||||
|
// 3,5", DS, HD, 80 tracks, 18 spt, 512 bytes/sector, MFM
|
||||||
|
ECMA_125,
|
||||||
|
// 3,5", DS, ED, 80 tracks, 36 spt, 512 bytes/sector, MFM
|
||||||
|
ECMA_147,
|
||||||
|
// 8", SS, SD, 77 tracks, 26 spt, 128 bytes/sector, FM
|
||||||
|
ECMA_54,
|
||||||
|
// 8", DS, SD, 77 tracks, 26 spt, 128 bytes/sector, FM
|
||||||
|
ECMA_59,
|
||||||
|
// 5,25", SS, DD, 35 tracks, 9 spt, 256 bytes/sector, FM, track 0 side 0 = 16 sectors, 128 bytes/sector
|
||||||
|
ECMA_66,
|
||||||
|
// 8", DS, DD, 77 tracks, 8 spt, 1024 bytes/sector, FM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector
|
||||||
|
ECMA_69_8,
|
||||||
|
// 8", DS, DD, 77 tracks, 15 spt, 512 bytes/sector, FM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector
|
||||||
|
ECMA_69_15,
|
||||||
|
// 8", DS, DD, 77 tracks, 26 spt, 256 bytes/sector, FM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector
|
||||||
|
ECMA_69_26,
|
||||||
|
// 5,25", DS, DD, 40 tracks, 16 spt, 256 bytes/sector, FM, track 0 side 0 = 16 sectors, 128 bytes/sector, track 0 side 1 = 16 sectors, 256 bytes/sector
|
||||||
|
ECMA_70,
|
||||||
|
// 5,25", DS, DD, 80 tracks, 16 spt, 256 bytes/sector, FM, track 0 side 0 = 16 sectors, 128 bytes/sector, track 0 side 1 = 16 sectors, 256 bytes/sector
|
||||||
|
ECMA_78,
|
||||||
|
// 5,25", DS, DD, 80 tracks, 9 spt, 512 bytes/sector, FM
|
||||||
|
ECMA_78_2,
|
||||||
|
// 3,5", M.O., 250000 sectors, 512 bytes/sector
|
||||||
|
ECMA_154,
|
||||||
|
// 5,25", M.O., 940470 sectors, 512 bytes/sector
|
||||||
|
ECMA_183_512,
|
||||||
|
// 5,25", M.O., 520902 sectors, 1024 bytes/sector
|
||||||
|
ECMA_183_1024,
|
||||||
|
// 5,25", M.O., 1165600 sectors, 512 bytes/sector
|
||||||
|
ECMA_184_512,
|
||||||
|
// 5,25", M.O., 639200 sectors, 1024 bytes/sector
|
||||||
|
ECMA_184_1024,
|
||||||
|
// 3,5", M.O., 448500 sectors, 512 bytes/sector
|
||||||
|
ECMA_201,
|
||||||
|
// FDFORMAT, non-standard floppy formats
|
||||||
|
// 5,25", DS, DD, 82 tracks, 10 spt, 512 bytes/sector, MFM
|
||||||
|
FDFORMAT_525_DD
|
||||||
};
|
};
|
||||||
// Track (as partitioning element) types
|
// Track (as partitioning element) types
|
||||||
public enum TrackType
|
public enum TrackType
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ using System.IO;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
// Created following notes from Dave Dunfield
|
// Created following notes from Dave Dunfield
|
||||||
|
// http://www.classiccmp.org/dunfield/img54306/td0notes.txt
|
||||||
namespace FileSystemIDandChk.ImagePlugins
|
namespace FileSystemIDandChk.ImagePlugins
|
||||||
{
|
{
|
||||||
class TeleDisk : ImagePlugin
|
class TeleDisk : ImagePlugin
|
||||||
@@ -193,7 +194,12 @@ namespace FileSystemIDandChk.ImagePlugins
|
|||||||
string comment;
|
string comment;
|
||||||
DateTime creationDate;
|
DateTime creationDate;
|
||||||
DateTime modificationDate;
|
DateTime modificationDate;
|
||||||
|
Dictionary<UInt32, byte[]> sectorsData; // LBA, data
|
||||||
|
UInt32 totalDiskSize;
|
||||||
|
UInt64 imageSizeWithoutHeaders;
|
||||||
|
string imageName;
|
||||||
|
string telediskVersion;
|
||||||
|
UInt32 biggestSectorSize;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public TeleDisk(PluginBase Core)
|
public TeleDisk(PluginBase Core)
|
||||||
@@ -286,6 +292,9 @@ namespace FileSystemIDandChk.ImagePlugins
|
|||||||
header.dosAllocation = headerBytes[8];
|
header.dosAllocation = headerBytes[8];
|
||||||
header.sides = headerBytes[9];
|
header.sides = headerBytes[9];
|
||||||
header.crc = BitConverter.ToUInt16(headerBytes, 10);
|
header.crc = BitConverter.ToUInt16(headerBytes, 10);
|
||||||
|
|
||||||
|
imageName = Path.GetFileNameWithoutExtension(imagePath);
|
||||||
|
telediskVersion = String.Format("{0}.{1}", (header.version & 0xF0) >> 4, header.version & 0x0F);
|
||||||
|
|
||||||
byte[] headerBytesForCRC = new byte[10];
|
byte[] headerBytesForCRC = new byte[10];
|
||||||
Array.Copy(headerBytes, headerBytesForCRC, 10);
|
Array.Copy(headerBytes, headerBytesForCRC, 10);
|
||||||
@@ -398,7 +407,165 @@ namespace FileSystemIDandChk.ImagePlugins
|
|||||||
Console.WriteLine("DEBUG (TeleDisk plugin): Image modified on {0}", modificationDate);
|
Console.WriteLine("DEBUG (TeleDisk plugin): Image modified on {0}", modificationDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
if (MainClass.isDebug)
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): Parsing image");
|
||||||
|
|
||||||
|
totalDiskSize = 0;
|
||||||
|
byte spt = 0;
|
||||||
|
imageSizeWithoutHeaders = 0;
|
||||||
|
sectorsData = new Dictionary<uint, byte[]>();
|
||||||
|
biggestSectorSize = 0;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
TDTrackHeader TDTrack = new TDTrackHeader();
|
||||||
|
byte[] TDTrackForCRC = new byte[3];
|
||||||
|
byte TDTrackCalculatedCRC;
|
||||||
|
|
||||||
|
TDTrack.sectors = (byte)stream.ReadByte();
|
||||||
|
TDTrack.cylinder = (byte)stream.ReadByte();
|
||||||
|
TDTrack.head = (byte)stream.ReadByte();
|
||||||
|
TDTrack.crc = (byte)stream.ReadByte();
|
||||||
|
|
||||||
|
TDTrackForCRC[0] = TDTrack.sectors;
|
||||||
|
TDTrackForCRC[1] = TDTrack.cylinder;
|
||||||
|
TDTrackForCRC[2] = TDTrack.head;
|
||||||
|
|
||||||
|
TDTrackCalculatedCRC = (byte)(TeleDiskCRC(0, TDTrackForCRC) & 0xFF);
|
||||||
|
|
||||||
|
if (MainClass.isDebug)
|
||||||
|
{
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): Track follows");
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): \tTrack cylinder: {0}\t", TDTrack.cylinder);
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): \tTrack head: {0}\t", TDTrack.head);
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): \tSectors in track: {0}\t", TDTrack.sectors);
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): \tTrack header CRC: 0x{0:X2} (calculated 0x{1:X2})\t", TDTrack.crc, TDTrackCalculatedCRC);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TDTrack.sectors == 0xFF) // End of disk image
|
||||||
|
{
|
||||||
|
if (MainClass.isDebug)
|
||||||
|
{
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): End of disk image arrived");
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): Total of {0} data sectors, for {1} bytes", sectorsData.Count, totalDiskSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spt != TDTrack.sectors)
|
||||||
|
{
|
||||||
|
if (spt != 0)
|
||||||
|
throw new FeatureUnsupportedImageException("Variable number of sectors per track. This kind of image is not yet supported");
|
||||||
|
else
|
||||||
|
spt = TDTrack.sectors;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (byte processedSectors = 0; processedSectors < TDTrack.sectors; processedSectors++)
|
||||||
|
{
|
||||||
|
TDSectorHeader TDSector = new TDSectorHeader();
|
||||||
|
TDDataHeader TDData = new TDDataHeader();
|
||||||
|
byte[] dataSizeBytes = new byte[2];
|
||||||
|
byte[] data;
|
||||||
|
byte[] decodedData;
|
||||||
|
|
||||||
|
TDSector.cylinder = (byte)stream.ReadByte();
|
||||||
|
TDSector.head = (byte)stream.ReadByte();
|
||||||
|
TDSector.sectorNumber = (byte)stream.ReadByte();
|
||||||
|
TDSector.sectorSize = (byte)stream.ReadByte();
|
||||||
|
TDSector.flags = (byte)stream.ReadByte();
|
||||||
|
TDSector.crc = (byte)stream.ReadByte();
|
||||||
|
|
||||||
|
if (MainClass.isDebug)
|
||||||
|
{
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): \tSector follows");
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): \t\tAddressMark cylinder: {0}", TDSector.cylinder);
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): \t\tAddressMark head: {0}", TDSector.head);
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): \t\tAddressMark sector number: {0}", TDSector.sectorNumber);
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): \t\tSector size: {0}", TDSector.sectorSize);
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): \t\tSector flags: 0x{0:X2}", TDSector.flags);
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): \t\tSector CRC (plus headers): 0x{0:X2}", TDSector.crc);
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt32 LBA = (uint)((TDSector.cylinder * header.sides * spt) + (TDSector.head * spt) + (TDSector.sectorNumber - 1));
|
||||||
|
if ((TDSector.flags & FlagsSectorDataless) != FlagsSectorDataless && (TDSector.flags & FlagsSectorSkipped) != FlagsSectorSkipped)
|
||||||
|
{
|
||||||
|
stream.Read(dataSizeBytes, 0, 2);
|
||||||
|
TDData.dataSize = BitConverter.ToUInt16(dataSizeBytes, 0);
|
||||||
|
TDData.dataSize--; // Sydex decided to including dataEncoding byte as part of it
|
||||||
|
imageSizeWithoutHeaders += TDData.dataSize;
|
||||||
|
TDData.dataEncoding = (byte)stream.ReadByte();
|
||||||
|
data = new byte[TDData.dataSize];
|
||||||
|
stream.Read(data, 0, TDData.dataSize);
|
||||||
|
if (MainClass.isDebug)
|
||||||
|
{
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): \t\tData size (in-image): {0}", TDData.dataSize);
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): \t\tData encoding: 0x{0:X2}", TDData.dataEncoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
decodedData = DecodeTeleDiskData(TDSector.sectorSize, TDData.dataEncoding, data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (TDSector.sectorSize)
|
||||||
|
{
|
||||||
|
case SectorSize128:
|
||||||
|
decodedData = new byte[128];
|
||||||
|
break;
|
||||||
|
case SectorSize256:
|
||||||
|
decodedData = new byte[256];
|
||||||
|
break;
|
||||||
|
case SectorSize512:
|
||||||
|
decodedData = new byte[512];
|
||||||
|
break;
|
||||||
|
case SectorSize1K:
|
||||||
|
decodedData = new byte[1024];
|
||||||
|
break;
|
||||||
|
case SectorSize2K:
|
||||||
|
decodedData = new byte[2048];
|
||||||
|
break;
|
||||||
|
case SectorSize4K:
|
||||||
|
decodedData = new byte[4096];
|
||||||
|
break;
|
||||||
|
case SectorSize8K:
|
||||||
|
decodedData = new byte[8192];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ImageNotSupportedException(String.Format("Sector size {0} for cylinder {1} head {2} sector {3} is incorrect.",
|
||||||
|
TDSector.sectorSize, TDSector.cylinder, TDSector.head, TDSector.sectorNumber));
|
||||||
|
}
|
||||||
|
ArrayHelpers.ArrayFill(decodedData, (byte)0);
|
||||||
|
}
|
||||||
|
if (MainClass.isDebug)
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): \t\tLBA: {0}", LBA);
|
||||||
|
|
||||||
|
if ((TDSector.flags & FlagsSectorNoID) != FlagsSectorNoID)
|
||||||
|
{
|
||||||
|
if (sectorsData.ContainsKey(LBA))
|
||||||
|
{
|
||||||
|
if ((TDSector.flags & FlagsSectorDuplicate) == FlagsSectorDuplicate)
|
||||||
|
{
|
||||||
|
if (MainClass.isDebug)
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): \t\tSector {0} on cylinder {1} head {2} is duplicate, and marked so",
|
||||||
|
TDSector.sectorNumber, TDSector.cylinder, TDSector.head);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (MainClass.isDebug)
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): \t\tSector {0} on cylinder {1} head {2} is duplicate, but is not marked so",
|
||||||
|
TDSector.sectorNumber, TDSector.cylinder, TDSector.head);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sectorsData.Add(LBA, decodedData);
|
||||||
|
totalDiskSize += (uint)decodedData.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (decodedData.Length > biggestSectorSize)
|
||||||
|
biggestSectorSize = (uint)decodedData.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool ImageHasPartitions()
|
public override bool ImageHasPartitions()
|
||||||
@@ -408,17 +575,17 @@ namespace FileSystemIDandChk.ImagePlugins
|
|||||||
|
|
||||||
public override UInt64 GetImageSize()
|
public override UInt64 GetImageSize()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("Not yet implemented.");
|
return this.imageSizeWithoutHeaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override UInt64 GetSectors()
|
public override UInt64 GetSectors()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("Not yet implemented.");
|
return (ulong)this.sectorsData.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override UInt32 GetSectorSize()
|
public override UInt32 GetSectorSize()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("Not yet implemented.");
|
return this.biggestSectorSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override byte[] ReadSector(UInt64 sectorAddress)
|
public override byte[] ReadSector(UInt64 sectorAddress)
|
||||||
@@ -428,7 +595,35 @@ namespace FileSystemIDandChk.ImagePlugins
|
|||||||
|
|
||||||
public override byte[] ReadSectors(UInt64 sectorAddress, UInt32 length)
|
public override byte[] ReadSectors(UInt64 sectorAddress, UInt32 length)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("Not yet implemented.");
|
byte[] data = new byte[1]; // To make compiler happy
|
||||||
|
bool first = true;
|
||||||
|
int dataPosition = 0;
|
||||||
|
|
||||||
|
for (ulong i = sectorAddress; i < (sectorAddress + length); i++)
|
||||||
|
{
|
||||||
|
if (!this.sectorsData.ContainsKey((uint)i))
|
||||||
|
throw new ImageNotSupportedException(String.Format("Requested sector {0} not found", i));
|
||||||
|
|
||||||
|
byte[] sector;
|
||||||
|
|
||||||
|
if(!this.sectorsData.TryGetValue((uint)i, out sector))
|
||||||
|
throw new ImageNotSupportedException(String.Format("Error reading sector {0}", i));
|
||||||
|
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
data = new byte[sector.Length];
|
||||||
|
Array.Copy(sector, data, sector.Length);
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Array.Resize(ref data, dataPosition + sector.Length);
|
||||||
|
Array.Copy(sector, 0, data, dataPosition, sector.Length);
|
||||||
|
}
|
||||||
|
dataPosition += sector.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override byte[] ReadSectorLong(UInt64 sectorAddress)
|
public override byte[] ReadSectorLong(UInt64 sectorAddress)
|
||||||
@@ -448,7 +643,7 @@ namespace FileSystemIDandChk.ImagePlugins
|
|||||||
|
|
||||||
public override string GetImageVersion()
|
public override string GetImageVersion()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("Not yet implemented.");
|
return this.telediskVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string GetImageApplication()
|
public override string GetImageApplication()
|
||||||
@@ -458,26 +653,203 @@ namespace FileSystemIDandChk.ImagePlugins
|
|||||||
|
|
||||||
public override string GetImageApplicationVersion()
|
public override string GetImageApplicationVersion()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("Not yet implemented.");
|
return this.telediskVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override DateTime GetImageCreationTime()
|
public override DateTime GetImageCreationTime()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("Not yet implemented.");
|
return this.creationDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override DateTime GetImageLastModificationTime()
|
public override DateTime GetImageLastModificationTime()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("Not yet implemented.");
|
return this.modificationDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string GetImageName()
|
public override string GetImageName()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException("Not yet implemented.");
|
return this.imageName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override DiskType GetDiskType()
|
public override DiskType GetDiskType()
|
||||||
{
|
{
|
||||||
|
switch (this.header.driveType)
|
||||||
|
{
|
||||||
|
case DriveType525DD:
|
||||||
|
case DriveType525HD_DDDisk:
|
||||||
|
case DriveType525HD:
|
||||||
|
{
|
||||||
|
switch (this.totalDiskSize)
|
||||||
|
{
|
||||||
|
case 163840:
|
||||||
|
{
|
||||||
|
// Acorn disk uses 256 bytes/sector
|
||||||
|
if(this.biggestSectorSize == 256)
|
||||||
|
return DiskType.ACORN_525_SS_DD_40;
|
||||||
|
else // DOS disks use 512 bytes/sector
|
||||||
|
return DiskType.DOS_525_SS_DD_8;
|
||||||
|
}
|
||||||
|
case 184320:
|
||||||
|
{
|
||||||
|
// Atari disk uses 256 bytes/sector
|
||||||
|
if(this.biggestSectorSize == 256)
|
||||||
|
return DiskType.ATARI_525_DD;
|
||||||
|
else // DOS disks use 512 bytes/sector
|
||||||
|
return DiskType.DOS_525_SS_DD_9;
|
||||||
|
}
|
||||||
|
case 327680:
|
||||||
|
{
|
||||||
|
// Acorn disk uses 256 bytes/sector
|
||||||
|
if(this.biggestSectorSize == 256)
|
||||||
|
return DiskType.ACORN_525_SS_DD_80;
|
||||||
|
else // DOS disks use 512 bytes/sector
|
||||||
|
return DiskType.DOS_525_DS_DD_8;
|
||||||
|
}
|
||||||
|
case 368640:
|
||||||
|
return DiskType.DOS_525_DS_DD_9;
|
||||||
|
case 1228800:
|
||||||
|
return DiskType.DOS_525_HD;
|
||||||
|
case 102400:
|
||||||
|
return DiskType.ACORN_525_SS_SD_40;
|
||||||
|
case 204800:
|
||||||
|
return DiskType.ACORN_525_SS_SD_80;
|
||||||
|
case 655360:
|
||||||
|
return DiskType.ACORN_525_DS_DD;
|
||||||
|
case 92160:
|
||||||
|
return DiskType.ATARI_525_SD;
|
||||||
|
case 133120:
|
||||||
|
return DiskType.ATARI_525_ED;
|
||||||
|
case 1310720:
|
||||||
|
return DiskType.NEC_525_HD;
|
||||||
|
case 1261568:
|
||||||
|
return DiskType.SHARP_525;
|
||||||
|
case 839680:
|
||||||
|
return DiskType.FDFORMAT_525_DD;
|
||||||
|
case 1304320:
|
||||||
|
return DiskType.ECMA_99_8;
|
||||||
|
case 1223424:
|
||||||
|
return DiskType.ECMA_99_15;
|
||||||
|
case 1061632:
|
||||||
|
return DiskType.ECMA_99_26;
|
||||||
|
case 80384:
|
||||||
|
return DiskType.ECMA_66;
|
||||||
|
case 325632:
|
||||||
|
return DiskType.ECMA_70;
|
||||||
|
case 653312:
|
||||||
|
return DiskType.ECMA_78;
|
||||||
|
case 737280:
|
||||||
|
return DiskType.ECMA_78_2;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
if (MainClass.isDebug)
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): Unknown 5,25\" disk with {0} bytes", this.totalDiskSize);
|
||||||
|
return DiskType.Unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DriveType35DD:
|
||||||
|
case DriveType35ED:
|
||||||
|
case DriveType35HD:
|
||||||
|
{
|
||||||
|
switch (this.totalDiskSize)
|
||||||
|
{
|
||||||
|
case 327680:
|
||||||
|
return DiskType.DOS_35_SS_DD_8;
|
||||||
|
case 368640:
|
||||||
|
return DiskType.DOS_35_SS_DD_9;
|
||||||
|
case 655360:
|
||||||
|
return DiskType.DOS_35_DS_DD_8;
|
||||||
|
case 737280:
|
||||||
|
return DiskType.DOS_35_DS_DD_9;
|
||||||
|
case 1474560:
|
||||||
|
return DiskType.DOS_35_HD;
|
||||||
|
case 2949120:
|
||||||
|
return DiskType.DOS_35_ED;
|
||||||
|
case 1720320:
|
||||||
|
return DiskType.DMF;
|
||||||
|
case 1763328:
|
||||||
|
return DiskType.DMF_82;
|
||||||
|
case 1884160: // Irreal size, seen as BIOS with TSR, 23 sectors/track
|
||||||
|
case 1860608: // Real data size, sum of all sectors
|
||||||
|
return DiskType.XDF_35;
|
||||||
|
case 819200:
|
||||||
|
return DiskType.CBM_35_DD;
|
||||||
|
case 901120:
|
||||||
|
return DiskType.CBM_AMIGA_35_DD;
|
||||||
|
case 1802240:
|
||||||
|
return DiskType.CBM_AMIGA_35_HD;
|
||||||
|
case 1310720:
|
||||||
|
return DiskType.NEC_35_HD_8;
|
||||||
|
case 1228800:
|
||||||
|
return DiskType.NEC_35_HD_15;
|
||||||
|
case 1261568:
|
||||||
|
return DiskType.SHARP_35;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
if (MainClass.isDebug)
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): Unknown 3,5\" disk with {0} bytes", this.totalDiskSize);
|
||||||
|
return DiskType.Unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case DriveType8inch:
|
||||||
|
{
|
||||||
|
switch (this.totalDiskSize)
|
||||||
|
{
|
||||||
|
case 81664:
|
||||||
|
return DiskType.IBM23FD;
|
||||||
|
case 242944:
|
||||||
|
return DiskType.IBM33FD_128;
|
||||||
|
case 287488:
|
||||||
|
return DiskType.IBM33FD_256;
|
||||||
|
case 306432:
|
||||||
|
return DiskType.IBM33FD_512;
|
||||||
|
case 499200:
|
||||||
|
return DiskType.IBM43FD_128;
|
||||||
|
case 574976:
|
||||||
|
return DiskType.IBM43FD_256;
|
||||||
|
case 995072:
|
||||||
|
return DiskType.IBM53FD_256;
|
||||||
|
case 1146624:
|
||||||
|
return DiskType.IBM53FD_512;
|
||||||
|
case 1222400:
|
||||||
|
return DiskType.IBM53FD_1024;
|
||||||
|
case 256256:
|
||||||
|
// Same size, with same disk geometry, for DEC RX01, NEC and ECMA, return ECMA
|
||||||
|
return DiskType.ECMA_54;
|
||||||
|
case 512512:
|
||||||
|
{
|
||||||
|
// DEC disk uses 256 bytes/sector
|
||||||
|
if(this.biggestSectorSize == 256)
|
||||||
|
return DiskType.RX02;
|
||||||
|
else // ECMA disks use 128 bytes/sector
|
||||||
|
return DiskType.ECMA_59;
|
||||||
|
}
|
||||||
|
case 1261568:
|
||||||
|
return DiskType.NEC_8_DD;
|
||||||
|
case 1255168:
|
||||||
|
return DiskType.ECMA_69_8;
|
||||||
|
case 1177344:
|
||||||
|
return DiskType.ECMA_69_15;
|
||||||
|
case 1021696:
|
||||||
|
return DiskType.ECMA_69_26;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
if (MainClass.isDebug)
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): Unknown 8\" disk with {0} bytes", this.totalDiskSize);
|
||||||
|
return DiskType.Unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
if (MainClass.isDebug)
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): Unknown drive type {1} with {0} bytes", this.totalDiskSize, this.header.driveType);
|
||||||
|
return DiskType.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
throw new NotImplementedException("Not yet implemented.");
|
throw new NotImplementedException("Not yet implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -503,6 +875,116 @@ namespace FileSystemIDandChk.ImagePlugins
|
|||||||
|
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static byte[] DecodeTeleDiskData(byte sectorSize, byte encodingType, byte[] encodedData)
|
||||||
|
{
|
||||||
|
byte[] decodedData;
|
||||||
|
switch (sectorSize)
|
||||||
|
{
|
||||||
|
case SectorSize128:
|
||||||
|
decodedData = new byte[128];
|
||||||
|
break;
|
||||||
|
case SectorSize256:
|
||||||
|
decodedData = new byte[256];
|
||||||
|
break;
|
||||||
|
case SectorSize512:
|
||||||
|
decodedData = new byte[512];
|
||||||
|
break;
|
||||||
|
case SectorSize1K:
|
||||||
|
decodedData = new byte[1024];
|
||||||
|
break;
|
||||||
|
case SectorSize2K:
|
||||||
|
decodedData = new byte[2048];
|
||||||
|
break;
|
||||||
|
case SectorSize4K:
|
||||||
|
decodedData = new byte[4096];
|
||||||
|
break;
|
||||||
|
case SectorSize8K:
|
||||||
|
decodedData = new byte[8192];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ImageNotSupportedException(String.Format("Sector size {0} is incorrect.", sectorSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (encodingType)
|
||||||
|
{
|
||||||
|
case dataBlockCopy:
|
||||||
|
Array.Copy(encodedData, decodedData, decodedData.Length);
|
||||||
|
break;
|
||||||
|
case dataBlockPattern:
|
||||||
|
{
|
||||||
|
int ins = 0;
|
||||||
|
int outs = 0;
|
||||||
|
while (ins < encodedData.Length)
|
||||||
|
{
|
||||||
|
UInt16 repeatNumber;
|
||||||
|
byte[] repeatValue = new byte[2];
|
||||||
|
|
||||||
|
repeatNumber = BitConverter.ToUInt16(encodedData, ins);
|
||||||
|
Array.Copy(encodedData, ins + 2, repeatValue, 0, 2);
|
||||||
|
byte[] decodedPiece = new byte[repeatNumber*2];
|
||||||
|
ArrayHelpers.ArrayFill(decodedPiece, repeatValue);
|
||||||
|
Array.Copy(decodedPiece, 0, decodedData, outs, decodedPiece.Length);
|
||||||
|
ins += 4;
|
||||||
|
outs += decodedPiece.Length;
|
||||||
|
}
|
||||||
|
if (MainClass.isDebug)
|
||||||
|
{
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): (Block pattern decoder): Input data size: {0} bytes", encodedData.Length);
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): (Block pattern decoder): Processed input: {0} bytes", ins);
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): (Block pattern decoder): Output data size: {0} bytes", decodedData.Length);
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): (Block pattern decoder): Processed Output: {0} bytes", outs);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case dataBlockRLE:
|
||||||
|
{
|
||||||
|
int ins = 0;
|
||||||
|
int outs = 0;
|
||||||
|
while (ins < encodedData.Length)
|
||||||
|
{
|
||||||
|
byte Run;
|
||||||
|
byte Length;
|
||||||
|
byte Encoding;
|
||||||
|
byte[] Piece;
|
||||||
|
|
||||||
|
Encoding = encodedData[ins];
|
||||||
|
if (Encoding == 0x00)
|
||||||
|
{
|
||||||
|
Length = encodedData[ins + 1];
|
||||||
|
Piece = new byte[Length];
|
||||||
|
Array.Copy(encodedData, ins + 2, decodedData, outs, Length);
|
||||||
|
ins += (2 + Length);
|
||||||
|
outs += Length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Length = (byte)(Encoding * 2);
|
||||||
|
Run = encodedData[ins + 1];
|
||||||
|
byte[] Part = new byte[Length];
|
||||||
|
Array.Copy(encodedData, ins + 2, Part, 0, Length);
|
||||||
|
Piece = new byte[Length * Run];
|
||||||
|
ArrayHelpers.ArrayFill(Piece, Part);
|
||||||
|
Array.Copy(Piece, 0, decodedData, outs, Piece.Length);
|
||||||
|
ins += (2 + Length);
|
||||||
|
outs += Piece.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (MainClass.isDebug)
|
||||||
|
{
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): (RLE decoder): Input data size: {0} bytes", encodedData.Length);
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): (RLE decoder): Processed input: {0} bytes", ins);
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): (RLE decoder): Output data size: {0} bytes", decodedData.Length);
|
||||||
|
Console.WriteLine("DEBUG (TeleDisk plugin): (RLE decoder): Processed Output: {0} bytes", outs);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new ImageNotSupportedException(String.Format("Data encoding {0} is incorrect.", encodingType));
|
||||||
|
}
|
||||||
|
|
||||||
|
return decodedData;
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Unsupported features
|
#region Unsupported features
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ namespace FileSystemIDandChk
|
|||||||
if (isDebug)
|
if (isDebug)
|
||||||
{
|
{
|
||||||
plugins.RegisterAllPlugins();
|
plugins.RegisterAllPlugins();
|
||||||
Runner("/Users/claunia/Desktop/disk_images/dc42.dc42");
|
Runner("/Users/claunia/Desktop/disk_images/teledisk.td0");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -169,6 +169,7 @@ namespace FileSystemIDandChk
|
|||||||
Console.WriteLine("DEBUG: Correctly opened image file.");
|
Console.WriteLine("DEBUG: Correctly opened image file.");
|
||||||
Console.WriteLine("DEBUG: Image without headers is {0} bytes.", _imageFormat.GetImageSize());
|
Console.WriteLine("DEBUG: Image without headers is {0} bytes.", _imageFormat.GetImageSize());
|
||||||
Console.WriteLine("DEBUG: Image has {0} sectors.", _imageFormat.GetSectors());
|
Console.WriteLine("DEBUG: Image has {0} sectors.", _imageFormat.GetSectors());
|
||||||
|
Console.WriteLine("DEBUG: Image identifies disk type as {0}.", _imageFormat.GetDiskType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
--- Add support for Alcohol images
|
--- Add support for Alcohol images
|
||||||
--- Add support for Nero images
|
--- Add support for Nero images
|
||||||
--- Add support for cdrdao images
|
--- Add support for cdrdao images
|
||||||
--- Add support for Teledisk images
|
|
||||||
--- Add support for dump(8) images
|
--- Add support for dump(8) images
|
||||||
--- Add support for IMD images
|
--- Add support for IMD images
|
||||||
--- Add support for Kryoflux images
|
--- Add support for Kryoflux images
|
||||||
@@ -47,6 +46,7 @@ Filesystem plugins:
|
|||||||
--- Add support for exFAT
|
--- Add support for exFAT
|
||||||
--- Add support for FAT+
|
--- Add support for FAT+
|
||||||
--- Add support for ReFS
|
--- Add support for ReFS
|
||||||
|
--- Add support for ECMA-67
|
||||||
|
|
||||||
Partitioning scheme plugins:
|
Partitioning scheme plugins:
|
||||||
--- Add support for Acorn partitions
|
--- Add support for Acorn partitions
|
||||||
@@ -62,4 +62,8 @@ Things to test/debug:
|
|||||||
--- After moving to disc images, HFS CDs with 512 bytes/sector are not detected anymore
|
--- After moving to disc images, HFS CDs with 512 bytes/sector are not detected anymore
|
||||||
|
|
||||||
Other things:
|
Other things:
|
||||||
--- Surprise!
|
--- Surprise!
|
||||||
|
|
||||||
|
Teledisk plugin:
|
||||||
|
--- Add support for "advanced compression"
|
||||||
|
--- Handle variable sectors per track situation. Teledisk seems to be able to read garbage from previous formattings.
|
||||||
Reference in New Issue
Block a user