REFACTOR: Reformat code.

This commit is contained in:
2017-12-19 20:33:03 +00:00
parent 77edc7c91c
commit e6f6ace80b
704 changed files with 82627 additions and 83641 deletions

View File

@@ -121,10 +121,8 @@ namespace DiscImageChef.Filesystems.CPM
{
Name = "CP/M File System";
PluginUUID = new Guid("AA2B8585-41DF-4E3B-8A35-D1A935E2F8A1");
if(encoding == null)
CurrentEncoding = Encoding.GetEncoding("IBM437");
else
CurrentEncoding = encoding;
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("IBM437");
else CurrentEncoding = encoding;
}
public CPM(ImagePlugin imagePlugin, Partition partition, Encoding encoding)
@@ -133,11 +131,8 @@ namespace DiscImageChef.Filesystems.CPM
this.partition = partition;
Name = "CP/M File System";
PluginUUID = new Guid("AA2B8585-41DF-4E3B-8A35-D1A935E2F8A1");
if(encoding == null)
CurrentEncoding = Encoding.GetEncoding("IBM437");
else
CurrentEncoding = encoding;
if(encoding == null) CurrentEncoding = Encoding.GetEncoding("IBM437");
else CurrentEncoding = encoding;
}
}
}
}

View File

@@ -81,5 +81,4 @@ namespace DiscImageChef.Filesystems.CPM
k720Alt = 0x94
}
}
}
}

View File

@@ -48,7 +48,9 @@ namespace DiscImageChef.Filesystems.CPM
{
try
{
XmlReader defsReader = XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream("DiscImageChef.Filesystems.CPM.cpmdefs.xml"));
XmlReader defsReader =
XmlReader.Create(Assembly.GetExecutingAssembly()
.GetManifestResourceStream("DiscImageChef.Filesystems.CPM.cpmdefs.xml"));
XmlSerializer defsSerializer = new XmlSerializer(typeof(CpmDefinitions));
definitions = (CpmDefinitions)defsSerializer.Deserialize(defsReader);
@@ -60,8 +62,7 @@ namespace DiscImageChef.Filesystems.CPM
def.side1 = new Side();
def.side1.sideId = 0;
def.side1.sectorIds = new int[def.sectorsPerTrack];
for(int i = 0; i < def.sectorsPerTrack; i++)
def.side1.sectorIds[i] = i + 1;
for(int i = 0; i < def.sectorsPerTrack; i++) def.side1.sectorIds[i] = i + 1;
}
if(def.sides == 2 && def.side2 == null)
@@ -69,17 +70,13 @@ namespace DiscImageChef.Filesystems.CPM
def.side2 = new Side();
def.side2.sideId = 1;
def.side2.sectorIds = new int[def.sectorsPerTrack];
for(int i = 0; i < def.sectorsPerTrack; i++)
def.side2.sectorIds[i] = i + 1;
for(int i = 0; i < def.sectorsPerTrack; i++) def.side2.sectorIds[i] = i + 1;
}
}
return true;
}
catch
{
return false;
}
catch { return false; }
}
}
@@ -211,5 +208,4 @@ namespace DiscImageChef.Filesystems.CPM
/// </summary>
public int[] sectorIds;
}
}
}

View File

@@ -41,8 +41,7 @@ namespace DiscImageChef.Filesystems.CPM
{
public override Errno ReadDir(string path, ref List<string> contents)
{
if(!mounted)
return Errno.AccessDenied;
if(!mounted) return Errno.AccessDenied;
if(!string.IsNullOrEmpty(path) && string.Compare(path, "/", StringComparison.OrdinalIgnoreCase) != 0)
return Errno.NotSupported;
@@ -64,8 +63,7 @@ namespace DiscImageChef.Filesystems.CPM
{
try
{
if(directory == null)
return false;
if(directory == null) return false;
int fileCount = 0;
@@ -81,31 +79,26 @@ namespace DiscImageChef.Filesystems.CPM
{
for(int f = 0; f < 8; f++)
{
if(entry.filename[f] < 0x20 && entry.filename[f] != 0x00)
return false;
if(entry.filename[f] < 0x20 && entry.filename[f] != 0x00) return false;
}
for(int e = 0; e < 3; e++)
{
if(entry.extension[e] < 0x20 && entry.extension[e] != 0x00)
return false;
if(entry.extension[e] < 0x20 && entry.extension[e] != 0x00) return false;
}
if(!ArrayHelpers.ArrayIsNullOrWhiteSpace(entry.filename))
fileCount++;
if(!ArrayHelpers.ArrayIsNullOrWhiteSpace(entry.filename)) fileCount++;
}
else if(entry.statusUser == 0x20)
{
for(int f = 0; f < 8; f++)
{
if(entry.filename[f] < 0x20 && entry.filename[f] != 0x00)
return false;
if(entry.filename[f] < 0x20 && entry.filename[f] != 0x00) return false;
}
for(int e = 0; e < 3; e++)
{
if(entry.extension[e] < 0x20 && entry.extension[e] != 0x00)
return false;
if(entry.extension[e] < 0x20 && entry.extension[e] != 0x00) return false;
}
label = Encoding.ASCII.GetString(directory, off + 1, 11).Trim();
@@ -116,21 +109,14 @@ namespace DiscImageChef.Filesystems.CPM
}
else if(entry.statusUser == 0x21)
{
if(directory[off + 1] == 0x00)
{
thirdPartyTimestamps = true;
}
if(directory[off + 1] == 0x00) { thirdPartyTimestamps = true; }
else standardTimestamps |= (directory[off + 21] == 0x00 && directory[off + 31] == 0x00);
}
}
return fileCount > 0;
}
catch
{
return false;
}
catch { return false; }
}
}
}
}

View File

@@ -38,16 +38,15 @@ namespace DiscImageChef.Filesystems.CPM
{
public override Errno GetAttributes(string path, ref FileAttributes attributes)
{
if(!mounted)
return Errno.AccessDenied;
if(!mounted) return Errno.AccessDenied;
string[] pathElements = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
if(pathElements.Length != 1)
return Errno.NotSupported;
string[] pathElements = path.Split(new char[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
if(pathElements.Length != 1) return Errno.NotSupported;
FileEntryInfo fInfo;
if(string.IsNullOrEmpty(pathElements[0]) || string.Compare(pathElements[0], "/", StringComparison.OrdinalIgnoreCase) == 0)
if(string.IsNullOrEmpty(pathElements[0]) ||
string.Compare(pathElements[0], "/", StringComparison.OrdinalIgnoreCase) == 0)
{
attributes = new FileAttributes();
attributes = FileAttributes.Directory;
@@ -65,8 +64,7 @@ namespace DiscImageChef.Filesystems.CPM
public override Errno MapBlock(string path, long fileBlock, ref long deviceBlock)
{
if(!mounted)
return Errno.AccessDenied;
if(!mounted) return Errno.AccessDenied;
// TODO: Implementing this would require storing the interleaving
return Errno.NotImplemented;
@@ -74,8 +72,7 @@ namespace DiscImageChef.Filesystems.CPM
public override Errno Read(string path, long offset, long size, ref byte[] buf)
{
if(!mounted)
return Errno.AccessDenied;
if(!mounted) return Errno.AccessDenied;
if(size == 0)
{
@@ -83,23 +80,18 @@ namespace DiscImageChef.Filesystems.CPM
return Errno.NoError;
}
if(offset < 0)
return Errno.InvalidArgument;
if(offset < 0) return Errno.InvalidArgument;
string[] pathElements = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
if(pathElements.Length != 1)
return Errno.NotSupported;
string[] pathElements = path.Split(new char[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
if(pathElements.Length != 1) return Errno.NotSupported;
byte[] file;
if(!fileCache.TryGetValue(pathElements[0].ToUpperInvariant(), out file))
return Errno.NoSuchFile;
if(!fileCache.TryGetValue(pathElements[0].ToUpperInvariant(), out file)) return Errno.NoSuchFile;
if(offset >= file.Length)
return Errno.EINVAL;
if(offset >= file.Length) return Errno.EINVAL;
if(size + offset >= file.Length)
size = file.Length - offset;
if(size + offset >= file.Length) size = file.Length - offset;
buf = new byte[size];
Array.Copy(file, offset, buf, 0, size);
@@ -108,38 +100,30 @@ namespace DiscImageChef.Filesystems.CPM
public override Errno ReadLink(string path, ref string dest)
{
if(!mounted)
return Errno.AccessDenied;
if(!mounted) return Errno.AccessDenied;
return Errno.NotSupported;
}
public override Errno Stat(string path, ref FileEntryInfo stat)
{
if(!mounted)
return Errno.AccessDenied;
if(!mounted) return Errno.AccessDenied;
string[] pathElements = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
if(pathElements.Length != 1)
return Errno.NotSupported;
string[] pathElements = path.Split(new char[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
if(pathElements.Length != 1) return Errno.NotSupported;
if(string.IsNullOrEmpty(path) || string.Compare(path, "/", StringComparison.OrdinalIgnoreCase) == 0)
{
if(labelCreationDate != null)
stat.CreationTime = DateHandlers.CPMToDateTime(labelCreationDate);
if(labelUpdateDate != null)
stat.StatusChangeTime = DateHandlers.CPMToDateTime(labelUpdateDate);
if(labelCreationDate != null) stat.CreationTime = DateHandlers.CPMToDateTime(labelCreationDate);
if(labelUpdateDate != null) stat.StatusChangeTime = DateHandlers.CPMToDateTime(labelUpdateDate);
stat.Attributes = FileAttributes.Directory;
stat.BlockSize = xmlFSType.ClusterSize;
return Errno.NoError;
}
if(statCache.TryGetValue(pathElements[0].ToUpperInvariant(), out stat))
return Errno.NoError;
if(statCache.TryGetValue(pathElements[0].ToUpperInvariant(), out stat)) return Errno.NoError;
return Errno.NoSuchFile;
}
}
}
}

View File

@@ -153,12 +153,10 @@ namespace DiscImageChef.Filesystems.CPM
case MediaType.RP06:
case MediaType.RP06_18:
case MediaType.GENERIC_HDD:
case MediaType.FlashDrive:
break;
default:
return false;
case MediaType.FlashDrive: break;
default: return false;
}
// This will try to identify a CP/M filesystem
// However as it contains no identification marks whatsoever it's more something of trial-and-error
// As anything can happen, better try{}catch{} than sorry ;)
@@ -186,8 +184,7 @@ namespace DiscImageChef.Filesystems.CPM
sig3 = BitConverter.ToUInt32(sector, 0x7C);
// PCW16 extended boot record
if(sig1 == 0x4D2F5043 && sig2 == 0x004B5344 && sig3 == sig1)
amsSbOffset = 0x80;
if(sig1 == 0x4D2F5043 && sig2 == 0x004B5344 && sig3 == sig1) amsSbOffset = 0x80;
// Read the superblock
AmstradSuperBlock amsSb = new AmstradSuperBlock();
@@ -207,8 +204,7 @@ namespace DiscImageChef.Filesystems.CPM
sectorSize = (ulong)(128 << amsSb.psh);
// Compare device limits from superblock to real limits
if(sectorSize == imagePlugin.GetSectorSize() &&
sectorCount == imagePlugin.GetSectors())
if(sectorSize == imagePlugin.GetSectorSize() && sectorCount == imagePlugin.GetSectors())
{
cpmFound = true;
firstDirectorySector = (ulong)((amsSb.off * amsSb.spt));
@@ -218,8 +214,8 @@ namespace DiscImageChef.Filesystems.CPM
dpb.al0 = sectorCount == 1440 ? (byte)0xF0 : (byte)0xC0;
dpb.spt = amsSb.spt;
dpb.bsh = amsSb.bsh;
for(int i = 0; i < dpb.bsh; i++)
dpb.blm += (byte)Math.Pow(2, i);
for(int i = 0; i < dpb.bsh; i++) dpb.blm += (byte)Math.Pow(2, i);
if(sectorCount >= 1440)
{
dpb.cks = 0x40;
@@ -234,11 +230,12 @@ namespace DiscImageChef.Filesystems.CPM
dpb.exm = sectorCount == 2880 ? (byte)1 : (byte)0;
dpb.off = amsSb.off;
dpb.psh = amsSb.psh;
for(int i = 0; i < dpb.psh; i++)
dpb.phm += (byte)Math.Pow(2, i);
for(int i = 0; i < dpb.psh; i++) dpb.phm += (byte)Math.Pow(2, i);
dpb.spt = (ushort)(amsSb.spt * (sectorSize / 128));
uint directoryLength = (uint)((((ulong)dpb.drm + 1) * 32) / sectorSize);
directory = imagePlugin.ReadSectors(firstDirectorySector + partition.Start, directoryLength);
directory = imagePlugin.ReadSectors(firstDirectorySector + partition.Start,
directoryLength);
// Build a CP/M disk definition
workingDefinition = new CpmDefinition();
@@ -262,26 +259,20 @@ namespace DiscImageChef.Filesystems.CPM
workingDefinition.side1 = new Side();
workingDefinition.side1.sideId = 0;
workingDefinition.side1.sectorIds = new int[amsSb.spt];
for(int si = 0; si < amsSb.spt; si++)
workingDefinition.side1.sectorIds[si] = si + 1;
for(int si = 0; si < amsSb.spt; si++) workingDefinition.side1.sectorIds[si] = si + 1;
if(amsSb.format == 2)
{
if((amsSb.sidedness & 0x02) == 1)
workingDefinition.order = "SIDES";
else if((amsSb.sidedness & 0x02) == 2)
workingDefinition.order = "CYLINDERS";
else
workingDefinition.order = null;
if((amsSb.sidedness & 0x02) == 1) workingDefinition.order = "SIDES";
else if((amsSb.sidedness & 0x02) == 2) workingDefinition.order = "CYLINDERS";
else workingDefinition.order = null;
workingDefinition.side2 = new Side();
workingDefinition.side2.sideId = 1;
workingDefinition.side2.sectorIds = new int[amsSb.spt];
for(int si = 0; si < amsSb.spt; si++)
workingDefinition.side2.sectorIds[si] = si + 1;
for(int si = 0; si < amsSb.spt; si++) workingDefinition.side2.sectorIds[si] = si + 1;
}
else
workingDefinition.order = null;
else workingDefinition.order = null;
workingDefinition.skew = 2;
workingDefinition.sofs = 0;
@@ -299,8 +290,7 @@ namespace DiscImageChef.Filesystems.CPM
ushort sum = 0;
// Sum of all 16-bit words that make this sector must be 0
for(int i = 0; i < sector.Length; i += 2)
sum += BitConverter.ToUInt16(sector, i);
for(int i = 0; i < sector.Length; i += 2) sum += BitConverter.ToUInt16(sector, i);
// It may happen that there is a corrupted superblock
// Better to ignore corrupted than to false positive the rest
@@ -316,11 +306,11 @@ namespace DiscImageChef.Filesystems.CPM
// Calculate volume size
sectorSize = (ulong)(hddSb.recordsPerSector * 128);
ulong sectorsInPartition = (ulong)(hddSb.cylinders * hddSb.heads * hddSb.sectorsPerTrack);
ulong startingSector = (ulong)((hddSb.firstCylinder * hddSb.heads + hddSb.heads) * hddSb.sectorsPerTrack);
ulong startingSector =
(ulong)((hddSb.firstCylinder * hddSb.heads + hddSb.heads) * hddSb.sectorsPerTrack);
// If volume size corresponds with working partition (this variant will be inside MBR partitioning)
if(sectorSize == imagePlugin.GetSectorSize() &&
startingSector == partition.Start &&
if(sectorSize == imagePlugin.GetSectorSize() && startingSector == partition.Start &&
sectorsInPartition + partition.Start <= partition.End)
{
cpmFound = true;
@@ -341,7 +331,8 @@ namespace DiscImageChef.Filesystems.CPM
dpb.psh = 0; // Needed?
dpb.spt = hddSb.spt;
uint directoryLength = (uint)((((ulong)dpb.drm + 1) * 32) / sectorSize);
directory = imagePlugin.ReadSectors(firstDirectorySector + partition.Start, directoryLength);
directory = imagePlugin.ReadSectors(firstDirectorySector + partition.Start,
directoryLength);
DicConsole.DebugWriteLine("CP/M Plugin", "Found CP/M-86 hard disk superblock.");
// Build a CP/M disk definition
@@ -367,12 +358,13 @@ namespace DiscImageChef.Filesystems.CPM
workingDefinition.side1.sectorIds = new int[hddSb.sectorsPerTrack];
for(int si = 0; si < hddSb.sectorsPerTrack; si++)
workingDefinition.side1.sectorIds[si] = si + 1;
workingDefinition.order = "SIDES";
workingDefinition.side2 = new Side();
workingDefinition.side2.sideId = 1;
workingDefinition.side2.sectorIds = new int[hddSb.sectorsPerTrack];
for(int si = 0; si < hddSb.spt; si++)
workingDefinition.side2.sectorIds[si] = si + 1;
for(int si = 0; si < hddSb.spt; si++) workingDefinition.side2.sectorIds[si] = si + 1;
workingDefinition.skew = 0;
workingDefinition.sofs = 0;
}
@@ -389,13 +381,10 @@ namespace DiscImageChef.Filesystems.CPM
// Check for alternate location of format ID
if(sector.Last() == 0x00 || sector.Last() == 0xFF)
{
if(sector[0x40] == 0x94 || sector[0x40] == 0x26)
formatByte = sector[0x40];
else
formatByte = sector.Last();
if(sector[0x40] == 0x94 || sector[0x40] == 0x26) formatByte = sector[0x40];
else formatByte = sector.Last();
}
else
formatByte = sector.Last();
else formatByte = sector.Last();
uint firstDirectorySector86 = 0;
@@ -445,11 +434,12 @@ namespace DiscImageChef.Filesystems.CPM
workingDefinition.side1 = new Side();
workingDefinition.side1.sideId = 0;
workingDefinition.side1.sectorIds = new int[8];
for(int si = 0; si < 8; si++)
workingDefinition.side1.sectorIds[si] = si + 1;
for(int si = 0; si < 8; si++) workingDefinition.side1.sectorIds[si] = si + 1;
workingDefinition.skew = 0;
workingDefinition.sofs = 0;
}
break;
case FormatByte.k320:
if(imagePlugin.GetSectorSize() == 512 && imagePlugin.GetSectors() == 640)
@@ -490,17 +480,18 @@ namespace DiscImageChef.Filesystems.CPM
workingDefinition.side1 = new Side();
workingDefinition.side1.sideId = 0;
workingDefinition.side1.sectorIds = new int[8];
for(int si = 0; si < 8; si++)
workingDefinition.side1.sectorIds[si] = si + 1;
for(int si = 0; si < 8; si++) workingDefinition.side1.sectorIds[si] = si + 1;
workingDefinition.order = "SIDES";
workingDefinition.side2 = new Side();
workingDefinition.side2.sideId = 1;
workingDefinition.side2.sectorIds = new int[8];
for(int si = 0; si < 8; si++)
workingDefinition.side2.sectorIds[si] = si + 1;
for(int si = 0; si < 8; si++) workingDefinition.side2.sectorIds[si] = si + 1;
workingDefinition.skew = 0;
workingDefinition.sofs = 0;
}
break;
case FormatByte.k360:
case FormatByte.k360Alt:
@@ -543,17 +534,18 @@ namespace DiscImageChef.Filesystems.CPM
workingDefinition.side1 = new Side();
workingDefinition.side1.sideId = 0;
workingDefinition.side1.sectorIds = new int[9];
for(int si = 0; si < 9; si++)
workingDefinition.side1.sectorIds[si] = si + 1;
for(int si = 0; si < 9; si++) workingDefinition.side1.sectorIds[si] = si + 1;
workingDefinition.order = "SIDES";
workingDefinition.side2 = new Side();
workingDefinition.side2.sideId = 1;
workingDefinition.side2.sectorIds = new int[9];
for(int si = 0; si < 9; si++)
workingDefinition.side2.sectorIds[si] = si + 1;
for(int si = 0; si < 9; si++) workingDefinition.side2.sectorIds[si] = si + 1;
workingDefinition.skew = 0;
workingDefinition.sofs = 0;
}
break;
case FormatByte.k720:
case FormatByte.k720Alt:
@@ -595,17 +587,18 @@ namespace DiscImageChef.Filesystems.CPM
workingDefinition.side1 = new Side();
workingDefinition.side1.sideId = 0;
workingDefinition.side1.sectorIds = new int[9];
for(int si = 0; si < 9; si++)
workingDefinition.side1.sectorIds[si] = si + 1;
for(int si = 0; si < 9; si++) workingDefinition.side1.sectorIds[si] = si + 1;
workingDefinition.order = "SIDES";
workingDefinition.side2 = new Side();
workingDefinition.side2.sideId = 1;
workingDefinition.side2.sectorIds = new int[9];
for(int si = 0; si < 9; si++)
workingDefinition.side2.sectorIds[si] = si + 1;
for(int si = 0; si < 9; si++) workingDefinition.side2.sectorIds[si] = si + 1;
workingDefinition.skew = 0;
workingDefinition.sofs = 0;
}
break;
case FormatByte.f720:
if(imagePlugin.GetSectorSize() == 512 && imagePlugin.GetSectors() == 1440)
@@ -646,17 +639,18 @@ namespace DiscImageChef.Filesystems.CPM
workingDefinition.side1 = new Side();
workingDefinition.side1.sideId = 0;
workingDefinition.side1.sectorIds = new int[9];
for(int si = 0; si < 9; si++)
workingDefinition.side1.sectorIds[si] = si + 1;
for(int si = 0; si < 9; si++) workingDefinition.side1.sectorIds[si] = si + 1;
workingDefinition.order = "CYLINDERS";
workingDefinition.side2 = new Side();
workingDefinition.side2.sideId = 1;
workingDefinition.side2.sectorIds = new int[9];
for(int si = 0; si < 9; si++)
workingDefinition.side2.sectorIds[si] = si + 1;
for(int si = 0; si < 9; si++) workingDefinition.side2.sectorIds[si] = si + 1;
workingDefinition.skew = 0;
workingDefinition.sofs = 0;
}
break;
case FormatByte.f1200:
if(imagePlugin.GetSectorSize() == 512 && imagePlugin.GetSectors() == 2400)
@@ -697,17 +691,18 @@ namespace DiscImageChef.Filesystems.CPM
workingDefinition.side1 = new Side();
workingDefinition.side1.sideId = 0;
workingDefinition.side1.sectorIds = new int[15];
for(int si = 0; si < 15; si++)
workingDefinition.side1.sectorIds[si] = si + 1;
for(int si = 0; si < 15; si++) workingDefinition.side1.sectorIds[si] = si + 1;
workingDefinition.order = "CYLINDERS";
workingDefinition.side2 = new Side();
workingDefinition.side2.sideId = 1;
workingDefinition.side2.sectorIds = new int[15];
for(int si = 0; si < 15; si++)
workingDefinition.side2.sectorIds[si] = si + 1;
for(int si = 0; si < 15; si++) workingDefinition.side2.sectorIds[si] = si + 1;
workingDefinition.skew = 0;
workingDefinition.sofs = 0;
}
break;
case FormatByte.f1440:
if(imagePlugin.GetSectorSize() == 512 && imagePlugin.GetSectors() == 2880)
@@ -748,17 +743,18 @@ namespace DiscImageChef.Filesystems.CPM
workingDefinition.side1 = new Side();
workingDefinition.side1.sideId = 0;
workingDefinition.side1.sectorIds = new int[18];
for(int si = 0; si < 18; si++)
workingDefinition.side1.sectorIds[si] = si + 1;
for(int si = 0; si < 18; si++) workingDefinition.side1.sectorIds[si] = si + 1;
workingDefinition.order = "CYLINDERS";
workingDefinition.side2 = new Side();
workingDefinition.side2.sideId = 1;
workingDefinition.side2.sectorIds = new int[18];
for(int si = 0; si < 18; si++)
workingDefinition.side2.sectorIds[si] = si + 1;
for(int si = 0; si < 18; si++) workingDefinition.side2.sectorIds[si] = si + 1;
workingDefinition.skew = 0;
workingDefinition.sofs = 0;
}
break;
}
@@ -787,7 +783,8 @@ namespace DiscImageChef.Filesystems.CPM
{
// Load all definitions
DicConsole.DebugWriteLine("CP/M Plugin", "Trying to load definitions.");
if(LoadDefinitions() && definitions != null && definitions.definitions != null && definitions.definitions.Count > 0)
if(LoadDefinitions() && definitions != null && definitions.definitions != null &&
definitions.definitions.Count > 0)
{
DicConsole.DebugWriteLine("CP/M Plugin", "Trying all known definitions.");
foreach(CpmDefinition def in definitions.definitions)
@@ -799,10 +796,8 @@ namespace DiscImageChef.Filesystems.CPM
{
DicConsole.DebugWriteLine("CP/M Plugin", "Trying definition \"{0}\"", def.comment);
ulong offset;
if(def.sofs != 0)
offset = (ulong)def.sofs;
else
offset = (ulong)(def.ofs * def.sectorsPerTrack);
if(def.sofs != 0) offset = (ulong)def.sofs;
else offset = (ulong)(def.ofs * def.sectorsPerTrack);
int dirLen = ((def.drm + 1) * 32) / def.bytesPerSector;
@@ -815,39 +810,51 @@ namespace DiscImageChef.Filesystems.CPM
else
{
// Head changes after every track
if(string.Compare(def.order, "SIDES", StringComparison.InvariantCultureIgnoreCase) == 0)
if(string.Compare(def.order, "SIDES",
StringComparison.InvariantCultureIgnoreCase) == 0)
{
sectorMask = new int[def.side1.sectorIds.Length + def.side2.sectorIds.Length];
for(int m = 0; m < def.side1.sectorIds.Length; m++)
sectorMask[m] = def.side1.sectorIds[m] - def.side1.sectorIds[0];
// Skip first track (first side)
for(int m = 0; m < def.side2.sectorIds.Length; m++)
sectorMask[m + def.side1.sectorIds.Length] = (def.side2.sectorIds[m] - def.side2.sectorIds[0]) + def.side1.sectorIds.Length;
sectorMask[m + def.side1.sectorIds.Length] =
(def.side2.sectorIds[m] - def.side2.sectorIds[0]) +
def.side1.sectorIds.Length;
}
// Head changes after whole side
else if(string.Compare(def.order, "CYLINDERS", StringComparison.InvariantCultureIgnoreCase) == 0)
else if(string.Compare(def.order, "CYLINDERS",
StringComparison.InvariantCultureIgnoreCase) == 0)
{
for(int m = 0; m < def.side1.sectorIds.Length; m++)
sectorMask[m] = def.side1.sectorIds[m] - def.side1.sectorIds[0];
// Skip first track (first side) and first track (second side)
for(int m = 0; m < def.side1.sectorIds.Length; m++)
sectorMask[m + def.side1.sectorIds.Length] = (def.side1.sectorIds[m] - def.side1.sectorIds[0]) + def.side1.sectorIds.Length + def.side2.sectorIds.Length;
sectorMask[m + def.side1.sectorIds.Length] =
(def.side1.sectorIds[m] - def.side1.sectorIds[0]) +
def.side1.sectorIds.Length + def.side2.sectorIds.Length;
}
// TODO: Implement COLUMBIA ordering
else if(string.Compare(def.order, "COLUMBIA", StringComparison.InvariantCultureIgnoreCase) == 0)
else if(string.Compare(def.order, "COLUMBIA",
StringComparison.InvariantCultureIgnoreCase) == 0)
{
DicConsole.DebugWriteLine("CP/M Plugin", "Don't know how to handle COLUMBIA ordering, not proceeding with this definition.");
DicConsole.DebugWriteLine("CP/M Plugin",
"Don't know how to handle COLUMBIA ordering, not proceeding with this definition.");
continue;
}
// TODO: Implement EAGLE ordering
else if(string.Compare(def.order, "EAGLE", StringComparison.InvariantCultureIgnoreCase) == 0)
else if(string.Compare(def.order, "EAGLE",
StringComparison.InvariantCultureIgnoreCase) == 0)
{
DicConsole.DebugWriteLine("CP/M Plugin", "Don't know how to handle EAGLE ordering, not proceeding with this definition.");
DicConsole.DebugWriteLine("CP/M Plugin",
"Don't know how to handle EAGLE ordering, not proceeding with this definition.");
continue;
}
else
{
DicConsole.DebugWriteLine("CP/M Plugin", "Unknown order type \"{0}\", not proceeding with this definition.", def.order);
DicConsole.DebugWriteLine("CP/M Plugin",
"Unknown order type \"{0}\", not proceeding with this definition.",
def.order);
continue;
}
}
@@ -856,13 +863,18 @@ namespace DiscImageChef.Filesystems.CPM
MemoryStream ms = new MemoryStream();
for(int p = 0; p < dirLen; p++)
{
byte[] dirSector = imagePlugin.ReadSector((ulong)((int)offset + (int)partition.Start + (p / sectorMask.Length) * sectorMask.Length + sectorMask[p % sectorMask.Length]));
byte[] dirSector =
imagePlugin.ReadSector((ulong)((int)offset + (int)partition.Start +
(p / sectorMask.Length) * sectorMask.Length +
sectorMask[p % sectorMask.Length]));
ms.Write(dirSector, 0, dirSector.Length);
}
directory = ms.ToArray();
if(def.evenOdd)
DicConsole.DebugWriteLine("CP/M Plugin", "Definition contains EVEN-ODD field, with unknown meaning, detection may be wrong.");
DicConsole.DebugWriteLine("CP/M Plugin",
"Definition contains EVEN-ODD field, with unknown meaning, detection may be wrong.");
// Complement of the directory bytes if needed
if(def.complement)
@@ -874,7 +886,9 @@ namespace DiscImageChef.Filesystems.CPM
// Check the directory
if(CheckDir(directory))
{
DicConsole.DebugWriteLine("CP/M Plugin", "Definition \"{0}\" has a correct directory", def.comment);
DicConsole.DebugWriteLine("CP/M Plugin",
"Definition \"{0}\" has a correct directory",
def.comment);
// Build a Disc Parameter Block
workingDefinition = def;
@@ -927,6 +941,7 @@ namespace DiscImageChef.Filesystems.CPM
dpb.phm = 255;
break;
}
dpb.spt = (ushort)((def.sectorsPerTrack * def.bytesPerSector) / 128);
cpmFound = true;
workingDefinition = def;
@@ -962,8 +977,7 @@ namespace DiscImageChef.Filesystems.CPM
{
information = "";
// As the identification is so complex, just call Identify() and relay on its findings
if(!Identify(imagePlugin, partition) || !cpmFound || workingDefinition == null || dpb == null)
return;
if(!Identify(imagePlugin, partition) || !cpmFound || workingDefinition == null || dpb == null) return;
StringBuilder sb = new StringBuilder();
sb.AppendLine("CP/M filesystem");
@@ -971,12 +985,15 @@ namespace DiscImageChef.Filesystems.CPM
sb.AppendFormat("Identified as {0}", workingDefinition.comment).AppendLine();
sb.AppendFormat("Volume block is {0} bytes", 128 << dpb.bsh).AppendLine();
if(dpb.dsm > 0)
sb.AppendFormat("Volume contains {0} blocks ({1} bytes)", dpb.dsm, (dpb.dsm) * (128 << dpb.bsh)).AppendLine();
sb.AppendFormat("Volume contains {0} blocks ({1} bytes)", dpb.dsm, (dpb.dsm) * (128 << dpb.bsh))
.AppendLine();
sb.AppendFormat("Volume contains {0} directory entries", dpb.drm + 1).AppendLine();
if(workingDefinition.sofs > 0)
sb.AppendFormat("Volume reserves {0} sectors for system", workingDefinition.sofs).AppendLine();
else
sb.AppendFormat("Volume reserves {1} tracks ({0} sectors) for system", workingDefinition.ofs * workingDefinition.sectorsPerTrack, workingDefinition.ofs).AppendLine();
sb.AppendFormat("Volume reserves {1} tracks ({0} sectors) for system",
workingDefinition.ofs * workingDefinition.sectorsPerTrack, workingDefinition.ofs)
.AppendLine();
int interleaveSide1;
int interleaveSide2 = 1;
@@ -987,7 +1004,7 @@ namespace DiscImageChef.Filesystems.CPM
if(interleaveSide1 > 1)
sb.AppendFormat("Side 0 uses {0}:1 software interleaving", interleaveSide1).AppendLine();
}
if(workingDefinition.sides == 2)
{
if(workingDefinition.side2.sectorIds.Length >= 2)
@@ -1014,18 +1031,19 @@ namespace DiscImageChef.Filesystems.CPM
sb.AppendFormat("Device uses {0}:1 hardware interleaving", workingDefinition.skew).AppendLine();
if(workingDefinition.sofs > 0)
sb.AppendFormat("BSH {0} BLM {1} EXM {2} DSM {3} DRM {4} AL0 {5:X2}H AL1 {6:X2}H SOFS {7}", dpb.bsh, dpb.blm, dpb.exm, dpb.dsm, dpb.drm, dpb.al0, dpb.al1, workingDefinition.sofs).AppendLine();
sb.AppendFormat("BSH {0} BLM {1} EXM {2} DSM {3} DRM {4} AL0 {5:X2}H AL1 {6:X2}H SOFS {7}", dpb.bsh,
dpb.blm, dpb.exm, dpb.dsm, dpb.drm, dpb.al0, dpb.al1, workingDefinition.sofs)
.AppendLine();
else
sb.AppendFormat("BSH {0} BLM {1} EXM {2} DSM {3} DRM {4} AL0 {5:X2}H AL1 {6:X2}H OFS {7}", dpb.bsh, dpb.blm, dpb.exm, dpb.dsm, dpb.drm, dpb.al0, dpb.al1, workingDefinition.ofs).AppendLine();
sb.AppendFormat("BSH {0} BLM {1} EXM {2} DSM {3} DRM {4} AL0 {5:X2}H AL1 {6:X2}H OFS {7}", dpb.bsh,
dpb.blm, dpb.exm, dpb.dsm, dpb.drm, dpb.al0, dpb.al1, workingDefinition.ofs)
.AppendLine();
if(label != null)
sb.AppendFormat("Volume label {0}", label).AppendLine();
if(label != null) sb.AppendFormat("Volume label {0}", label).AppendLine();
if(standardTimestamps)
sb.AppendLine("Volume uses standard CP/M timestamps");
if(standardTimestamps) sb.AppendLine("Volume uses standard CP/M timestamps");
if(thirdPartyTimestamps)
sb.AppendLine("Volume uses third party timestamps");
if(thirdPartyTimestamps) sb.AppendLine("Volume uses third party timestamps");
if(labelCreationDate != null)
sb.AppendFormat("Volume created on {0}", DateHandlers.CPMToDateTime(labelCreationDate)).AppendLine();
@@ -1035,10 +1053,8 @@ namespace DiscImageChef.Filesystems.CPM
xmlFSType = new Schemas.FileSystemType();
xmlFSType.Bootable |= (workingDefinition.sofs > 0 || workingDefinition.ofs > 0);
xmlFSType.ClusterSize = 128 << dpb.bsh;
if(dpb.dsm > 0)
xmlFSType.Clusters = dpb.dsm;
else
xmlFSType.Clusters = (long)(partition.End - partition.Start);
if(dpb.dsm > 0) xmlFSType.Clusters = dpb.dsm;
else xmlFSType.Clusters = (long)(partition.End - partition.Start);
if(labelCreationDate != null)
{
xmlFSType.CreationDate = DateHandlers.CPMToDateTime(labelCreationDate);
@@ -1055,5 +1071,4 @@ namespace DiscImageChef.Filesystems.CPM
information = sb.ToString();
}
}
}
}

View File

@@ -176,8 +176,7 @@ namespace DiscImageChef.Filesystems.CPM
/// <summary>
/// Copyright string
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x1F)]
public byte[] copyright;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x1F)] public byte[] copyright;
/// <summary>
/// First cylinder of disk where this volume resides
/// </summary>
@@ -289,8 +288,7 @@ namespace DiscImageChef.Filesystems.CPM
/// <summary>
/// Label in ASCII
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)]
public byte[] label;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public byte[] label;
/// <summary>
/// Label flags. Bit 0 = label exists, bit 4 = creation timestamp, bit 5 = modification timestamp, bit 6 = access timestamp, bit 7 = password enabled
/// </summary>
@@ -306,18 +304,15 @@ namespace DiscImageChef.Filesystems.CPM
/// <summary>
/// Password XOR'ed with <see cref="passwordDecoder"/>
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] password;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] password;
/// <summary>
/// Label creation time
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] ctime;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] ctime;
/// <summary>
/// Label modification time
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] mtime;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] mtime;
}
/// <summary>
@@ -333,8 +328,7 @@ namespace DiscImageChef.Filesystems.CPM
/// <summary>
/// File 1 create/access timestamp
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] date1;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] date1;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
/// <summary>
/// File 1 modification timestamp
@@ -348,13 +342,11 @@ namespace DiscImageChef.Filesystems.CPM
/// <summary>
/// File 2 create/access timestamp
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] date3;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] date3;
/// <summary>
/// File 2 modification timestamp
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] date4;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] date4;
/// <summary>
/// File 2 password mode
/// </summary>
@@ -363,13 +355,11 @@ namespace DiscImageChef.Filesystems.CPM
/// <summary>
/// File 3 create/access timestamp
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] date5;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] date5;
/// <summary>
/// File 3 modification timestamp
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] date6;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] date6;
/// <summary>
/// File 3 password mode
/// </summary>
@@ -390,13 +380,11 @@ namespace DiscImageChef.Filesystems.CPM
/// <summary>
/// Filename
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] filename;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] filename;
/// <summary>
/// Extension
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] extension;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] extension;
/// <summary>
/// Password mode. Bit 7 = required for read, bit 6 = required for write, bit 5 = required for delete
/// </summary>
@@ -405,15 +393,12 @@ namespace DiscImageChef.Filesystems.CPM
/// Password decoder byte
/// </summary>
public byte passwordDecoder;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public byte[] reserved;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] reserved;
/// <summary>
/// Password XOR'ed with <see cref="passwordDecoder"/>
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] password;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] reserved2;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] password;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] reserved2;
}
/// <summary>
@@ -430,48 +415,39 @@ namespace DiscImageChef.Filesystems.CPM
/// <summary>
/// Creation year for file 1
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public byte[] create1;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] create1;
/// <summary>
/// Modification time for file 1
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] modify1;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] modify1;
/// <summary>
/// Access time for file 1
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] access1;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] access1;
/// <summary>
/// Creation year for file 2
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public byte[] create2;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] create2;
/// <summary>
/// Modification time for file 2
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] modify2;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] modify2;
/// <summary>
/// Access time for file 2
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] access2;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] access2;
/// <summary>
/// Creation year for file 3
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public byte[] create3;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] create3;
/// <summary>
/// Modification time for file 3
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] modify3;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] modify3;
/// <summary>
/// Access time for file 3
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] access3;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] access3;
}
/// <summary>
@@ -487,13 +463,11 @@ namespace DiscImageChef.Filesystems.CPM
/// <summary>
/// Filename and bit 7 as flags
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] filename;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] filename;
/// <summary>
/// Extension and bit 7 as flags
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] extension;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] extension;
/// <summary>
/// Low byte of extent number
/// </summary>
@@ -514,8 +488,7 @@ namespace DiscImageChef.Filesystems.CPM
/// <summary>
/// Allocation blocks
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] allocations;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] allocations;
}
/// <summary>
@@ -531,13 +504,11 @@ namespace DiscImageChef.Filesystems.CPM
/// <summary>
/// Filename and bit 7 as flags
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] filename;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] filename;
/// <summary>
/// Extension and bit 7 as flags
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] extension;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] extension;
/// <summary>
/// Low byte of extent number
/// </summary>
@@ -558,9 +529,7 @@ namespace DiscImageChef.Filesystems.CPM
/// <summary>
/// Allocation blocks
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public ushort[] allocations;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public ushort[] allocations;
}
}
}
}

View File

@@ -66,59 +66,75 @@ namespace DiscImageChef.Filesystems.CPM
// Head changes after every track
if(string.Compare(workingDefinition.order, "SIDES", StringComparison.InvariantCultureIgnoreCase) == 0)
{
sectorMask = new int[workingDefinition.side1.sectorIds.Length + workingDefinition.side2.sectorIds.Length];
sectorMask = new int[workingDefinition.side1.sectorIds.Length +
workingDefinition.side2.sectorIds.Length];
for(int m = 0; m < workingDefinition.side1.sectorIds.Length; m++)
sectorMask[m] = workingDefinition.side1.sectorIds[m] - workingDefinition.side1.sectorIds[0];
// Skip first track (first side)
for(int m = 0; m < workingDefinition.side2.sectorIds.Length; m++)
sectorMask[m + workingDefinition.side1.sectorIds.Length] = (workingDefinition.side2.sectorIds[m] - workingDefinition.side2.sectorIds[0]) + workingDefinition.side1.sectorIds.Length;
sectorMask[m + workingDefinition.side1.sectorIds.Length] =
(workingDefinition.side2.sectorIds[m] - workingDefinition.side2.sectorIds[0]) +
workingDefinition.side1.sectorIds.Length;
}
// Head changes after whole side
else if(string.Compare(workingDefinition.order, "CYLINDERS", StringComparison.InvariantCultureIgnoreCase) == 0)
else if(string.Compare(workingDefinition.order, "CYLINDERS",
StringComparison.InvariantCultureIgnoreCase) == 0)
{
for(int m = 0; m < workingDefinition.side1.sectorIds.Length; m++)
sectorMask[m] = workingDefinition.side1.sectorIds[m] - workingDefinition.side1.sectorIds[0];
// Skip first track (first side) and first track (second side)
for(int m = 0; m < workingDefinition.side1.sectorIds.Length; m++)
sectorMask[m + workingDefinition.side1.sectorIds.Length] = (workingDefinition.side1.sectorIds[m] - workingDefinition.side1.sectorIds[0]) + workingDefinition.side1.sectorIds.Length + workingDefinition.side2.sectorIds.Length;
sectorMask[m + workingDefinition.side1.sectorIds.Length] =
(workingDefinition.side1.sectorIds[m] - workingDefinition.side1.sectorIds[0]) +
workingDefinition.side1.sectorIds.Length + workingDefinition.side2.sectorIds.Length;
// TODO: Implement CYLINDERS ordering
DicConsole.DebugWriteLine("CP/M Plugin", "CYLINDERS ordering not yet implemented.");
return Errno.NotImplemented;
}
// TODO: Implement COLUMBIA ordering
else if(string.Compare(workingDefinition.order, "COLUMBIA", StringComparison.InvariantCultureIgnoreCase) == 0)
else if(
string.Compare(workingDefinition.order, "COLUMBIA", StringComparison.InvariantCultureIgnoreCase) ==
0)
{
DicConsole.DebugWriteLine("CP/M Plugin", "Don't know how to handle COLUMBIA ordering, not proceeding with this definition.");
DicConsole.DebugWriteLine("CP/M Plugin",
"Don't know how to handle COLUMBIA ordering, not proceeding with this definition.");
return Errno.NotImplemented;
}
// TODO: Implement EAGLE ordering
else if(string.Compare(workingDefinition.order, "EAGLE", StringComparison.InvariantCultureIgnoreCase) == 0)
else if(string.Compare(workingDefinition.order, "EAGLE", StringComparison.InvariantCultureIgnoreCase) ==
0)
{
DicConsole.DebugWriteLine("CP/M Plugin", "Don't know how to handle EAGLE ordering, not proceeding with this definition.");
DicConsole.DebugWriteLine("CP/M Plugin",
"Don't know how to handle EAGLE ordering, not proceeding with this definition.");
return Errno.NotImplemented;
}
else
{
DicConsole.DebugWriteLine("CP/M Plugin", "Unknown order type \"{0}\", not proceeding with this definition.", workingDefinition.order);
DicConsole.DebugWriteLine("CP/M Plugin",
"Unknown order type \"{0}\", not proceeding with this definition.",
workingDefinition.order);
return Errno.NotSupported;
}
}
// Deinterleave whole volume
Dictionary<ulong, byte[]> deinterleavedSectors = new Dictionary<ulong, byte[]>();
if(workingDefinition.sides == 1 || string.Compare(workingDefinition.order, "SIDES", StringComparison.InvariantCultureIgnoreCase) == 0)
if(workingDefinition.sides == 1 ||
string.Compare(workingDefinition.order, "SIDES", StringComparison.InvariantCultureIgnoreCase) == 0)
{
DicConsole.DebugWriteLine("CP/M Plugin", "Deinterleaving whole volume.");
for(int p = 0; p <= (int)(partition.End - partition.Start); p++)
{
byte[] readSector = device.ReadSector((ulong)((int)partition.Start + (p / sectorMask.Length) * sectorMask.Length + sectorMask[p % sectorMask.Length]));
byte[] readSector =
device.ReadSector((ulong)((int)partition.Start + (p / sectorMask.Length) * sectorMask.Length +
sectorMask[p % sectorMask.Length]));
if(workingDefinition.complement)
{
for(int b = 0; b < readSector.Length; b++)
readSector[b] = (byte)(~readSector[b] & 0xFF);
for(int b = 0; b < readSector.Length; b++) readSector[b] = (byte)(~readSector[b] & 0xFF);
}
deinterleavedSectors.Add((ulong)p, readSector);
}
}
@@ -161,18 +177,15 @@ namespace DiscImageChef.Filesystems.CPM
}
}
// CP/M blocks are same size than physical sectors
else
allocationBlocks.Add(blockNo++, sector);
else allocationBlocks.Add(blockNo++, sector);
}
DicConsole.DebugWriteLine("CP/M Plugin", "Reading directory.");
int dirOff;
int dirSectors = ((dpb.drm + 1) * 32) / workingDefinition.bytesPerSector;
if(workingDefinition.sofs > 0)
dirOff = workingDefinition.sofs;
else
dirOff = workingDefinition.ofs * workingDefinition.sectorsPerTrack;
if(workingDefinition.sofs > 0) dirOff = workingDefinition.sofs;
else dirOff = workingDefinition.ofs * workingDefinition.sectorsPerTrack;
// Read the whole directory blocks
MemoryStream dirMs = new MemoryStream();
@@ -182,16 +195,17 @@ namespace DiscImageChef.Filesystems.CPM
deinterleavedSectors.TryGetValue((ulong)(d + dirOff), out sector);
dirMs.Write(sector, 0, sector.Length);
}
byte[] directory = dirMs.ToArray();
if(directory == null)
return Errno.InvalidArgument;
if(directory == null) return Errno.InvalidArgument;
int dirCnt = 0;
string file1 = null;
string file2 = null;
string file3 = null;
Dictionary<string, Dictionary<int, List<ushort>>> fileExtents = new Dictionary<string, Dictionary<int, List<ushort>>>();
Dictionary<string, Dictionary<int, List<ushort>>> fileExtents =
new Dictionary<string, Dictionary<int, List<ushort>>>();
statCache = new Dictionary<string, FileEntryInfo>();
cpmStat = new FileSystemInfo();
bool atime = false;
@@ -236,17 +250,14 @@ namespace DiscImageChef.Filesystems.CPM
validEntry &= entry.extension[i] >= 0x20;
}
if(!validEntry)
continue;
if(!validEntry) continue;
string filename = Encoding.ASCII.GetString(entry.filename).Trim();
string extension = Encoding.ASCII.GetString(entry.extension).Trim();
// If user is != 0, append user to name to have identical filenames
if(user > 0)
filename = string.Format("{0:X1}:{1}", user, filename);
if(!string.IsNullOrEmpty(extension))
filename = filename + "." + extension;
if(user > 0) filename = string.Format("{0:X1}:{1}", user, filename);
if(!string.IsNullOrEmpty(extension)) filename = filename + "." + extension;
int entryNo = ((32 * entry.extentCounter) + entry.extentCounterHigh) / (dpb.exm + 1);
List<ushort> blocks;
@@ -254,8 +265,7 @@ namespace DiscImageChef.Filesystems.CPM
FileEntryInfo fInfo;
// Do we have a stat for the file already?
if(statCache.TryGetValue(filename, out fInfo))
statCache.Remove(filename);
if(statCache.TryGetValue(filename, out fInfo)) statCache.Remove(filename);
else
{
fInfo = new FileEntryInfo();
@@ -263,24 +273,17 @@ namespace DiscImageChef.Filesystems.CPM
}
// And any extent?
if(fileExtents.TryGetValue(filename, out extentBlocks))
fileExtents.Remove(filename);
else
extentBlocks = new Dictionary<int, List<ushort>>();
if(fileExtents.TryGetValue(filename, out extentBlocks)) fileExtents.Remove(filename);
else extentBlocks = new Dictionary<int, List<ushort>>();
// Do we already have this extent? Should never happen
if(extentBlocks.TryGetValue(entryNo, out blocks))
extentBlocks.Remove(entryNo);
else
blocks = new List<ushort>();
if(extentBlocks.TryGetValue(entryNo, out blocks)) extentBlocks.Remove(entryNo);
else blocks = new List<ushort>();
// Attributes
if(hidden)
fInfo.Attributes |= FileAttributes.Hidden;
if(rdOnly)
fInfo.Attributes |= FileAttributes.ReadOnly;
if(system)
fInfo.Attributes |= FileAttributes.System;
if(hidden) fInfo.Attributes |= FileAttributes.Hidden;
if(rdOnly) fInfo.Attributes |= FileAttributes.ReadOnly;
if(system) fInfo.Attributes |= FileAttributes.System;
// Supposedly there is a value in the directory entry telling how many blocks are designated in this entry
// However some implementations tend to do whatever they wish, but none will ever allocate block 0 for a file
@@ -289,8 +292,7 @@ namespace DiscImageChef.Filesystems.CPM
// we must ignore it.
foreach(ushort blk in entry.allocations)
{
if(!blocks.Contains(blk) && blk != 0)
blocks.Add(blk);
if(!blocks.Contains(blk) && blk != 0) blocks.Add(blk);
}
// Save the file
@@ -300,8 +302,7 @@ namespace DiscImageChef.Filesystems.CPM
statCache.Add(filename, fInfo);
// Add the file to the directory listing
if(!dirList.Contains(filename))
dirList.Add(filename);
if(!dirList.Contains(filename)) dirList.Add(filename);
// Count entries 3 by 3 for timestamps
switch(dirCnt % 3)
@@ -316,6 +317,7 @@ namespace DiscImageChef.Filesystems.CPM
file3 = filename;
break;
}
dirCnt++;
}
else
@@ -345,17 +347,14 @@ namespace DiscImageChef.Filesystems.CPM
validEntry &= entry.extension[i] >= 0x20;
}
if(!validEntry)
continue;
if(!validEntry) continue;
string filename = Encoding.ASCII.GetString(entry.filename).Trim();
string extension = Encoding.ASCII.GetString(entry.extension).Trim();
// If user is != 0, append user to name to have identical filenames
if(user > 0)
filename = string.Format("{0:X1}:{1}", user, filename);
if(!string.IsNullOrEmpty(extension))
filename = filename + "." + extension;
if(user > 0) filename = string.Format("{0:X1}:{1}", user, filename);
if(!string.IsNullOrEmpty(extension)) filename = filename + "." + extension;
int entryNo = ((32 * entry.extentCounterHigh) + entry.extentCounter) / (dpb.exm + 1);
List<ushort> blocks;
@@ -363,8 +362,7 @@ namespace DiscImageChef.Filesystems.CPM
FileEntryInfo fInfo;
// Do we have a stat for the file already?
if(statCache.TryGetValue(filename, out fInfo))
statCache.Remove(filename);
if(statCache.TryGetValue(filename, out fInfo)) statCache.Remove(filename);
else
{
fInfo = new FileEntryInfo();
@@ -372,24 +370,17 @@ namespace DiscImageChef.Filesystems.CPM
}
// And any extent?
if(fileExtents.TryGetValue(filename, out extentBlocks))
fileExtents.Remove(filename);
else
extentBlocks = new Dictionary<int, List<ushort>>();
if(fileExtents.TryGetValue(filename, out extentBlocks)) fileExtents.Remove(filename);
else extentBlocks = new Dictionary<int, List<ushort>>();
// Do we already have this extent? Should never happen
if(extentBlocks.TryGetValue(entryNo, out blocks))
extentBlocks.Remove(entryNo);
else
blocks = new List<ushort>();
if(extentBlocks.TryGetValue(entryNo, out blocks)) extentBlocks.Remove(entryNo);
else blocks = new List<ushort>();
// Attributes
if(hidden)
fInfo.Attributes |= FileAttributes.Hidden;
if(rdOnly)
fInfo.Attributes |= FileAttributes.ReadOnly;
if(system)
fInfo.Attributes |= FileAttributes.System;
if(hidden) fInfo.Attributes |= FileAttributes.Hidden;
if(rdOnly) fInfo.Attributes |= FileAttributes.ReadOnly;
if(system) fInfo.Attributes |= FileAttributes.System;
// Supposedly there is a value in the directory entry telling how many blocks are designated in this entry
// However some implementations tend to do whatever they wish, but none will ever allocate block 0 for a file
@@ -398,8 +389,7 @@ namespace DiscImageChef.Filesystems.CPM
// we must ignore it.
foreach(ushort blk in entry.allocations)
{
if(!blocks.Contains(blk) && blk != 0)
blocks.Add(blk);
if(!blocks.Contains(blk) && blk != 0) blocks.Add(blk);
}
// Save the file
@@ -409,8 +399,7 @@ namespace DiscImageChef.Filesystems.CPM
statCache.Add(filename, fInfo);
// Add the file to the directory listing
if(!dirList.Contains(filename))
dirList.Add(filename);
if(!dirList.Contains(filename)) dirList.Add(filename);
// Count entries 3 by 3 for timestamps
switch(dirCnt % 3)
@@ -425,6 +414,7 @@ namespace DiscImageChef.Filesystems.CPM
file3 = filename;
break;
}
dirCnt++;
}
}
@@ -439,23 +429,18 @@ namespace DiscImageChef.Filesystems.CPM
int user = (entry.userNumber & 0x0F);
for(int i = 0; i < 8; i++)
entry.filename[i] &= 0x7F;
for(int i = 0; i < 3; i++)
entry.extension[i] &= 0x7F;
for(int i = 0; i < 8; i++) entry.filename[i] &= 0x7F;
for(int i = 0; i < 3; i++) entry.extension[i] &= 0x7F;
string filename = Encoding.ASCII.GetString(entry.filename).Trim();
string extension = Encoding.ASCII.GetString(entry.extension).Trim();
// If user is != 0, append user to name to have identical filenames
if(user > 0)
filename = string.Format("{0:X1}:{1}", user, filename);
if(!string.IsNullOrEmpty(extension))
filename = filename + "." + extension;
if(user > 0) filename = string.Format("{0:X1}:{1}", user, filename);
if(!string.IsNullOrEmpty(extension)) filename = filename + "." + extension;
// Do not repeat passwords
if(passwordCache.ContainsKey(filename))
passwordCache.Remove(filename);
if(passwordCache.ContainsKey(filename)) passwordCache.Remove(filename);
// Copy whole password entry
byte[] tmp = new byte[32];
@@ -475,6 +460,7 @@ namespace DiscImageChef.Filesystems.CPM
file3 = filename;
break;
}
dirCnt++;
}
// Volume label and password entry. Volume password is ignored.
@@ -508,15 +494,14 @@ namespace DiscImageChef.Filesystems.CPM
file3 = null;
break;
}
dirCnt++;
}
// Timestamp entry
else if((directory[dOff] & 0x7F) == 0x21)
{
// These places must be zero on CP/M 3 timestamp
if(directory[dOff + 10] == 0x00 &&
directory[dOff + 20] == 0x00 &&
directory[dOff + 30] == 0x00 &&
if(directory[dOff + 10] == 0x00 && directory[dOff + 20] == 0x00 && directory[dOff + 30] == 0x00 &&
directory[dOff + 31] == 0x00)
{
DateEntry entry = new DateEntry();
@@ -530,15 +515,11 @@ namespace DiscImageChef.Filesystems.CPM
// Entry contains timestamps for last 3 entries, whatever the kind they are.
if(!string.IsNullOrEmpty(file1))
{
if(statCache.TryGetValue(file1, out fInfo))
statCache.Remove(file1);
else
fInfo = new FileEntryInfo();
if(statCache.TryGetValue(file1, out fInfo)) statCache.Remove(file1);
else fInfo = new FileEntryInfo();
if(atime)
fInfo.AccessTime = DateHandlers.CPMToDateTime(entry.date1);
else
fInfo.CreationTime = DateHandlers.CPMToDateTime(entry.date1);
if(atime) fInfo.AccessTime = DateHandlers.CPMToDateTime(entry.date1);
else fInfo.CreationTime = DateHandlers.CPMToDateTime(entry.date1);
fInfo.LastWriteTime = DateHandlers.CPMToDateTime(entry.date2);
@@ -547,15 +528,11 @@ namespace DiscImageChef.Filesystems.CPM
if(!string.IsNullOrEmpty(file2))
{
if(statCache.TryGetValue(file2, out fInfo))
statCache.Remove(file2);
else
fInfo = new FileEntryInfo();
if(statCache.TryGetValue(file2, out fInfo)) statCache.Remove(file2);
else fInfo = new FileEntryInfo();
if(atime)
fInfo.AccessTime = DateHandlers.CPMToDateTime(entry.date3);
else
fInfo.CreationTime = DateHandlers.CPMToDateTime(entry.date3);
if(atime) fInfo.AccessTime = DateHandlers.CPMToDateTime(entry.date3);
else fInfo.CreationTime = DateHandlers.CPMToDateTime(entry.date3);
fInfo.LastWriteTime = DateHandlers.CPMToDateTime(entry.date4);
@@ -564,15 +541,11 @@ namespace DiscImageChef.Filesystems.CPM
if(!string.IsNullOrEmpty(file3))
{
if(statCache.TryGetValue(file3, out fInfo))
statCache.Remove(file3);
else
fInfo = new FileEntryInfo();
if(statCache.TryGetValue(file3, out fInfo)) statCache.Remove(file3);
else fInfo = new FileEntryInfo();
if(atime)
fInfo.AccessTime = DateHandlers.CPMToDateTime(entry.date5);
else
fInfo.CreationTime = DateHandlers.CPMToDateTime(entry.date5);
if(atime) fInfo.AccessTime = DateHandlers.CPMToDateTime(entry.date5);
else fInfo.CreationTime = DateHandlers.CPMToDateTime(entry.date5);
fInfo.LastWriteTime = DateHandlers.CPMToDateTime(entry.date6);
@@ -598,10 +571,8 @@ namespace DiscImageChef.Filesystems.CPM
// Entry contains timestamps for last 3 entries, whatever the kind they are.
if(!string.IsNullOrEmpty(file1))
{
if(statCache.TryGetValue(file1, out fInfo))
statCache.Remove(file1);
else
fInfo = new FileEntryInfo();
if(statCache.TryGetValue(file1, out fInfo)) statCache.Remove(file1);
else fInfo = new FileEntryInfo();
byte[] ctime = new byte[4];
ctime[0] = entry.create1[0];
@@ -616,10 +587,8 @@ namespace DiscImageChef.Filesystems.CPM
if(!string.IsNullOrEmpty(file2))
{
if(statCache.TryGetValue(file2, out fInfo))
statCache.Remove(file2);
else
fInfo = new FileEntryInfo();
if(statCache.TryGetValue(file2, out fInfo)) statCache.Remove(file2);
else fInfo = new FileEntryInfo();
byte[] ctime = new byte[4];
ctime[0] = entry.create2[0];
@@ -634,10 +603,8 @@ namespace DiscImageChef.Filesystems.CPM
if(!string.IsNullOrEmpty(file3))
{
if(statCache.TryGetValue(file1, out fInfo))
statCache.Remove(file3);
else
fInfo = new FileEntryInfo();
if(statCache.TryGetValue(file1, out fInfo)) statCache.Remove(file3);
else fInfo = new FileEntryInfo();
byte[] ctime = new byte[4];
ctime[0] = entry.create3[0];
@@ -668,8 +635,7 @@ namespace DiscImageChef.Filesystems.CPM
MemoryStream fileMs = new MemoryStream();
FileEntryInfo fInfo = new FileEntryInfo();
if(statCache.TryGetValue(filename, out fInfo))
statCache.Remove(filename);
if(statCache.TryGetValue(filename, out fInfo)) statCache.Remove(filename);
fInfo.Blocks = 0;
@@ -712,8 +678,7 @@ namespace DiscImageChef.Filesystems.CPM
{
byte[] tmp = new byte[8];
Array.Copy(kvp.Value, 16, tmp, 0, 8);
for(int t = 0; t < 8; t++)
tmp[t] ^= kvp.Value[13];
for(int t = 0; t < 8; t++) tmp[t] ^= kvp.Value[13];
decodedPasswordCache.Add(kvp.Key, tmp);
}
@@ -746,8 +711,7 @@ namespace DiscImageChef.Filesystems.CPM
xmlFSType.FreeClusters = cpmStat.FreeBlocks;
xmlFSType.FreeClustersSpecified = true;
xmlFSType.Type = "CP/M filesystem";
if(!string.IsNullOrEmpty(label))
xmlFSType.VolumeName = label;
if(!string.IsNullOrEmpty(label)) xmlFSType.VolumeName = label;
mounted = true;
return Errno.NoError;
@@ -759,8 +723,7 @@ namespace DiscImageChef.Filesystems.CPM
/// <param name="stat">Information about the mounted volume.</param>
public override Errno StatFs(ref FileSystemInfo stat)
{
if(!mounted)
return Errno.AccessDenied;
if(!mounted) return Errno.AccessDenied;
stat = cpmStat;
@@ -773,7 +736,7 @@ namespace DiscImageChef.Filesystems.CPM
definitions = null;
cpmFound = false;
workingDefinition = null;
dpb = null;
dpb = null;
sectorMask = null;
label = null;
thirdPartyTimestamps = false;
@@ -783,5 +746,4 @@ namespace DiscImageChef.Filesystems.CPM
return Errno.NoError;
}
}
}
}

View File

@@ -46,26 +46,21 @@ namespace DiscImageChef.Filesystems.CPM
/// <param name="buf">Buffer.</param>
public override Errno GetXattr(string path, string xattr, ref byte[] buf)
{
if(!mounted)
return Errno.AccessDenied;
if(!mounted) return Errno.AccessDenied;
string[] pathElements = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
if(pathElements.Length != 1)
return Errno.NotSupported;
string[] pathElements = path.Split(new char[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
if(pathElements.Length != 1) return Errno.NotSupported;
if(!fileCache.ContainsKey(pathElements[0].ToUpperInvariant()))
return Errno.NoSuchFile;
if(!fileCache.ContainsKey(pathElements[0].ToUpperInvariant())) return Errno.NoSuchFile;
if(string.Compare(xattr, "com.caldera.cpm.password", StringComparison.InvariantCulture) == 0)
{
if(!passwordCache.TryGetValue(pathElements[0].ToUpperInvariant(), out buf))
return Errno.NoError;
if(!passwordCache.TryGetValue(pathElements[0].ToUpperInvariant(), out buf)) return Errno.NoError;
}
if(string.Compare(xattr, "com.caldera.cpm.password.text", StringComparison.InvariantCulture) == 0)
{
if(!passwordCache.TryGetValue(pathElements[0].ToUpperInvariant(), out buf))
return Errno.NoError;
if(!passwordCache.TryGetValue(pathElements[0].ToUpperInvariant(), out buf)) return Errno.NoError;
}
return Errno.NoSuchExtendedAttribute;
@@ -79,19 +74,15 @@ namespace DiscImageChef.Filesystems.CPM
/// <param name="xattrs">List of extended attributes, alternate data streams and forks.</param>
public override Errno ListXAttr(string path, ref List<string> xattrs)
{
if(!mounted)
return Errno.AccessDenied;
if(!mounted) return Errno.AccessDenied;
string[] pathElements = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
if(pathElements.Length != 1)
return Errno.NotSupported;
string[] pathElements = path.Split(new char[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
if(pathElements.Length != 1) return Errno.NotSupported;
if(!fileCache.ContainsKey(pathElements[0].ToUpperInvariant()))
return Errno.NoSuchFile;
if(!fileCache.ContainsKey(pathElements[0].ToUpperInvariant())) return Errno.NoSuchFile;
xattrs = new List<string>();
if(passwordCache.ContainsKey(pathElements[0].ToUpperInvariant()))
xattrs.Add("com.caldera.cpm.password");
if(passwordCache.ContainsKey(pathElements[0].ToUpperInvariant())) xattrs.Add("com.caldera.cpm.password");
if(decodedPasswordCache.ContainsKey(pathElements[0].ToUpperInvariant()))
xattrs.Add("com.caldera.cpm.password.text");
@@ -99,5 +90,4 @@ namespace DiscImageChef.Filesystems.CPM
return Errno.NoError;
}
}
}
}

File diff suppressed because it is too large Load Diff