Code cleanup.

This commit is contained in:
2018-06-22 08:08:38 +01:00
parent 82f474c7e3
commit 88da8fc019
581 changed files with 22423 additions and 20839 deletions

View File

@@ -60,7 +60,7 @@ namespace DiscImageChef.Filesystems.CPM
/// Stores all known CP/M disk definitions
/// </summary>
CpmDefinitions definitions;
IMediaImage device;
IMediaImage device;
/// <summary>
/// Cached directory listing
/// </summary>
@@ -84,7 +84,7 @@ namespace DiscImageChef.Filesystems.CPM
/// <summary>
/// Timestamp in volume label for update
/// </summary>
byte[] labelUpdateDate;
byte[] labelUpdateDate;
bool mounted;
Partition partition;
/// <summary>
@@ -118,7 +118,7 @@ namespace DiscImageChef.Filesystems.CPM
public Guid Id => new Guid("AA2B8585-41DF-4E3B-8A35-D1A935E2F8A1");
public IEnumerable<(string name, Type type, string description)> SupportedOptions =>
new(string name, Type type, string description)[] { };
new (string name, Type type, string description)[] { };
static Dictionary<string, string> GetDefaultOptions()
{

View File

@@ -78,30 +78,36 @@ namespace DiscImageChef.Filesystems.CPM
if((entry.statusUser & 0x7F) < 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;
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();
label = Encoding.ASCII.GetString(directory, off + 1, 11).Trim();
labelCreationDate = new byte[4];
labelUpdateDate = new byte[4];
labelUpdateDate = new byte[4];
Array.Copy(directory, off + 24, labelCreationDate, 0, 4);
Array.Copy(directory, off + 28, labelUpdateDate, 0, 4);
Array.Copy(directory, off + 28, labelUpdateDate, 0, 4);
}
else if(entry.statusUser == 0x21)
if(directory[off + 1] == 0x00) thirdPartyTimestamps = true;
else standardTimestamps |= directory[off + 21] == 0x00 && directory[off + 31] == 0x00;
if(directory[off + 1] == 0x00)
thirdPartyTimestamps = true;
else
standardTimestamps |= directory[off + 21] == 0x00 && directory[off + 31] == 0x00;
}
return fileCount > 0;

View File

@@ -112,8 +112,8 @@ namespace DiscImageChef.Filesystems.CPM
: Errno.NoSuchFile;
stat = new FileEntryInfo {Attributes = FileAttributes.Directory, BlockSize = XmlFsType.ClusterSize};
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);
return Errno.NoError;
}
}

View File

@@ -159,11 +159,11 @@ namespace DiscImageChef.Filesystems.CPM
try
{
byte[] sector;
ulong sectorSize;
ulong firstDirectorySector;
ulong sectorSize;
ulong firstDirectorySector;
byte[] directory = null;
workingDefinition = null;
label = null;
label = null;
// Try Amstrad superblock
if(!cpmFound)
@@ -182,7 +182,8 @@ namespace DiscImageChef.Filesystems.CPM
// Read the superblock
IntPtr amsPtr = Marshal.AllocHGlobal(16);
Marshal.Copy(sector, amsSbOffset, amsPtr, 16);
AmstradSuperBlock amsSb = (AmstradSuperBlock)Marshal.PtrToStructure(amsPtr, typeof(AmstradSuperBlock));
AmstradSuperBlock amsSb =
(AmstradSuperBlock)Marshal.PtrToStructure(amsPtr, typeof(AmstradSuperBlock));
Marshal.FreeHGlobal(amsPtr);
// Check that format byte and sidedness indicate the same number of sizes
@@ -191,14 +192,14 @@ namespace DiscImageChef.Filesystems.CPM
amsSb.format == 2 && (amsSb.sidedness & 0x02) == 2)
{
// Calculate device limits
ulong sides = (ulong)(amsSb.format == 0 ? 1 : 2);
ulong sides = (ulong)(amsSb.format == 0 ? 1 : 2);
ulong sectorCount = (ulong)(amsSb.tps * amsSb.spt * (byte)sides);
sectorSize = (ulong)(128 << amsSb.psh);
// Compare device limits from superblock to real limits
if(sectorSize == imagePlugin.Info.SectorSize && sectorCount == imagePlugin.Info.Sectors)
{
cpmFound = true;
cpmFound = true;
firstDirectorySector = (ulong)(amsSb.off * amsSb.spt);
// Build a DiscParameterBlock
@@ -220,13 +221,14 @@ namespace DiscImageChef.Filesystems.CPM
dpb.cks = 0x10;
dpb.drm = 0x3F;
}
dpb.dsm = 0; // I don't care
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);
dpb.spt = (ushort)(amsSb.spt * (sectorSize / 128));
dpb.spt = (ushort)(amsSb.spt * (sectorSize / 128));
uint directoryLength = (uint)(((ulong)dpb.drm + 1) * 32 / sectorSize);
directory = imagePlugin.ReadSectors(firstDirectorySector + partition.Start,
directoryLength);
@@ -234,23 +236,23 @@ namespace DiscImageChef.Filesystems.CPM
// Build a CP/M disk definition
workingDefinition = new CpmDefinition
{
al0 = dpb.al0,
al1 = dpb.al1,
bitrate = "LOW",
blm = dpb.blm,
bsh = dpb.bsh,
bytesPerSector = 512,
cylinders = amsSb.tps,
drm = dpb.drm,
dsm = dpb.dsm,
encoding = "MFM",
evenOdd = false,
exm = dpb.exm,
label = null,
comment = "Amstrad PCW superblock",
ofs = dpb.off,
al0 = dpb.al0,
al1 = dpb.al1,
bitrate = "LOW",
blm = dpb.blm,
bsh = dpb.bsh,
bytesPerSector = 512,
cylinders = amsSb.tps,
drm = dpb.drm,
dsm = dpb.dsm,
encoding = "MFM",
evenOdd = false,
exm = dpb.exm,
label = null,
comment = "Amstrad PCW superblock",
ofs = dpb.off,
sectorsPerTrack = amsSb.spt,
side1 = new Side {sideId = 0, sectorIds = new int[amsSb.spt]}
side1 = new Side {sideId = 0, sectorIds = new int[amsSb.spt]}
};
for(int si = 0; si < amsSb.spt; si++) workingDefinition.side1.sectorIds[si] = si + 1;
@@ -298,8 +300,8 @@ namespace DiscImageChef.Filesystems.CPM
if(sum == 0)
{
// Read the superblock
HardDiskSuperBlock hddSb = new HardDiskSuperBlock();
IntPtr hddPtr = Marshal.AllocHGlobal(Marshal.SizeOf(hddSb));
HardDiskSuperBlock hddSb = new HardDiskSuperBlock();
IntPtr hddPtr = Marshal.AllocHGlobal(Marshal.SizeOf(hddSb));
Marshal.Copy(sector, 0, hddPtr, Marshal.SizeOf(hddSb));
hddSb = (HardDiskSuperBlock)Marshal.PtrToStructure(hddPtr, typeof(HardDiskSuperBlock));
Marshal.FreeHGlobal(hddPtr);
@@ -311,10 +313,11 @@ namespace DiscImageChef.Filesystems.CPM
(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.Info.SectorSize && startingSector == partition.Start &&
if(sectorSize == imagePlugin.Info.SectorSize &&
startingSector == partition.Start &&
sectorsInPartition + partition.Start <= partition.End)
{
cpmFound = true;
cpmFound = true;
firstDirectorySector = (ulong)(hddSb.off * hddSb.sectorsPerTrack);
// Build a DiscParameterBlock
@@ -344,27 +347,27 @@ namespace DiscImageChef.Filesystems.CPM
// Build a CP/M disk definition
workingDefinition = new CpmDefinition
{
al0 = dpb.al0,
al1 = dpb.al1,
bitrate = "HIGH",
blm = dpb.blm,
bsh = dpb.bsh,
bytesPerSector = 512,
cylinders = hddSb.cylinders,
drm = dpb.drm,
dsm = dpb.dsm,
encoding = "MFM",
evenOdd = false,
exm = dpb.exm,
label = null,
comment = "CP/M-86 hard disk superblock",
ofs = dpb.off,
al0 = dpb.al0,
al1 = dpb.al1,
bitrate = "HIGH",
blm = dpb.blm,
bsh = dpb.bsh,
bytesPerSector = 512,
cylinders = hddSb.cylinders,
drm = dpb.drm,
dsm = dpb.dsm,
encoding = "MFM",
evenOdd = false,
exm = dpb.exm,
label = null,
comment = "CP/M-86 hard disk superblock",
ofs = dpb.off,
sectorsPerTrack = hddSb.sectorsPerTrack,
side1 = new Side {sideId = 0, sectorIds = new int[hddSb.sectorsPerTrack]},
order = "SIDES",
side2 = new Side {sideId = 1, sectorIds = new int[hddSb.sectorsPerTrack]},
skew = 0,
sofs = 0
side1 = new Side {sideId = 0, sectorIds = new int[hddSb.sectorsPerTrack]},
order = "SIDES",
side2 = new Side {sideId = 1, sectorIds = new int[hddSb.sectorsPerTrack]},
skew = 0,
sofs = 0
};
for(int si = 0; si < hddSb.sectorsPerTrack; si++)
@@ -383,8 +386,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();
uint firstDirectorySector86 = 0;
@@ -399,7 +404,7 @@ namespace DiscImageChef.Filesystems.CPM
case FormatByte.k160:
if(imagePlugin.Info.SectorSize == 512 && imagePlugin.Info.Sectors == 320)
{
cpmFound = true;
cpmFound = true;
firstDirectorySector86 = 8;
dpb = new DiscParameterBlock
{
@@ -419,25 +424,25 @@ namespace DiscImageChef.Filesystems.CPM
workingDefinition = new CpmDefinition
{
al0 = dpb.al0,
al1 = dpb.al1,
bitrate = "LOW",
blm = dpb.blm,
bsh = dpb.bsh,
bytesPerSector = 512,
cylinders = 40,
drm = dpb.drm,
dsm = dpb.dsm,
encoding = "MFM",
evenOdd = false,
exm = dpb.exm,
label = null,
comment = "CP/M-86 floppy identifier",
ofs = dpb.off,
al0 = dpb.al0,
al1 = dpb.al1,
bitrate = "LOW",
blm = dpb.blm,
bsh = dpb.bsh,
bytesPerSector = 512,
cylinders = 40,
drm = dpb.drm,
dsm = dpb.dsm,
encoding = "MFM",
evenOdd = false,
exm = dpb.exm,
label = null,
comment = "CP/M-86 floppy identifier",
ofs = dpb.off,
sectorsPerTrack = 8,
side1 = new Side {sideId = 0, sectorIds = new int[8]},
skew = 0,
sofs = 0
side1 = new Side {sideId = 0, sectorIds = new int[8]},
skew = 0,
sofs = 0
};
for(int si = 0; si < 8; si++) workingDefinition.side1.sectorIds[si] = si + 1;
@@ -447,7 +452,7 @@ namespace DiscImageChef.Filesystems.CPM
case FormatByte.k320:
if(imagePlugin.Info.SectorSize == 512 && imagePlugin.Info.Sectors == 640)
{
cpmFound = true;
cpmFound = true;
firstDirectorySector86 = 16;
dpb = new DiscParameterBlock
{
@@ -467,27 +472,27 @@ namespace DiscImageChef.Filesystems.CPM
workingDefinition = new CpmDefinition
{
al0 = dpb.al0,
al1 = dpb.al1,
bitrate = "LOW",
blm = dpb.blm,
bsh = dpb.bsh,
bytesPerSector = 512,
cylinders = 40,
drm = dpb.drm,
dsm = dpb.dsm,
encoding = "MFM",
evenOdd = false,
exm = dpb.exm,
label = null,
comment = "CP/M-86 floppy identifier",
ofs = dpb.off,
al0 = dpb.al0,
al1 = dpb.al1,
bitrate = "LOW",
blm = dpb.blm,
bsh = dpb.bsh,
bytesPerSector = 512,
cylinders = 40,
drm = dpb.drm,
dsm = dpb.dsm,
encoding = "MFM",
evenOdd = false,
exm = dpb.exm,
label = null,
comment = "CP/M-86 floppy identifier",
ofs = dpb.off,
sectorsPerTrack = 8,
side1 = new Side {sideId = 0, sectorIds = new int[8]},
order = "SIDES",
side2 = new Side {sideId = 1, sectorIds = new int[8]},
skew = 0,
sofs = 0
side1 = new Side {sideId = 0, sectorIds = new int[8]},
order = "SIDES",
side2 = new Side {sideId = 1, sectorIds = new int[8]},
skew = 0,
sofs = 0
};
for(int si = 0; si < 8; si++) workingDefinition.side1.sectorIds[si] = si + 1;
@@ -500,7 +505,7 @@ namespace DiscImageChef.Filesystems.CPM
case FormatByte.k360Alt2:
if(imagePlugin.Info.SectorSize == 512 && imagePlugin.Info.Sectors == 720)
{
cpmFound = true;
cpmFound = true;
firstDirectorySector86 = 36;
dpb = new DiscParameterBlock
{
@@ -520,27 +525,27 @@ namespace DiscImageChef.Filesystems.CPM
workingDefinition = new CpmDefinition
{
al0 = dpb.al0,
al1 = dpb.al1,
bitrate = "LOW",
blm = dpb.blm,
bsh = dpb.bsh,
bytesPerSector = 512,
cylinders = 40,
drm = dpb.drm,
dsm = dpb.dsm,
encoding = "MFM",
evenOdd = false,
exm = dpb.exm,
label = null,
comment = "CP/M-86 floppy identifier",
ofs = dpb.off,
al0 = dpb.al0,
al1 = dpb.al1,
bitrate = "LOW",
blm = dpb.blm,
bsh = dpb.bsh,
bytesPerSector = 512,
cylinders = 40,
drm = dpb.drm,
dsm = dpb.dsm,
encoding = "MFM",
evenOdd = false,
exm = dpb.exm,
label = null,
comment = "CP/M-86 floppy identifier",
ofs = dpb.off,
sectorsPerTrack = 9,
side1 = new Side {sideId = 0, sectorIds = new int[9]},
order = "SIDES",
side2 = new Side {sideId = 1, sectorIds = new int[9]},
skew = 0,
sofs = 0
side1 = new Side {sideId = 0, sectorIds = new int[9]},
order = "SIDES",
side2 = new Side {sideId = 1, sectorIds = new int[9]},
skew = 0,
sofs = 0
};
for(int si = 0; si < 9; si++) workingDefinition.side1.sectorIds[si] = si + 1;
@@ -552,7 +557,7 @@ namespace DiscImageChef.Filesystems.CPM
case FormatByte.k720Alt:
if(imagePlugin.Info.SectorSize == 512 && imagePlugin.Info.Sectors == 1440)
{
cpmFound = true;
cpmFound = true;
firstDirectorySector86 = 36;
dpb = new DiscParameterBlock
{
@@ -572,27 +577,27 @@ namespace DiscImageChef.Filesystems.CPM
workingDefinition = new CpmDefinition
{
al0 = dpb.al0,
al1 = dpb.al1,
bitrate = "LOW",
blm = dpb.blm,
bsh = dpb.bsh,
bytesPerSector = 512,
cylinders = 80,
drm = dpb.drm,
dsm = dpb.dsm,
encoding = "MFM",
evenOdd = false,
exm = dpb.exm,
label = null,
comment = "CP/M-86 floppy identifier",
ofs = dpb.off,
al0 = dpb.al0,
al1 = dpb.al1,
bitrate = "LOW",
blm = dpb.blm,
bsh = dpb.bsh,
bytesPerSector = 512,
cylinders = 80,
drm = dpb.drm,
dsm = dpb.dsm,
encoding = "MFM",
evenOdd = false,
exm = dpb.exm,
label = null,
comment = "CP/M-86 floppy identifier",
ofs = dpb.off,
sectorsPerTrack = 9,
side1 = new Side {sideId = 0, sectorIds = new int[9]},
order = "SIDES",
side2 = new Side {sideId = 1, sectorIds = new int[9]},
skew = 0,
sofs = 0
side1 = new Side {sideId = 0, sectorIds = new int[9]},
order = "SIDES",
side2 = new Side {sideId = 1, sectorIds = new int[9]},
skew = 0,
sofs = 0
};
for(int si = 0; si < 9; si++) workingDefinition.side1.sectorIds[si] = si + 1;
@@ -603,7 +608,7 @@ namespace DiscImageChef.Filesystems.CPM
case FormatByte.f720:
if(imagePlugin.Info.SectorSize == 512 && imagePlugin.Info.Sectors == 1440)
{
cpmFound = true;
cpmFound = true;
firstDirectorySector86 = 18;
dpb = new DiscParameterBlock
{
@@ -623,27 +628,27 @@ namespace DiscImageChef.Filesystems.CPM
workingDefinition = new CpmDefinition
{
al0 = dpb.al0,
al1 = dpb.al1,
bitrate = "LOW",
blm = dpb.blm,
bsh = dpb.bsh,
bytesPerSector = 512,
cylinders = 80,
drm = dpb.drm,
dsm = dpb.dsm,
encoding = "MFM",
evenOdd = false,
exm = dpb.exm,
label = null,
comment = "CP/M-86 floppy identifier",
ofs = dpb.off,
al0 = dpb.al0,
al1 = dpb.al1,
bitrate = "LOW",
blm = dpb.blm,
bsh = dpb.bsh,
bytesPerSector = 512,
cylinders = 80,
drm = dpb.drm,
dsm = dpb.dsm,
encoding = "MFM",
evenOdd = false,
exm = dpb.exm,
label = null,
comment = "CP/M-86 floppy identifier",
ofs = dpb.off,
sectorsPerTrack = 9,
side1 = new Side {sideId = 0, sectorIds = new int[9]},
order = "CYLINDERS",
side2 = new Side {sideId = 1, sectorIds = new int[9]},
skew = 0,
sofs = 0
side1 = new Side {sideId = 0, sectorIds = new int[9]},
order = "CYLINDERS",
side2 = new Side {sideId = 1, sectorIds = new int[9]},
skew = 0,
sofs = 0
};
for(int si = 0; si < 9; si++) workingDefinition.side1.sectorIds[si] = si + 1;
@@ -654,7 +659,7 @@ namespace DiscImageChef.Filesystems.CPM
case FormatByte.f1200:
if(imagePlugin.Info.SectorSize == 512 && imagePlugin.Info.Sectors == 2400)
{
cpmFound = true;
cpmFound = true;
firstDirectorySector86 = 30;
dpb = new DiscParameterBlock
{
@@ -674,27 +679,27 @@ namespace DiscImageChef.Filesystems.CPM
workingDefinition = new CpmDefinition
{
al0 = dpb.al0,
al1 = dpb.al1,
bitrate = "HIGH",
blm = dpb.blm,
bsh = dpb.bsh,
bytesPerSector = 512,
cylinders = 80,
drm = dpb.drm,
dsm = dpb.dsm,
encoding = "MFM",
evenOdd = false,
exm = dpb.exm,
label = null,
comment = "CP/M-86 floppy identifier",
ofs = dpb.off,
al0 = dpb.al0,
al1 = dpb.al1,
bitrate = "HIGH",
blm = dpb.blm,
bsh = dpb.bsh,
bytesPerSector = 512,
cylinders = 80,
drm = dpb.drm,
dsm = dpb.dsm,
encoding = "MFM",
evenOdd = false,
exm = dpb.exm,
label = null,
comment = "CP/M-86 floppy identifier",
ofs = dpb.off,
sectorsPerTrack = 15,
side1 = new Side {sideId = 0, sectorIds = new int[15]},
order = "CYLINDERS",
side2 = new Side {sideId = 1, sectorIds = new int[15]},
skew = 0,
sofs = 0
side1 = new Side {sideId = 0, sectorIds = new int[15]},
order = "CYLINDERS",
side2 = new Side {sideId = 1, sectorIds = new int[15]},
skew = 0,
sofs = 0
};
for(int si = 0; si < 15; si++) workingDefinition.side1.sectorIds[si] = si + 1;
@@ -705,7 +710,7 @@ namespace DiscImageChef.Filesystems.CPM
case FormatByte.f1440:
if(imagePlugin.Info.SectorSize == 512 && imagePlugin.Info.Sectors == 2880)
{
cpmFound = true;
cpmFound = true;
firstDirectorySector86 = 36;
dpb = new DiscParameterBlock
{
@@ -725,27 +730,27 @@ namespace DiscImageChef.Filesystems.CPM
workingDefinition = new CpmDefinition
{
al0 = dpb.al0,
al1 = dpb.al1,
bitrate = "LOW",
blm = dpb.blm,
bsh = dpb.bsh,
bytesPerSector = 512,
cylinders = 80,
drm = dpb.drm,
dsm = dpb.dsm,
encoding = "MFM",
evenOdd = false,
exm = dpb.exm,
label = null,
comment = "CP/M-86 floppy identifier",
ofs = dpb.off,
al0 = dpb.al0,
al1 = dpb.al1,
bitrate = "LOW",
blm = dpb.blm,
bsh = dpb.bsh,
bytesPerSector = 512,
cylinders = 80,
drm = dpb.drm,
dsm = dpb.dsm,
encoding = "MFM",
evenOdd = false,
exm = dpb.exm,
label = null,
comment = "CP/M-86 floppy identifier",
ofs = dpb.off,
sectorsPerTrack = 18,
side1 = new Side {sideId = 0, sectorIds = new int[18]},
order = "CYLINDERS",
side2 = new Side {sideId = 1, sectorIds = new int[18]},
skew = 0,
sofs = 0
side1 = new Side {sideId = 0, sectorIds = new int[18]},
order = "CYLINDERS",
side2 = new Side {sideId = 1, sectorIds = new int[18]},
skew = 0,
sofs = 0
};
for(int si = 0; si < 18; si++) workingDefinition.side1.sectorIds[si] = si + 1;
@@ -786,7 +791,7 @@ namespace DiscImageChef.Filesystems.CPM
foreach(CpmDefinition def in from def in definitions.definitions
let sectors =
(ulong)(def.cylinders * def.sides * def.sectorsPerTrack)
where sectors == imagePlugin.Info.Sectors &&
where sectors == imagePlugin.Info.Sectors &&
def.bytesPerSector == imagePlugin.Info.SectorSize
select def)
{
@@ -794,7 +799,7 @@ 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);
else offset = (ulong)(def.ofs * def.sectorsPerTrack);
int dirLen = (def.drm + 1) * 32 / def.bytesPerSector;
@@ -828,7 +833,8 @@ namespace DiscImageChef.Filesystems.CPM
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;
def.side1.sectorIds.Length +
def.side2.sectorIds.Length;
}
// TODO: Implement COLUMBIA ordering
else if(string.Compare(def.order, "COLUMBIA",
@@ -839,9 +845,8 @@ namespace DiscImageChef.Filesystems.CPM
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.");
@@ -861,7 +866,8 @@ namespace DiscImageChef.Filesystems.CPM
for(int p = 0; p < dirLen; p++)
{
byte[] dirSector =
imagePlugin.ReadSector((ulong)((int)offset + (int)partition.Start +
imagePlugin.ReadSector((ulong)((int)offset +
(int)partition.Start +
p / sectorMask.Length * sectorMask.Length +
sectorMask[p % sectorMask.Length]));
ms.Write(dirSector, 0, dirSector.Length);
@@ -875,7 +881,8 @@ namespace DiscImageChef.Filesystems.CPM
// Complement of the directory bytes if needed
if(def.complement)
for(int b = 0; b < directory.Length; b++) directory[b] = (byte)(~directory[b] & 0xFF);
for(int b = 0; b < directory.Length; b++)
directory[b] = (byte)(~directory[b] & 0xFF);
// Check the directory
if(CheckDir(directory))
@@ -939,25 +946,25 @@ namespace DiscImageChef.Filesystems.CPM
break;
}
cpmFound = true;
cpmFound = true;
workingDefinition = def;
return true;
}
label = null;
label = null;
labelCreationDate = null;
labelUpdateDate = null;
labelUpdateDate = null;
}
}
}
// Clear class variables
cpmFound = false;
workingDefinition = null;
dpb = null;
label = null;
standardTimestamps = false;
cpmFound = false;
workingDefinition = null;
dpb = null;
label = null;
standardTimestamps = false;
thirdPartyTimestamps = false;
return false;
}
@@ -969,9 +976,9 @@ namespace DiscImageChef.Filesystems.CPM
}
public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
Encoding encoding)
Encoding encoding)
{
Encoding = encoding ?? Encoding.GetEncoding("IBM437");
Encoding = encoding ?? Encoding.GetEncoding("IBM437");
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;
@@ -1007,6 +1014,7 @@ namespace DiscImageChef.Filesystems.CPM
if(interleaveSide2 > 1)
sb.AppendFormat("Side 1 uses {0}:1 software interleaving", interleaveSide2).AppendLine();
}
switch(workingDefinition.order)
{
case "SIDES":
@@ -1044,22 +1052,24 @@ namespace DiscImageChef.Filesystems.CPM
if(labelUpdateDate != null)
sb.AppendFormat("Volume updated on {0}", DateHandlers.CpmToDateTime(labelUpdateDate)).AppendLine();
XmlFsType = new FileSystemType();
XmlFsType.Bootable |= workingDefinition.sofs > 0 || workingDefinition.ofs > 0;
XmlFsType.ClusterSize = 128 << dpb.bsh;
XmlFsType = new 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);
else XmlFsType.Clusters = (long)(partition.End - partition.Start);
if(labelCreationDate != null)
{
XmlFsType.CreationDate = DateHandlers.CpmToDateTime(labelCreationDate);
XmlFsType.CreationDate = DateHandlers.CpmToDateTime(labelCreationDate);
XmlFsType.CreationDateSpecified = true;
}
if(labelUpdateDate != null)
{
XmlFsType.ModificationDate = DateHandlers.CpmToDateTime(labelUpdateDate);
XmlFsType.ModificationDate = DateHandlers.CpmToDateTime(labelUpdateDate);
XmlFsType.ModificationDateSpecified = true;
}
XmlFsType.Type = "CP/M";
XmlFsType.Type = "CP/M";
XmlFsType.VolumeName = label;
information = sb.ToString();

View File

@@ -176,7 +176,8 @@ 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>
@@ -288,7 +289,8 @@ 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
@@ -305,15 +307,18 @@ 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>
@@ -329,11 +334,13 @@ 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;
/// <summary>
/// File 1 modification timestamp
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] date2;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] date2;
/// <summary>
/// File 1 password mode
/// </summary>
@@ -342,11 +349,13 @@ 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>
@@ -355,11 +364,13 @@ 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>
@@ -380,11 +391,13 @@ 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>
@@ -393,12 +406,15 @@ 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>
@@ -415,39 +431,48 @@ 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>
@@ -463,11 +488,13 @@ 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>
@@ -489,7 +516,8 @@ 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>
@@ -505,11 +533,13 @@ 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>
@@ -531,7 +561,8 @@ 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

@@ -76,7 +76,7 @@ namespace DiscImageChef.Filesystems.CPM
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] =
sectorMask[m + workingDefinition.side1.sectorIds.Length] =
workingDefinition.side2.sectorIds[m] - workingDefinition.side2.sectorIds[0] +
workingDefinition.side1.sectorIds.Length;
}
@@ -88,9 +88,10 @@ namespace DiscImageChef.Filesystems.CPM
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.");
@@ -132,7 +133,7 @@ namespace DiscImageChef.Filesystems.CPM
{
byte[] readSector =
device.ReadSector((ulong)((int)partition.Start + p / sectorMask.Length * sectorMask.Length +
sectorMask[p % sectorMask.Length]));
sectorMask[p % sectorMask.Length]));
if(workingDefinition.complement)
for(int b = 0; b < readSector.Length; b++)
readSector[b] = (byte)(~readSector[b] & 0xFF);
@@ -155,7 +156,7 @@ namespace DiscImageChef.Filesystems.CPM
deinterleavedSectors.TryGetValue(a, out byte[] sector);
// May it happen? Just in case, CP/M blocks are smaller than physical sectors
if(sector.Length > blockSize)
if(sector.Length > blockSize)
for(int i = 0; i < sector.Length / blockSize; i++)
{
byte[] tmp = new byte[blockSize];
@@ -175,14 +176,13 @@ namespace DiscImageChef.Filesystems.CPM
blockMs = new MemoryStream();
}
// 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;
int dirSectors = (dpb.drm + 1) * 32 / workingDefinition.bytesPerSector;
if(workingDefinition.sofs > 0) dirOff = workingDefinition.sofs;
else dirOff = workingDefinition.ofs * workingDefinition.sectorsPerTrack;
@@ -198,15 +198,15 @@ namespace DiscImageChef.Filesystems.CPM
if(directory == null) return Errno.InvalidArgument;
int dirCnt = 0;
string file1 = null;
string file2 = null;
string file3 = null;
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>>>();
statCache = new Dictionary<string, FileEntryInfo>();
cpmStat = new FileSystemInfo();
bool atime = false;
statCache = new Dictionary<string, FileEntryInfo>();
cpmStat = new FileSystemInfo();
bool atime = false;
dirList = new List<string>();
labelCreationDate = null;
labelUpdateDate = null;
@@ -218,7 +218,7 @@ namespace DiscImageChef.Filesystems.CPM
// For each directory entry
for(int dOff = 0; dOff < directory.Length; dOff += 32)
// Describes a file (does not support PDOS entries with user >= 16, because they're identical to password entries
if((directory[dOff] & 0x7F) < 0x10)
if((directory[dOff] & 0x7F) < 0x10)
if(allocationBlocks.Count > 256)
{
dirPtr = Marshal.AllocHGlobal(32);
@@ -227,7 +227,7 @@ namespace DiscImageChef.Filesystems.CPM
(DirectoryEntry16)Marshal.PtrToStructure(dirPtr, typeof(DirectoryEntry16));
Marshal.FreeHGlobal(dirPtr);
bool hidden = (entry.statusUser & 0x80) == 0x80;
bool hidden = (entry.statusUser & 0x80) == 0x80;
bool rdOnly = (entry.filename[0] & 0x80) == 0x80 || (entry.extension[0] & 0x80) == 0x80;
bool system = (entry.filename[1] & 0x80) == 0x80 || (entry.extension[2] & 0x80) == 0x80;
//bool backed = (entry.filename[3] & 0x80) == 0x80 || (entry.extension[3] & 0x80) == 0x80;
@@ -316,7 +316,7 @@ namespace DiscImageChef.Filesystems.CPM
DirectoryEntry entry = (DirectoryEntry)Marshal.PtrToStructure(dirPtr, typeof(DirectoryEntry));
Marshal.FreeHGlobal(dirPtr);
bool hidden = (entry.statusUser & 0x80) == 0x80;
bool hidden = (entry.statusUser & 0x80) == 0x80;
bool rdOnly = (entry.filename[0] & 0x80) == 0x80 || (entry.extension[0] & 0x80) == 0x80;
bool system = (entry.filename[1] & 0x80) == 0x80 || (entry.extension[2] & 0x80) == 0x80;
//bool backed = (entry.filename[3] & 0x80) == 0x80 || (entry.extension[3] & 0x80) == 0x80;
@@ -553,8 +553,8 @@ namespace DiscImageChef.Filesystems.CPM
else fInfo = new FileEntryInfo();
byte[] ctime = new byte[4];
ctime[0] = trdPartyDateEntry.create1[0];
ctime[1] = trdPartyDateEntry.create1[1];
ctime[0] = trdPartyDateEntry.create1[0];
ctime[1] = trdPartyDateEntry.create1[1];
fInfo.AccessTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.access1);
fInfo.CreationTime = DateHandlers.CpmToDateTime(ctime);
@@ -569,8 +569,8 @@ namespace DiscImageChef.Filesystems.CPM
else fInfo = new FileEntryInfo();
byte[] ctime = new byte[4];
ctime[0] = trdPartyDateEntry.create2[0];
ctime[1] = trdPartyDateEntry.create2[1];
ctime[0] = trdPartyDateEntry.create2[0];
ctime[1] = trdPartyDateEntry.create2[1];
fInfo.AccessTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.access2);
fInfo.CreationTime = DateHandlers.CpmToDateTime(ctime);
@@ -585,8 +585,8 @@ namespace DiscImageChef.Filesystems.CPM
else fInfo = new FileEntryInfo();
byte[] ctime = new byte[4];
ctime[0] = trdPartyDateEntry.create3[0];
ctime[1] = trdPartyDateEntry.create3[1];
ctime[0] = trdPartyDateEntry.create3[0];
ctime[1] = trdPartyDateEntry.create3[1];
fInfo.AccessTime = DateHandlers.CpmToDateTime(trdPartyDateEntry.access3);
fInfo.CreationTime = DateHandlers.CpmToDateTime(ctime);
@@ -608,7 +608,7 @@ namespace DiscImageChef.Filesystems.CPM
// this should not be a problem
DicConsole.DebugWriteLine("CP/M Plugin", "Reading files.");
long usedBlocks = 0;
fileCache = new Dictionary<string, byte[]>();
fileCache = new Dictionary<string, byte[]>();
foreach(string filename in dirList)
{
MemoryStream fileMs = new MemoryStream();

View File

@@ -54,7 +54,8 @@ namespace DiscImageChef.Filesystems.CPM
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)
return Errno.NoSuchExtendedAttribute;