mirror of
https://github.com/aaru-dps/Aaru.Server.git
synced 2025-12-16 19:24:27 +00:00
Code cleanup.
This commit is contained in:
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user