Improved the nibble recognition a bit. It can deduce simple protected DOS disks. (DOS file system does not, so 'dump' can be used to verify.)

This commit is contained in:
Rob Greene
2025-09-06 11:05:12 -05:00
parent e86d2f0fc8
commit 18693ebea8
3 changed files with 29 additions and 25 deletions

View File

@@ -67,9 +67,9 @@ public class TrackSectorNibbleDevice implements TrackSectorDevice {
TrackSectorDevice device = new TrackSectorNibbleDevice(trackReaderWriter,
new Nibble62Disk525Codec(), sectorsPerTrack, DiskMarker.disk525sector16());
int count = 0;
for (int sector = 0; sector < sectorsPerTrack; sector++) {
for (int track = 0; track < trackReaderWriter.getTracksOnDevice(); track++) {
try {
DataBuffer sectorData = device.readSector(0, sector);
DataBuffer sectorData = device.readSector(track, sectorsPerTrack-1);
if (sectorData.limit() == TrackSectorDevice.SECTOR_SIZE) {
count++;
}
@@ -78,7 +78,7 @@ public class TrackSectorNibbleDevice implements TrackSectorDevice {
}
}
if (count > 3) {
// Just making certain we read more than sector 0
// Just making certain we read more than track 0
return Optional.of(device);
}
@@ -87,9 +87,9 @@ public class TrackSectorNibbleDevice implements TrackSectorDevice {
device = new TrackSectorNibbleDevice(trackReaderWriter,
new Nibble53Disk525Codec(), sectorsPerTrack, DiskMarker.disk525sector13());
count = 0;
for (int sector = 0; sector < sectorsPerTrack; sector++) {
for (int track = 0; track < trackReaderWriter.getTracksOnDevice(); track++) {
try {
DataBuffer sectorData = device.readSector(0, sector);
DataBuffer sectorData = device.readSector(track, sectorsPerTrack-1);
if (sectorData.limit() == TrackSectorDevice.SECTOR_SIZE) {
count++;
}

View File

@@ -46,22 +46,23 @@ public class NibbleScanner {
int successCount = 0;
for (int track=0; track<tracksOnDevice; track++) {
DataBuffer trackData = trackReaderWriter.readTrackData(track);
final int trackLength = trackData.limit();
// Generate a list of likely address prologs (that meet the expected 4&4 encodings and structure)
Map<Integer, Set<Integer>> addressPrologs = findAddressPrologs(track, trackData);
final int foundSectors = addressPrologs.values().stream().map(Collection::size).max(Integer::compareTo).orElseThrow();
// Assumption: Track is "mostly" normal, so 5&3 or 6&2 along with expected 13- and 16-sector sizing:
// (with the exception of track 0)
// (except for track 0 since it's possibly a mix of "expected" prolog and protected prolog bytes)
if (track != 0) {
if (foundSectors != 13 && foundSectors != 16) {
// Expecting 13 or 16 sector (just not track zero)
// Expecting 13 or 16 sector (just not track zero) -- fill in a fake DiskMarker just for sanity
diskMarkers[track] = foundSectors <= 13 ? DiskMarker.disk525sector13() : DiskMarker.disk525sector16();
break;
}
if (sectorsOnTrack == 0 || sectorsOnTrack == foundSectors) {
sectorsOnTrack = foundSectors;
} else {
// Expecting same sector count
// Expecting same sector count -- fill in DiskMarker just for sanity
successCount = 0;
diskMarkers[track] = foundSectors == 13 ? DiskMarker.disk525sector13() : DiskMarker.disk525sector16();
break;
}
}
@@ -72,19 +73,19 @@ public class NibbleScanner {
.findFirst().orElseThrow();
// Scan from an address prolog, look for (self?) sync bytes, and then assume next 3 are data prolog
int dataProlog = findDataProlog(addressProlog, trackData);
// Save
// Save (always, prevent easy NPE's in other code)
final int addr1 = (addressProlog >> 16) & 0xff;
final int addr2 = (addressProlog >> 8) & 0xff;
final int addr3 = addressProlog & 0xff;
final int data1 = (dataProlog >> 16) & 0xff;
final int data2 = (dataProlog >> 8) & 0xff;
final int data3 = dataProlog & 0xff;
diskMarkers[track] = DiskMarker.build()
.addressProlog(addr1, addr2, addr3).addressEpilog()
.dataProlog(data1, data2, data3).dataEpilog()
.get();
// Only tally good ones
if (dataProlog != 0) {
final int addr1 = (addressProlog >> 16) & 0xff;
final int addr2 = (addressProlog >> 8) & 0xff;
final int addr3 = addressProlog & 0xff;
final int data1 = (dataProlog >> 16) & 0xff;
final int data2 = (dataProlog >> 8) & 0xff;
final int data3 = dataProlog & 0xff;
diskMarkers[track] = DiskMarker.build()
.addressProlog(addr1, addr2, addr3).addressEpilog()
.dataProlog(data1, data2, data3).dataEpilog()
.get();
successCount++;
}
}
@@ -106,7 +107,7 @@ public class NibbleScanner {
Map<Integer, Set<Integer>> addressPrologs = new HashMap<>();
final int headerLength = 14;
final int trackLength = trackData.limit();
for (int i = 0; i < trackLength + headerLength; i++) {
for (int i = 5; i < trackLength + headerLength; i++) {
int trk = decodeOddEven(trackData, i % trackLength);
if (trk == track) {
int sct = decodeOddEven(trackData, (i + 2) % trackLength);

View File

@@ -32,8 +32,9 @@ public class NibbleUtil {
* See page 3-12 in Beneath Apple DOS for more information.
*/
public static int decodeOddEven(DataBuffer rawData, int offset) {
int b1 = rawData.getUnsignedByte(offset);
int b2 = rawData.getUnsignedByte(offset+1);
final int limit = rawData.limit();
int b1 = rawData.getUnsignedByte(offset % limit);
int b2 = rawData.getUnsignedByte((offset+1) % limit);
return (b1 << 1 | 0x01) & b2;
}
@@ -45,6 +46,8 @@ public class NibbleUtil {
public static void encodeOddEven(DataBuffer data, int offset, int value) {
int b1 = (value >> 1) | 0xaa;
int b2 = value | 0xaa;
data.putBytes(offset, b1, b2);
final int limit = data.limit();
data.putByte(offset % limit, b1);
data.putByte((offset + 1) % limit, b2);
}
}