mirror of
https://github.com/AppleCommander/AppleCommander.git
synced 2026-01-22 17:16:11 +00:00
Revamping CPM detection a bit based on scan results.
This commit is contained in:
@@ -24,6 +24,9 @@ import org.applecommander.device.*;
|
||||
import org.applecommander.hint.Hint;
|
||||
import org.applecommander.util.DataBuffer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Test this disk for a likely CP/M filesystem.
|
||||
* @see <a href="https://www.seasip.info/Cpm/format22.html">CP/M 2.2</a>
|
||||
@@ -32,6 +35,7 @@ import org.applecommander.util.DataBuffer;
|
||||
public class CpmDiskFactory implements DiskFactory {
|
||||
@Override
|
||||
public void inspect(Context ctx) {
|
||||
List<CpmFormatDisk> candidates = new ArrayList<>();
|
||||
ctx.trackSectorDevice()
|
||||
.include16Sector(Hint.DOS_SECTOR_ORDER)
|
||||
.get()
|
||||
@@ -40,41 +44,57 @@ public class CpmDiskFactory implements DiskFactory {
|
||||
SkewedTrackSectorDevice.dosToCpmSkew(device),
|
||||
TrackSectorToBlockAdapter.BlockStyle.CPM);
|
||||
CpmFormatDisk disk = new CpmFormatDisk(ctx.source.getName(), blockDevice);
|
||||
if (check(disk)) {
|
||||
ctx.disks.add(disk);
|
||||
}
|
||||
candidates.add(disk);
|
||||
});
|
||||
// Look for the one with the largest directory entry
|
||||
int maxFileCount = -1;
|
||||
CpmFormatDisk selectedDisk = null;
|
||||
for (CpmFormatDisk candidate : candidates) {
|
||||
int count = check(candidate);
|
||||
if (count != -1 && count > maxFileCount) {
|
||||
selectedDisk = candidate;
|
||||
maxFileCount = count;
|
||||
}
|
||||
}
|
||||
if (selectedDisk != null) {
|
||||
ctx.disks.add(selectedDisk);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean check(CpmFormatDisk disk) {
|
||||
public int check(CpmFormatDisk disk) {
|
||||
DataBuffer entries = DataBuffer.wrap(disk.readCpmFileEntries());
|
||||
int offset = 0;
|
||||
int count = 0;
|
||||
while (offset < entries.limit()) {
|
||||
// Check if this is an empty directory entry (and ignore it)
|
||||
int e5count = 0;
|
||||
for (int i=0; i<CpmFileEntry.ENTRY_LENGTH; i++) {
|
||||
e5count+= entries.getUnsignedByte(offset+i) == 0xe5 ? 1 : 0;
|
||||
}
|
||||
if (e5count != CpmFileEntry.ENTRY_LENGTH) { // Not all bytes were 0xE5
|
||||
// Check user number. Should be 0-15 or 0xE5
|
||||
int userNumber = entries.getUnsignedByte(offset);
|
||||
if (userNumber > 0x1f && userNumber != 0xe5) return false;
|
||||
// Validate filename has highbit off and is a character
|
||||
for (int i=0; i<8; i++) {
|
||||
int ch = entries.getUnsignedByte(offset+1+i);
|
||||
if (ch < 0x20 || ch > 127) return false;
|
||||
}
|
||||
// Extent should be 0-31 (low = 0-31 and high = 0)
|
||||
int exLow = entries.getUnsignedByte(offset+0xc);
|
||||
int exHighS2 = entries.getUnsignedByte(offset+0xe);
|
||||
if (exLow > 31 || exHighS2 > 0) return false;
|
||||
// Number of used records cannot exceed 0x80
|
||||
int numberOfRecords = entries.getUnsignedByte(offset+0xf);
|
||||
if (numberOfRecords > 0x80) return false;
|
||||
if (e5count == CpmFileEntry.ENTRY_LENGTH) {
|
||||
// If we find a fully blank entry, assume we are done. Should assist with sector order determination.
|
||||
return count;
|
||||
}
|
||||
// Not all bytes were 0xE5
|
||||
// Check user number. Should be 0-15 or 0xE5
|
||||
int userNumber = entries.getUnsignedByte(offset);
|
||||
if (userNumber > 0x1f && userNumber != 0xe5) return -1;
|
||||
// Validate filename has highbit off and is a character
|
||||
for (int i=0; i<8; i++) {
|
||||
int ch = entries.getUnsignedByte(offset+1+i);
|
||||
if (ch < 0x20 || ch > 127) return -1;
|
||||
}
|
||||
// Extent should be 0-31 (low = 0-31 and high = 0)
|
||||
int exLow = entries.getUnsignedByte(offset+0xc);
|
||||
int exHighS2 = entries.getUnsignedByte(offset+0xe);
|
||||
if (exLow > 31 || exHighS2 > 0) return -1;
|
||||
// Number of used records cannot exceed 0x80
|
||||
int numberOfRecords = entries.getUnsignedByte(offset+0xf);
|
||||
if (numberOfRecords > 0x80) return -1;
|
||||
count++;
|
||||
// Next entry
|
||||
offset+= CpmFileEntry.ENTRY_LENGTH;
|
||||
}
|
||||
return true;
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user