diff --git a/src/com/bytezone/diskbrowser/cpm/CPMDisk.java b/src/com/bytezone/diskbrowser/cpm/CPMDisk.java index 2b137f7..c9ca0fe 100644 --- a/src/com/bytezone/diskbrowser/cpm/CPMDisk.java +++ b/src/com/bytezone/diskbrowser/cpm/CPMDisk.java @@ -24,6 +24,7 @@ public class CPMDisk extends AbstractFormattedDisk public final SectorType macSector = new SectorType ("MAC", Color.green); private int version; // http://www.seasip.info/Cpm/format22.html + // // http://www.seasip.info/Cpm/format31.html public CPMDisk (Disk disk) { diff --git a/src/com/bytezone/diskbrowser/disk/AppleDisk.java b/src/com/bytezone/diskbrowser/disk/AppleDisk.java index e619c15..761ee6a 100755 --- a/src/com/bytezone/diskbrowser/disk/AppleDisk.java +++ b/src/com/bytezone/diskbrowser/disk/AppleDisk.java @@ -231,30 +231,16 @@ public class AppleDisk implements Disk this.tracks = tracks; this.sectors = sectors; file = disk.file; + diskBuffer = disk.diskBuffer; if (sectors == 13) { trackSize = 0xD00; sectorSize = 256; - diskBuffer = new byte[116480]; - - int ptr = 0; - for (int track = 0; track < 35; track++) - { - for (int sector = 0; sector < 13; sector++) - { - int ptr2 = track * 0xD00 + sector * 0x100; - System.arraycopy (disk.diskBuffer, ptr, diskBuffer, ptr2, 0x100); - // System.out.printf ("Copying %04X -> %04X%n", ptr, ptr2); - ptr += 0x100; - } - ptr += 0x300; // skip 3 sectors - } } else { - trackSize = 4096; - diskBuffer = disk.diskBuffer; + trackSize = 0x1000; sectorSize = trackSize / sectors; } diff --git a/src/com/bytezone/diskbrowser/disk/ByteTranslator.java b/src/com/bytezone/diskbrowser/disk/ByteTranslator.java new file mode 100644 index 0000000..b48e46d --- /dev/null +++ b/src/com/bytezone/diskbrowser/disk/ByteTranslator.java @@ -0,0 +1,8 @@ +package com.bytezone.diskbrowser.disk; + +public abstract class ByteTranslator +{ + abstract byte encode (byte b); + + abstract byte decode (byte b) throws DiskNibbleException; +} diff --git a/src/com/bytezone/diskbrowser/disk/ByteTranslator5and3.java b/src/com/bytezone/diskbrowser/disk/ByteTranslator5and3.java new file mode 100644 index 0000000..bd47137 --- /dev/null +++ b/src/com/bytezone/diskbrowser/disk/ByteTranslator5and3.java @@ -0,0 +1,68 @@ +package com.bytezone.diskbrowser.disk; + +public class ByteTranslator5and3 extends ByteTranslator +{ + // 32 valid bytes that can be stored on a disk (plus 0xAA and 0xD5) + private static byte[] writeTranslateTable5and3 = + { (byte) 0xAB, (byte) 0xAD, (byte) 0xAE, (byte) 0xAF, (byte) 0xB5, (byte) 0xB6, + (byte) 0xB7, (byte) 0xBA, (byte) 0xBB, (byte) 0xBD, (byte) 0xBE, (byte) 0xBF, + (byte) 0xD6, (byte) 0xD7, (byte) 0xDA, (byte) 0xDB, // + (byte) 0xDD, (byte) 0xDE, (byte) 0xDF, (byte) 0xEA, (byte) 0xEB, (byte) 0xED, + (byte) 0xEE, (byte) 0xEF, (byte) 0xF5, (byte) 0xF6, (byte) 0xF7, (byte) 0xFA, + (byte) 0xFB, (byte) 0xFD, (byte) 0xFE, (byte) 0xFF }; + + private static byte[] readTranslateTable5and3 = new byte[85]; // skip first 171 blanks + private static boolean debug = false; + + static + { + for (int i = 0; i < writeTranslateTable5and3.length; i++) + { + int j = (writeTranslateTable5and3[i] & 0xFF) - 0xAB; // skip first 171 blanks + readTranslateTable5and3[j] = (byte) (i + 1); // offset by 1 to avoid zero + if (debug) + System.out.printf ("%02X %02X %02X%n", i, writeTranslateTable5and3[i], j); + } + if (debug) + for (int j = 0; j < readTranslateTable5and3.length; j++) + { + int target = readTranslateTable5and3[j] - 1; + if (target >= 0) + { + int value = writeTranslateTable5and3[target] & 0xFF; + System.out.printf ("%02X -> %02X%n", j, value); + } + else + System.out.printf ("%02X%n", j); + } + } + + // ---------------------------------------------------------------------------------// + // encode + // ---------------------------------------------------------------------------------// + + @Override + byte encode (byte b) + { + return 0; + } + + // ---------------------------------------------------------------------------------// + // decode + // ---------------------------------------------------------------------------------// + + @Override + byte decode (byte b) throws DiskNibbleException + { + int val = (b & 0xFF) - 0xAB; // 0 - 84 + // assert val >= 0 && val <= 84 : "Val: " + val; + if (val < 0 || val > 84) + throw new DiskNibbleException ("Val: " + val); + byte trans = (byte) (readTranslateTable5and3[val] - 1); // 0 - 31 (5 bits) + // assert trans >= 0 && trans <= 31 : "Trans: " + trans; + if (trans < 0 || trans > 31) + throw new DiskNibbleException ("Trans: " + trans); + return (byte) (trans << 3); // left justify 5 bits + } + +} diff --git a/src/com/bytezone/diskbrowser/disk/ByteTranslator6and2.java b/src/com/bytezone/diskbrowser/disk/ByteTranslator6and2.java new file mode 100644 index 0000000..329b5ce --- /dev/null +++ b/src/com/bytezone/diskbrowser/disk/ByteTranslator6and2.java @@ -0,0 +1,50 @@ +package com.bytezone.diskbrowser.disk; + +public class ByteTranslator6and2 extends ByteTranslator +{ + // 64 valid bytes that can be stored on a disk (plus 0xAA and 0xD5) + private static byte[] writeTranslateTable6and2 = + { (byte) 0x96, (byte) 0x97, (byte) 0x9A, (byte) 0x9B, (byte) 0x9D, (byte) 0x9E, + (byte) 0x9F, (byte) 0xA6, (byte) 0xA7, (byte) 0xAB, (byte) 0xAC, (byte) 0xAD, + (byte) 0xAE, (byte) 0xAF, (byte) 0xB2, (byte) 0xB3, // + (byte) 0xB4, (byte) 0xB5, (byte) 0xB6, (byte) 0xB7, (byte) 0xB9, (byte) 0xBA, + (byte) 0xBB, (byte) 0xBC, (byte) 0xBD, (byte) 0xBE, (byte) 0xBF, (byte) 0xCB, + (byte) 0xCD, (byte) 0xCE, (byte) 0xCF, (byte) 0xD3, // + (byte) 0xD6, (byte) 0xD7, (byte) 0xD9, (byte) 0xDA, (byte) 0xDB, (byte) 0xDC, + (byte) 0xDD, (byte) 0xDE, (byte) 0xDF, (byte) 0xE5, (byte) 0xE6, (byte) 0xE7, + (byte) 0xE9, (byte) 0xEA, (byte) 0xEB, (byte) 0xEC, // + (byte) 0xED, (byte) 0xEE, (byte) 0xEF, (byte) 0xF2, (byte) 0xF3, (byte) 0xF4, + (byte) 0xF5, (byte) 0xF6, (byte) 0xF7, (byte) 0xF9, (byte) 0xFA, (byte) 0xFB, + (byte) 0xFC, (byte) 0xFD, (byte) 0xFE, (byte) 0xFF }; + + private static byte[] readTranslateTable6and2 = new byte[106]; // skip first 150 blanks + + static + { + for (int i = 0; i < writeTranslateTable6and2.length; i++) + { + int j = (writeTranslateTable6and2[i] & 0xFF) - 0x96; // skip first 150 blanks + readTranslateTable6and2[j] = (byte) (i + 1); // offset by 1 to avoid zero + } + } + + @Override + byte encode (byte b) + { + return writeTranslateTable6and2[(b & 0xFC) / 4]; + } + + @Override + byte decode (byte b) throws DiskNibbleException + { + int val = (b & 0xFF) - 0x96; // 0 - 105 + // assert val >= 0 && val <= 105 : "Val: " + val; + if (val < 0 || val > 105) + throw new DiskNibbleException ("Val: " + val); + byte trans = (byte) (readTranslateTable6and2[val] - 1); // 0 - 63 (6 bits) + // assert trans >= 0 && trans <= 63 : "Trans: " + trans; + if (trans < 0 || trans > 63) + throw new DiskNibbleException ("Trans: " + trans); + return (byte) (trans << 2); // left justify 6 bits + } +} diff --git a/src/com/bytezone/diskbrowser/disk/DiskAddressField.java b/src/com/bytezone/diskbrowser/disk/DiskAddressField.java new file mode 100644 index 0000000..a1ff083 --- /dev/null +++ b/src/com/bytezone/diskbrowser/disk/DiskAddressField.java @@ -0,0 +1,40 @@ +package com.bytezone.diskbrowser.disk; + +class DiskAddressField +{ + int track, sector, volume, checksum; + + // ---------------------------------------------------------------------------------// + // constructor + // ---------------------------------------------------------------------------------// + + DiskAddressField (byte[] buffer, int offset) + { + volume = decode4and4 (buffer, offset); + track = decode4and4 (buffer, offset + 2); + sector = decode4and4 (buffer, offset + 4); + checksum = decode4and4 (buffer, offset + 6); + } + + // ---------------------------------------------------------------------------------// + // decode4and4 + // ---------------------------------------------------------------------------------// + + int decode4and4 (byte[] buffer, int offset) + { + int odds = ((buffer[offset] & 0xFF) << 1) + 1; + int evens = buffer[offset + 1] & 0xFF; + return odds & evens; + } + + // ---------------------------------------------------------------------------------// + // toString + // ---------------------------------------------------------------------------------// + + @Override + public String toString () + { + return String.format ("[volume: %02X, track: %02X, sector: %02X, checksum: %02X]", + volume, track, sector, checksum); + } +} diff --git a/src/com/bytezone/diskbrowser/disk/DiskFactory.java b/src/com/bytezone/diskbrowser/disk/DiskFactory.java index d833bf3..977e34f 100755 --- a/src/com/bytezone/diskbrowser/disk/DiskFactory.java +++ b/src/com/bytezone/diskbrowser/disk/DiskFactory.java @@ -232,7 +232,7 @@ public class DiskFactory try { WozDisk wozDisk = new WozDisk (file); - if (wozDisk.sectorsPerTrack == 13) + if (wozDisk.getSectorsPerTrack () == 13) { AppleDisk appleDisk = new AppleDisk (wozDisk, 35, 13); disk = checkDos (appleDisk); @@ -248,7 +248,8 @@ public class DiskFactory } catch (Exception e) { - System.out.println (e); + // System.out.println (e); + e.printStackTrace (); return null; } } diff --git a/src/com/bytezone/diskbrowser/disk/DiskNibbleException.java b/src/com/bytezone/diskbrowser/disk/DiskNibbleException.java new file mode 100644 index 0000000..61bfcc2 --- /dev/null +++ b/src/com/bytezone/diskbrowser/disk/DiskNibbleException.java @@ -0,0 +1,17 @@ +package com.bytezone.diskbrowser.disk; + +public class DiskNibbleException extends Exception +{ + String message; + + public DiskNibbleException (String message) + { + this.message = message; + } + + @Override + public String toString () + { + return message; + } +} diff --git a/src/com/bytezone/diskbrowser/disk/DiskReader.java b/src/com/bytezone/diskbrowser/disk/DiskReader.java new file mode 100644 index 0000000..27e2ed2 --- /dev/null +++ b/src/com/bytezone/diskbrowser/disk/DiskReader.java @@ -0,0 +1,33 @@ +package com.bytezone.diskbrowser.disk; + +import com.bytezone.diskbrowser.disk.MC3470.DiskSector; + +public abstract class DiskReader +{ + static final int BLOCK_SIZE = 256; + static final byte[] dataPrologue = { (byte) 0xD5, (byte) 0xAA, (byte) 0xAD }; + + int sectorsPerTrack; + boolean debug = false; + + // ---------------------------------------------------------------------------------// + // constructor + // ---------------------------------------------------------------------------------// + + DiskReader (int sectorsPerTrack) + { + this.sectorsPerTrack = sectorsPerTrack; + } + + // ---------------------------------------------------------------------------------// + // abstract functions + // ---------------------------------------------------------------------------------// + + abstract byte[] decodeSector (byte[] buffer, int ptr); + + abstract byte[] encodeSector (byte[] buffer); + + abstract void storeBuffer (DiskSector diskSector, byte[] diskBuffer); + + abstract int expectedDataSize (); +} diff --git a/src/com/bytezone/diskbrowser/disk/DiskReader13Sector.java b/src/com/bytezone/diskbrowser/disk/DiskReader13Sector.java new file mode 100644 index 0000000..9f9a928 --- /dev/null +++ b/src/com/bytezone/diskbrowser/disk/DiskReader13Sector.java @@ -0,0 +1,122 @@ +package com.bytezone.diskbrowser.disk; + +import com.bytezone.diskbrowser.disk.MC3470.DiskSector; + +public class DiskReader13Sector extends DiskReader +{ + private static final int RAW_BUFFER_SIZE_DOS_32 = 410; + private static final int BUFFER_WITH_CHECKSUM_SIZE_DOS_32 = RAW_BUFFER_SIZE_DOS_32 + 1; + + private final byte[] decodeDos32a = new byte[BUFFER_WITH_CHECKSUM_SIZE_DOS_32]; + private final byte[] decodeDos32b = new byte[RAW_BUFFER_SIZE_DOS_32]; + + private final ByteTranslator byteTranslator53 = new ByteTranslator5and3 (); + + // ---------------------------------------------------------------------------------// + // constructor + // ---------------------------------------------------------------------------------// + + DiskReader13Sector () + { + super (13); + } + + // ---------------------------------------------------------------------------------// + // decodeSector + // ---------------------------------------------------------------------------------// + + @Override + byte[] decodeSector (byte[] buffer, int offset) + { + byte[] decodedBuffer = new byte[BLOCK_SIZE]; + + try + { + // convert legal disk values to actual 5 bit values + for (int i = 0; i < BUFFER_WITH_CHECKSUM_SIZE_DOS_32; i++) // 411 bytes + decodeDos32a[i] = byteTranslator53.decode (buffer[offset++]); + + // reconstruct 410 bytes each with 5 bits + byte chk = 0; + int ptr = 0; + for (int i = 409; i >= 256; i--) // 154 bytes + chk = decodeDos32b[i] = (byte) (decodeDos32a[ptr++] ^ chk); + for (int i = 0; i < 256; i++) // 256 bytes + chk = decodeDos32b[i] = (byte) (decodeDos32a[ptr++] ^ chk); + if ((chk ^ decodeDos32a[ptr]) != 0) + throw new DiskNibbleException ("Checksum failed"); + + // rearrange 410 bytes into 256 + byte[] k = new byte[8]; + final int[] lines = { 0, 51, 102, 153, 204, 256, 307, 358 }; // 255 is skipped + + // process 8 disk bytes at a time, giving 5 valid bytes + // do this 51 times, giving 255 bytes + ptr = 0; + for (int i = 50; i >= 0; i--) + { + for (int j = 0; j < 8; j++) + k[j] = decodeDos32b[i + lines[j]]; + + k[0] |= (k[5] & 0xE0) >>> 5; + k[1] |= (k[6] & 0xE0) >>> 5; + k[2] |= (k[7] & 0xE0) >>> 5; + + k[3] |= (k[5] & 0x10) >>> 2; + k[3] |= (k[6] & 0x10) >>> 3; + k[3] |= (k[7] & 0x10) >>> 4; + + k[4] |= (k[5] & 0x08) >>> 1; + k[4] |= (k[6] & 0x08) >>> 2; + k[4] |= (k[7] & 0x08) >>> 3; + + for (int j = 0; j < 5; j++) + decodedBuffer[ptr++] = k[j]; + } + + // add last byte + decodedBuffer[ptr] = + (byte) (decodeDos32b[255] | ((decodeDos32b[409] & 0x3F) >>> 3)); + } + catch (Exception e) + { + System.out.println (e); + } + + return decodedBuffer; + } + + // ---------------------------------------------------------------------------------// + // encodeSector + // ---------------------------------------------------------------------------------// + + @Override + byte[] encodeSector (byte[] buffer) + { + System.out.println ("encodeSector() not written"); + return null; + } + + // ---------------------------------------------------------------------------------// + // storeBuffer + // ---------------------------------------------------------------------------------// + + @Override + void storeBuffer (DiskSector diskSector, byte[] diskBuffer) + { + DiskAddressField addressField = diskSector.addressField; + byte[] sectorBuffer = diskSector.buffer; + int offset = addressField.track * 0x0D00 + addressField.sector * 256; + System.arraycopy (sectorBuffer, 0, diskBuffer, offset, 256); + } + + // ---------------------------------------------------------------------------------// + // expectedDataSize + // ---------------------------------------------------------------------------------// + + @Override + int expectedDataSize () + { + return 411; + } +} diff --git a/src/com/bytezone/diskbrowser/disk/DiskReader16Sector.java b/src/com/bytezone/diskbrowser/disk/DiskReader16Sector.java new file mode 100644 index 0000000..26d284f --- /dev/null +++ b/src/com/bytezone/diskbrowser/disk/DiskReader16Sector.java @@ -0,0 +1,163 @@ +package com.bytezone.diskbrowser.disk; + +import com.bytezone.diskbrowser.disk.MC3470.DiskSector; + +public class DiskReader16Sector extends DiskReader +{ + private static final int RAW_BUFFER_SIZE_DOS_33 = 342; + private static final int BUFFER_WITH_CHECKSUM_SIZE_DOS_33 = RAW_BUFFER_SIZE_DOS_33 + 1; + + private final byte[] decodeDos33a = new byte[BUFFER_WITH_CHECKSUM_SIZE_DOS_33]; + private final byte[] decodeDos33b = new byte[RAW_BUFFER_SIZE_DOS_33]; + + private final byte[] encodeDos33a = new byte[RAW_BUFFER_SIZE_DOS_33]; + private final byte[] encodeDos33b = new byte[BUFFER_WITH_CHECKSUM_SIZE_DOS_33]; + + private final ByteTranslator byteTranslator62 = new ByteTranslator6and2 (); + + private static int[] interleave = + { 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 }; + + // ---------------------------------------------------------------------------------// + // constructor + // ---------------------------------------------------------------------------------// + + DiskReader16Sector () + { + super (16); + } + + // ---------------------------------------------------------------------------------// + // decodeSector + // ---------------------------------------------------------------------------------// + + @Override + byte[] decodeSector (byte[] buffer, int offset) + { + // rearrange 342 bytes into 256 + byte[] decodedBuffer = new byte[BLOCK_SIZE]; // 256 bytes + + try + { + if (offset + BUFFER_WITH_CHECKSUM_SIZE_DOS_33 >= buffer.length) + throw new DiskNibbleException ( + String.format ("Buffer not long enough (need %d, found %d)", + BUFFER_WITH_CHECKSUM_SIZE_DOS_33, buffer.length - offset)); + + // convert legal disk values to actual 6 bit values + for (int i = 0; i < BUFFER_WITH_CHECKSUM_SIZE_DOS_33; i++) // 343 bytes + { + if (offset == buffer.length) + offset = 0; + decodeDos33a[i] = byteTranslator62.decode (buffer[offset++]); + } + + // reconstruct 342 bytes each with 6 bits + byte chk = 0; + for (int i = decodeDos33b.length - 1; i >= 0; i--) // 342 bytes + chk = decodeDos33b[i] = (byte) (decodeDos33a[i + 1] ^ chk); + if ((chk ^ decodeDos33a[0]) != 0) + throw new DiskNibbleException ("Checksum failed"); + + // move 6 bits into place + for (int i = 0; i < BLOCK_SIZE; i++) + decodedBuffer[i] = decodeDos33b[i + 86]; + + // reattach each byte's last 2 bits + for (int i = 0, j = 86, k = 172; i < 86; i++, j++, k++) + { + byte val = decodeDos33b[i]; + + decodedBuffer[i] |= reverse ((val & 0x0C) >> 2); + decodedBuffer[j] |= reverse ((val & 0x30) >> 4); + + if (k < BLOCK_SIZE) + decodedBuffer[k] |= reverse ((val & 0xC0) >> 6); + } + } + catch (Exception e) + { + System.out.println (e); + } + + return decodedBuffer; + } + + // ---------------------------------------------------------------------------------// + // encodeSector + // ---------------------------------------------------------------------------------// + + // convert 256 data bytes into 342 translated bytes plus a checksum + @Override + byte[] encodeSector (byte[] buffer) + { + byte[] encodedBuffer = new byte[BUFFER_WITH_CHECKSUM_SIZE_DOS_33]; + + // move data buffer down to make room for the 86 extra bytes + for (int i = 0; i < BLOCK_SIZE; i++) + encodeDos33a[i + 86] = buffer[i]; + + // build extra 86 bytes from the bits stripped from the data bytes + for (int i = 0; i < 86; i++) + { + int b1 = reverse (buffer[i] & 0x03) << 2; + int b2 = reverse (buffer[i + 86] & 0x03) << 4; + + if (i < 84) + { + int b3 = reverse (buffer[i + 172] & 0x03) << 6; + encodeDos33a[i] = (byte) (b1 | b2 | b3); + } + else + encodeDos33a[i] = (byte) (b1 | b2); + } + + // convert into checksum bytes + byte checksum = 0; + for (int i = 0; i < RAW_BUFFER_SIZE_DOS_33; i++) + { + encodeDos33b[i] = (byte) (checksum ^ encodeDos33a[i]); + checksum = encodeDos33a[i]; + } + encodeDos33b[RAW_BUFFER_SIZE_DOS_33] = checksum; // add checksum to the end + + // remove two bits and convert to translated bytes + for (int i = 0; i < BUFFER_WITH_CHECKSUM_SIZE_DOS_33; i++) + encodedBuffer[i] = byteTranslator62.encode (encodeDos33b[i]); + + return encodedBuffer; + } + + // ---------------------------------------------------------------------------------// + // reverse + // ---------------------------------------------------------------------------------// + + // reverse 2 bits - 0 <= bits <= 3 + private static int reverse (int bits) + { + return bits == 1 ? 2 : bits == 2 ? 1 : bits; + } + + // ---------------------------------------------------------------------------------// + // storeBuffer + // ---------------------------------------------------------------------------------// + + @Override + void storeBuffer (DiskSector diskSector, byte[] diskBuffer) + { + DiskAddressField addressField = diskSector.addressField; + byte[] sectorBuffer = diskSector.buffer; + int offset = addressField.track * 0x1000 + interleave[addressField.sector] * 256; + System.arraycopy (sectorBuffer, 0, diskBuffer, offset, 256); + } + + // ---------------------------------------------------------------------------------// + // expectedDataSize + // ---------------------------------------------------------------------------------// + + @Override + int expectedDataSize () + { + return 343; + } +} diff --git a/src/com/bytezone/diskbrowser/disk/MC3470.java b/src/com/bytezone/diskbrowser/disk/MC3470.java new file mode 100644 index 0000000..c49ee2c --- /dev/null +++ b/src/com/bytezone/diskbrowser/disk/MC3470.java @@ -0,0 +1,229 @@ +package com.bytezone.diskbrowser.disk; + +import java.util.ArrayList; +import java.util.List; + +class MC3470 +{ + private final boolean debug = false; + + private final byte[] dataBuffer = new byte[411]; + int dataPtr = 0; + + private final List diskSectors = new ArrayList<> (); + DiskReader diskReader; + + State currentState; + DiskSector currentDiskSector; + int expectedDataSize; + + DiskReader diskReader16 = new DiskReader16Sector (); + DiskReader diskReader13 = new DiskReader13Sector (); + + enum State + { + ADDRESS, DATA, OTHER + } + + // ---------------------------------------------------------------------------------// + // readTrack + // ---------------------------------------------------------------------------------// + + void readTrack (byte[] buffer, int offset, int bytesUsed, int bitCount) + { + int value = 0; + + final int max = offset + bytesUsed; + int totalBits = 0; + + diskSectors.clear (); + currentDiskSector = null; + currentState = State.OTHER; + + if (debug) + { + System.out.printf ("%nOffset : %06X%n", offset); + System.out.printf ("Bytes used: %06X%n", bytesUsed); + } + + int inPtr = offset; + while (inPtr < max) + { + int b = buffer[inPtr++] & 0xFF; + for (int mask = 0x80; mask != 0; mask >>>= 1) + { + value <<= 1; + if ((b & mask) != 0) + value |= 1; + + ++totalBits; + + if ((value & 0x80) != 0) // is hi-bit set? + { + dataBuffer[dataPtr++] = (byte) value; + checkState (value); + value = 0; + } + } + if (inPtr == max && currentState == State.DATA) + { + System.out.println ("Unfinished business"); + } + } + + // if (bytesUsed > outputBuffer.length) + // { + // System.out.printf ("Bytes used %,5d%n", bytesUsed); + // System.out.printf ("Buffer size %,5d%n", outPtr); + // } + + if (value != 0) + System.out.printf ("********** Value not used: %01X%n", value); + } + + // ---------------------------------------------------------------------------------// + // storeSectors + // ---------------------------------------------------------------------------------// + + void storeSectors (byte[] diskBuffer) + { + for (DiskSector diskSector : diskSectors) + diskReader.storeBuffer (diskSector, diskBuffer); + } + + // ---------------------------------------------------------------------------------// + // checkState + // ---------------------------------------------------------------------------------// + + private void checkState (int value) + { + if (value == 0xB5 && isPrologue ()) + { + diskReader = diskReader13; + setState (State.ADDRESS); + } + + if (value == 0x96 && isPrologue ()) + { + diskReader = diskReader16; + setState (State.ADDRESS); + } + + if (value == 0xAD && isPrologue ()) + setState (State.DATA); + + if (value == 0xEB && isEpilogue ()) + setState (State.OTHER); + + if (dataPtr == expectedDataSize) + setState (State.OTHER); + } + + // ---------------------------------------------------------------------------------// + // setState + // ---------------------------------------------------------------------------------// + + private void setState (State newState) + { + if (currentState == newState && currentState == State.OTHER) + return; + assert currentState != newState; + + switch (currentState) // this state is now finished + { + case ADDRESS: + currentDiskSector = new DiskSector (new DiskAddressField (dataBuffer, 0)); + break; + + case DATA: + currentDiskSector.setBuffer (diskReader.decodeSector (dataBuffer, 0)); + diskSectors.add (currentDiskSector); + break; + + case OTHER: + break; + } + + currentState = newState; + dataPtr = 0; // start collecting new buffer + + switch (currentState) // this state is now starting + { + case ADDRESS: + expectedDataSize = 8; + break; + + case DATA: + expectedDataSize = diskReader.expectedDataSize (); + break; + + case OTHER: + expectedDataSize = -1; // unspecified length + break; + } + } + + // ---------------------------------------------------------------------------------// + // is13Sector + // ---------------------------------------------------------------------------------// + + boolean is13Sector () + { + return diskSectors.size () == 13 && diskReader.sectorsPerTrack == 13; + } + + // ---------------------------------------------------------------------------------// + // is16Sector + // ---------------------------------------------------------------------------------// + + boolean is16Sector () + { + return diskSectors.size () == 16 && diskReader.sectorsPerTrack == 16; + } + + // ---------------------------------------------------------------------------------// + // isPrologue + // ---------------------------------------------------------------------------------// + + private boolean isPrologue () + { + return dataPtr >= 3 && dataBuffer[dataPtr - 3] == (byte) 0xD5 + && dataBuffer[dataPtr - 2] == (byte) 0xAA; + } + + // ---------------------------------------------------------------------------------// + // isEpilogue + // ---------------------------------------------------------------------------------// + + private boolean isEpilogue () + { + return dataPtr >= 3 && dataBuffer[dataPtr - 3] == (byte) 0xDE + && dataBuffer[dataPtr - 2] == (byte) 0xAA; + } + + // ---------------------------------------------------------------------------------// + // DiskSector + // ---------------------------------------------------------------------------------// + + class DiskSector + { + DiskAddressField addressField; + byte[] buffer; + + DiskSector (DiskAddressField addressField) + { + this.addressField = addressField; + } + + void setBuffer (byte[] buffer) + { + this.buffer = buffer; + } + + @Override + public String toString () + { + return addressField.toString (); + } + } +} diff --git a/src/com/bytezone/diskbrowser/disk/Nibblizer.java b/src/com/bytezone/diskbrowser/disk/Nibblizer.java index c5adeb4..e469260 100644 --- a/src/com/bytezone/diskbrowser/disk/Nibblizer.java +++ b/src/com/bytezone/diskbrowser/disk/Nibblizer.java @@ -2,6 +2,8 @@ package com.bytezone.diskbrowser.disk; class Nibblizer { + // still used by NibDisk and V2dDisk + private static byte[] addressPrologue32 = { (byte) 0xD5, (byte) 0xAA, (byte) 0xB5 }; private static byte[] addressPrologue33 = { (byte) 0xD5, (byte) 0xAA, (byte) 0x96 }; private static byte[] dataPrologue = { (byte) 0xD5, (byte) 0xAA, (byte) 0xAD }; @@ -11,53 +13,13 @@ class Nibblizer { 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 }; private static final int BLOCK_SIZE = 256; - private static final int TRACK_SIZE = 4096; private static final int RAW_BUFFER_SIZE_DOS_33 = 342; private static final int RAW_BUFFER_SIZE_DOS_32 = 410; private static final int BUFFER_WITH_CHECKSUM_SIZE_DOS_33 = RAW_BUFFER_SIZE_DOS_33 + 1; private static final int BUFFER_WITH_CHECKSUM_SIZE_DOS_32 = RAW_BUFFER_SIZE_DOS_32 + 1; - // 32 valid bytes that can be stored on a disk (plus 0xAA and 0xD5) - private static byte[] writeTranslateTable5and3 = - { (byte) 0xAB, (byte) 0xAD, (byte) 0xAE, (byte) 0xAF, (byte) 0xB5, (byte) 0xB6, - (byte) 0xB7, (byte) 0xBA, (byte) 0xBB, (byte) 0xBD, (byte) 0xBE, (byte) 0xBF, - (byte) 0xD6, (byte) 0xD7, (byte) 0xDA, (byte) 0xDB, // - (byte) 0xDD, (byte) 0xDE, (byte) 0xDF, (byte) 0xEA, (byte) 0xEB, (byte) 0xED, - (byte) 0xEE, (byte) 0xEF, (byte) 0xF5, (byte) 0xF6, (byte) 0xF7, (byte) 0xFA, - (byte) 0xFB, (byte) 0xFD, (byte) 0xFE, (byte) 0xFF }; - - // 64 valid bytes that can be stored on a disk (plus 0xAA and 0xD5) - private static byte[] writeTranslateTable6and2 = - { (byte) 0x96, (byte) 0x97, (byte) 0x9A, (byte) 0x9B, (byte) 0x9D, (byte) 0x9E, - (byte) 0x9F, (byte) 0xA6, (byte) 0xA7, (byte) 0xAB, (byte) 0xAC, (byte) 0xAD, - (byte) 0xAE, (byte) 0xAF, (byte) 0xB2, (byte) 0xB3, // - (byte) 0xB4, (byte) 0xB5, (byte) 0xB6, (byte) 0xB7, (byte) 0xB9, (byte) 0xBA, - (byte) 0xBB, (byte) 0xBC, (byte) 0xBD, (byte) 0xBE, (byte) 0xBF, (byte) 0xCB, - (byte) 0xCD, (byte) 0xCE, (byte) 0xCF, (byte) 0xD3, // - (byte) 0xD6, (byte) 0xD7, (byte) 0xD9, (byte) 0xDA, (byte) 0xDB, (byte) 0xDC, - (byte) 0xDD, (byte) 0xDE, (byte) 0xDF, (byte) 0xE5, (byte) 0xE6, (byte) 0xE7, - (byte) 0xE9, (byte) 0xEA, (byte) 0xEB, (byte) 0xEC, // - (byte) 0xED, (byte) 0xEE, (byte) 0xEF, (byte) 0xF2, (byte) 0xF3, (byte) 0xF4, - (byte) 0xF5, (byte) 0xF6, (byte) 0xF7, (byte) 0xF9, (byte) 0xFA, (byte) 0xFB, - (byte) 0xFC, (byte) 0xFD, (byte) 0xFE, (byte) 0xFF }; - - private static byte[] readTranslateTable5and3 = new byte[85]; // skip first 171 blanks - private static byte[] readTranslateTable6and2 = new byte[106]; // skip first 150 blanks - - static - { - for (int i = 0; i < writeTranslateTable5and3.length; i++) - { - int j = (writeTranslateTable5and3[i] & 0xFF) - 0xAB; // skip first 171 blanks - readTranslateTable5and3[j] = (byte) (i + 1); // offset by 1 to avoid zero - } - - for (int i = 0; i < writeTranslateTable6and2.length; i++) - { - int j = (writeTranslateTable6and2[i] & 0xFF) - 0x96; // skip first 150 blanks - readTranslateTable6and2[j] = (byte) (i + 1); // offset by 1 to avoid zero - } - } + private final ByteTranslator byteTranslator62 = new ByteTranslator6and2 (); + private final ByteTranslator byteTranslator53 = new ByteTranslator5and3 (); private final byte[] decodeDos33a = new byte[BUFFER_WITH_CHECKSUM_SIZE_DOS_33]; private final byte[] decodeDos33b = new byte[RAW_BUFFER_SIZE_DOS_33]; @@ -68,52 +30,35 @@ class Nibblizer private final byte[] decodeDos32a = new byte[BUFFER_WITH_CHECKSUM_SIZE_DOS_32]; private final byte[] decodeDos32b = new byte[RAW_BUFFER_SIZE_DOS_32]; - enum DosVersion - { - DOS_3_2, DOS_3_3 - } - - private DosVersion currentDosVersion; - int sectorsPerTrack; + private int sectorsPerTrack; // ---------------------------------------------------------------------------------// // processTrack // ---------------------------------------------------------------------------------// - boolean processTrack (int trackNo, byte[] buffer, byte[] diskBuffer) + boolean processTrack (int trackNo, int maxTracks, byte[] buffer, byte[] diskBuffer) { int ptr = 0; int totalSectors = 0; boolean[] sectorsFound = new boolean[16]; + sectorsPerTrack = maxTracks; try { while (ptr < buffer.length) { - int ptr2 = findBytes (buffer, ptr, addressPrologue33); - if (ptr2 >= 0) - { - currentDosVersion = DosVersion.DOS_3_3; - sectorsPerTrack = 16; - } + if (sectorsPerTrack == 13) + ptr = findBytes (buffer, ptr, addressPrologue32); else - { - ptr2 = findBytes (buffer, ptr, addressPrologue32); - if (ptr2 >= 0) - { - currentDosVersion = DosVersion.DOS_3_2; - sectorsPerTrack = 13; - } - else - { - System.out.printf ("Track: %02X/%02X - Address prologue not found%n", trackNo, - totalSectors); - return false; - } - } - ptr = ptr2; + ptr = findBytes (buffer, ptr, addressPrologue33); - AddressField addressField = getAddressField (buffer, ptr); + if (ptr < 0) + { + System.out.printf ("Track: %02X - Address prologue not found%n", trackNo); + return false; + } + + AddressField addressField = new AddressField (buffer, ptr); if (!addressField.isValid ()) { System.out.printf ("Track: %02X - Invalid address field%n", trackNo); @@ -145,26 +90,23 @@ class Nibblizer return false; } - DataField dataField = getDataField (buffer, ptr); + DataField dataField = new DataField (buffer, ptr); if (!dataField.isValid ()) { System.out.printf ("Track: %02X - Invalid data field%n", trackNo); return false; } - int offset = addressField.track * TRACK_SIZE; - if (currentDosVersion == DosVersion.DOS_3_2) - offset += addressField.sector * BLOCK_SIZE; + int offset; + if (sectorsPerTrack == 13) + offset = addressField.track * 0x0D00 + addressField.sector * BLOCK_SIZE; else - offset += interleave[addressField.sector] * BLOCK_SIZE; + offset = + addressField.track * 0x1000 + interleave[addressField.sector] * BLOCK_SIZE; System.arraycopy (dataField.dataBuffer, 0, diskBuffer, offset, BLOCK_SIZE); - ++totalSectors; - - if (currentDosVersion == DosVersion.DOS_3_2 && totalSectors == 13) - break; - if (currentDosVersion == DosVersion.DOS_3_3 && totalSectors == 16) + if (++totalSectors == sectorsPerTrack) break; ptr += dataField.size (); @@ -175,13 +117,7 @@ class Nibblizer e.printStackTrace (); } - if (currentDosVersion == DosVersion.DOS_3_2 && totalSectors != 13) - { - System.out.printf ("Track: %02X - Sectors found: %02X%n", trackNo, totalSectors); - return false; - } - - if (currentDosVersion == DosVersion.DOS_3_3 && totalSectors != 16) + if (totalSectors != sectorsPerTrack) { System.out.printf ("Track: %02X - Sectors found: %02X%n", trackNo, totalSectors); return false; @@ -190,24 +126,6 @@ class Nibblizer return true; } - // ---------------------------------------------------------------------------------// - // getAddressField - // ---------------------------------------------------------------------------------// - - private AddressField getAddressField (byte[] buffer, int offset) - { - return new AddressField (buffer, offset); - } - - // ---------------------------------------------------------------------------------// - // getDataField - // ---------------------------------------------------------------------------------// - - private DataField getDataField (byte[] buffer, int offset) - { - return new DataField (buffer, offset); - } - // ---------------------------------------------------------------------------------// // decode4and4 // ---------------------------------------------------------------------------------// @@ -225,113 +143,105 @@ class Nibblizer private byte[] decode5and3 (byte[] buffer, int offset) { - // convert legal disk values to actual 5 bit values - for (int i = 0; i < BUFFER_WITH_CHECKSUM_SIZE_DOS_32; i++) // 411 bytes - decodeDos32a[i] = getByte5and3 (buffer[offset++]); - - // reconstruct 410 bytes each with 5 bits - byte chk = 0; - int ptr = 0; - for (int i = 409; i >= 256; i--) // 154 bytes - chk = decodeDos32b[i] = (byte) (decodeDos32a[ptr++] ^ chk); - for (int i = 0; i < 256; i++) // 256 bytes - chk = decodeDos32b[i] = (byte) (decodeDos32a[ptr++] ^ chk); - assert (chk ^ decodeDos32a[ptr]) == 0; - // rearrange 410 bytes into 256 byte[] decodedBuffer = new byte[BLOCK_SIZE]; // 256 bytes - byte[] k = new byte[8]; - ptr = 0; - int[] lines = { 0, 51, 102, 153, 204, 256, 307, 358 }; // NB 255 is skipped - // process 8 disk bytes at a time, giving 5 valid bytes - // do this 51 times, giving 255 bytes - for (int i = 50; i >= 0; i--) + try { - for (int j = 0; j < 8; j++) - k[j] = decodeDos32b[i + lines[j]]; + // convert legal disk values to actual 5 bit values + for (int i = 0; i < BUFFER_WITH_CHECKSUM_SIZE_DOS_32; i++) // 411 bytes + { + // System.out.printf ("%,5d %02X%n", i, buffer[offset]); + decodeDos32a[i] = byteTranslator53.decode (buffer[offset++]); + } - k[0] |= (k[5] & 0xE0) >>> 5; - k[1] |= (k[6] & 0xE0) >>> 5; - k[2] |= (k[7] & 0xE0) >>> 5; + // reconstruct 410 bytes each with 5 bits + byte chk = 0; + int ptr = 0; + for (int i = 409; i >= 256; i--) // 154 bytes + chk = decodeDos32b[i] = (byte) (decodeDos32a[ptr++] ^ chk); + for (int i = 0; i < 256; i++) // 256 bytes + chk = decodeDos32b[i] = (byte) (decodeDos32a[ptr++] ^ chk); + assert (chk ^ decodeDos32a[ptr]) == 0; - k[3] |= (k[5] & 0x10) >>> 2; - k[3] |= (k[6] & 0x10) >>> 3; - k[3] |= (k[7] & 0x10) >>> 4; + byte[] k = new byte[8]; + ptr = 0; + final int[] lines = { 0, 51, 102, 153, 204, 256, 307, 358 }; // 255 is skipped - k[4] |= (k[5] & 0x08) >>> 1; - k[4] |= (k[6] & 0x08) >>> 2; - k[4] |= (k[7] & 0x08) >>> 3; + // process 8 disk bytes at a time, giving 5 valid bytes + // do this 51 times, giving 255 bytes + for (int i = 50; i >= 0; i--) + { + for (int j = 0; j < 8; j++) + k[j] = decodeDos32b[i + lines[j]]; + + k[0] |= (k[5] & 0xE0) >>> 5; + k[1] |= (k[6] & 0xE0) >>> 5; + k[2] |= (k[7] & 0xE0) >>> 5; + + k[3] |= (k[5] & 0x10) >>> 2; + k[3] |= (k[6] & 0x10) >>> 3; + k[3] |= (k[7] & 0x10) >>> 4; + + k[4] |= (k[5] & 0x08) >>> 1; + k[4] |= (k[6] & 0x08) >>> 2; + k[4] |= (k[7] & 0x08) >>> 3; + + for (int j = 0; j < 5; j++) + decodedBuffer[ptr++] = k[j]; + } + + // add last byte + decodedBuffer[255] = (byte) (decodeDos32b[255] | (decodeDos32b[409] >>> 3)); + } + catch (Exception e) + { - for (int j = 0; j < 5; j++) - decodedBuffer[ptr++] = k[j]; } - // add last byte - decodedBuffer[255] = (byte) (decodeDos32b[255] | (decodeDos32b[409] >>> 3)); - return decodedBuffer; } - // ---------------------------------------------------------------------------------// - // getByte5and3 - // ---------------------------------------------------------------------------------// - - private byte getByte5and3 (byte b) - { - int val = (b & 0xFF) - 0xAB; // 0 - 84 - assert val >= 0 && val <= 84; - byte trans = (byte) (readTranslateTable5and3[val] - 1); // 0 - 31 (5 bits) - assert trans >= 0 && trans <= 31; - return (byte) (trans << 3); // left justify 5 bits - } - - // ---------------------------------------------------------------------------------// - // getByte6and2 - // ---------------------------------------------------------------------------------// - - private byte getByte6and2 (byte b) - { - int val = (b & 0xFF) - 0x96; // 0 - 105 - assert val >= 0 && val <= 105; - byte trans = (byte) (readTranslateTable6and2[val] - 1); // 0 - 63 (6 bits) - assert trans >= 0 && trans <= 63; - return (byte) (trans << 2); // left justify 6 bits - } - // ---------------------------------------------------------------------------------// // decode6and2 // ---------------------------------------------------------------------------------// private byte[] decode6and2 (byte[] buffer, int offset) { - // convert legal disk values to actual 6 bit values - for (int i = 0; i < BUFFER_WITH_CHECKSUM_SIZE_DOS_33; i++) // 343 bytes - decodeDos33a[i] = getByte6and2 (buffer[offset++]); - - // reconstruct 342 bytes each with 6 bits - byte chk = 0; - for (int i = decodeDos33b.length - 1; i >= 0; i--) // 342 bytes - chk = decodeDos33b[i] = (byte) (decodeDos33a[i + 1] ^ chk); - assert (chk ^ decodeDos33a[0]) == 0; - // rearrange 342 bytes into 256 byte[] decodedBuffer = new byte[BLOCK_SIZE]; // 256 bytes - // move 6 bits into place - for (int i = 0; i < BLOCK_SIZE; i++) - decodedBuffer[i] = decodeDos33b[i + 86]; - - // reattach each byte's last 2 bits - for (int i = 0, j = 86, k = 172; i < 86; i++, j++, k++) + try { - byte val = decodeDos33b[i]; + // convert legal disk values to actual 6 bit values + for (int i = 0; i < BUFFER_WITH_CHECKSUM_SIZE_DOS_33; i++) // 343 bytes + decodeDos33a[i] = byteTranslator62.decode (buffer[offset++]); - decodedBuffer[i] |= reverse ((val & 0x0C) >> 2); - decodedBuffer[j] |= reverse ((val & 0x30) >> 4); + // reconstruct 342 bytes each with 6 bits + byte chk = 0; + for (int i = decodeDos33b.length - 1; i >= 0; i--) // 342 bytes + chk = decodeDos33b[i] = (byte) (decodeDos33a[i + 1] ^ chk); + assert (chk ^ decodeDos33a[0]) == 0; + + // move 6 bits into place + for (int i = 0; i < BLOCK_SIZE; i++) + decodedBuffer[i] = decodeDos33b[i + 86]; + + // reattach each byte's last 2 bits + for (int i = 0, j = 86, k = 172; i < 86; i++, j++, k++) + { + byte val = decodeDos33b[i]; + + decodedBuffer[i] |= reverse ((val & 0x0C) >> 2); + decodedBuffer[j] |= reverse ((val & 0x30) >> 4); + + if (k < BLOCK_SIZE) + decodedBuffer[k] |= reverse ((val & 0xC0) >> 6); + } + } + catch (Exception e) + { - if (k < BLOCK_SIZE) - decodedBuffer[k] |= reverse ((val & 0xC0) >> 6); } return decodedBuffer; @@ -376,7 +286,8 @@ class Nibblizer // remove two bits and convert to translated bytes for (int i = 0; i < BUFFER_WITH_CHECKSUM_SIZE_DOS_33; i++) - encodedBuffer[i] = writeTranslateTable6and2[(encodeDos33b[i] & 0xFC) / 4]; + // encodedBuffer[i] = writeTranslateTable6and2[(encodeDos33b[i] & 0xFC) / 4]; + encodedBuffer[i] = byteTranslator62.encode (encodeDos33b[i]); return encodedBuffer; } @@ -496,17 +407,11 @@ class Nibblizer { super (buffer, offset); - // if (matchBytes (buffer, offset, addressPrologue33)) - // // && matchBytes (buffer, offset + 11, epilogue)) - // { volume = decode4and4 (buffer, offset + 3); track = decode4and4 (buffer, offset + 5); sector = decode4and4 (buffer, offset + 7); checksum = decode4and4 (buffer, offset + 9); valid = true; - // } - // else - // System.out.println (listBytes (buffer, offset, 14)); length = 14; } @@ -534,10 +439,10 @@ class Nibblizer if (matchBytes (buffer, offset, dataPrologue)) { valid = true; - if (currentDosVersion == DosVersion.DOS_3_3) - dataBuffer = decode6and2 (buffer, offset + 3); - else if (currentDosVersion == DosVersion.DOS_3_2) + if (sectorsPerTrack == 13) dataBuffer = decode5and3 (buffer, offset + 3); + else + dataBuffer = decode6and2 (buffer, offset + 3); } else { diff --git a/src/com/bytezone/diskbrowser/disk/V2dDisk.java b/src/com/bytezone/diskbrowser/disk/V2dDisk.java index 77ffbb8..060dd74 100644 --- a/src/com/bytezone/diskbrowser/disk/V2dDisk.java +++ b/src/com/bytezone/diskbrowser/disk/V2dDisk.java @@ -85,7 +85,7 @@ class V2dDisk int halfTrackNo = trackNumber % 4; if (halfTrackNo == 0) // only process full tracks - nibbler.processTrack (fullTrackNo, trackData, diskBuffer); + nibbler.processTrack (fullTrackNo, 16, trackData, diskBuffer); else System.out.printf ("%s skipping half track %02X / %02X%n", file.getName (), fullTrackNo, halfTrackNo); diff --git a/src/com/bytezone/diskbrowser/disk/WozDisk.java b/src/com/bytezone/diskbrowser/disk/WozDisk.java index 6291b63..a0a2458 100644 --- a/src/com/bytezone/diskbrowser/disk/WozDisk.java +++ b/src/com/bytezone/diskbrowser/disk/WozDisk.java @@ -10,18 +10,20 @@ import com.bytezone.diskbrowser.utilities.Utility; class WozDisk { + private static final byte[] WOZ_DISK_HEADER = + { 0x57, 0x4F, 0x5A, 0x31, (byte) 0xFF, 0x0a, 0x0D, 0x0A }; private static final int TRK_SIZE = 0x1A00; private static final int INFO_SIZE = 0x3C; private static final int TMAP_SIZE = 0xA0; private static final int DATA_SIZE = TRK_SIZE - 10; - private static byte[] header = - { 0x57, 0x4F, 0x5A, 0x31, (byte) 0xFF, 0x0a, 0x0D, 0x0A }; + private final boolean debug = false; private int diskType; // 5.25 or 3.5 - int sectorsPerTrack; final File file; - final byte[] diskBuffer = new byte[4096 * 35]; + byte[] diskBuffer; + + private final MC3470 mc3470 = new MC3470 (); // ---------------------------------------------------------------------------------// // constructor @@ -30,10 +32,9 @@ class WozDisk public WozDisk (File file) throws Exception { this.file = file; - Nibblizer nibbler = new Nibblizer (); byte[] buffer = readFile (); - if (!matches (header, buffer)) + if (!matches (WOZ_DISK_HEADER, buffer)) throw new Exception ("Header error"); int cs1 = readInt (buffer, 8, 4); @@ -88,7 +89,8 @@ class WozDisk if (debug) System.out.println ("Reading TRKS"); int tracks = chunkSize / TRK_SIZE; - for (int track = 0; track < tracks; track++) + + for (int trackNo = 0; trackNo < tracks; trackNo++) { int bytesUsed = readInt (buffer, ptr + DATA_SIZE, 2); int bitCount = readInt (buffer, ptr + DATA_SIZE + 2, 2); @@ -99,22 +101,37 @@ class WozDisk System.out.printf ("Bit count .... %,6d%n", bitCount); } - byte[] trackData = readTrack (buffer, ptr, bytesUsed, bitCount); - if (!nibbler.processTrack (track, trackData, diskBuffer)) + try { - System.out.println ("Nibblizer failure"); - if (debug) - System.out.println (HexFormatter.format (trackData)); - break read; + mc3470.readTrack (buffer, ptr, bytesUsed, bitCount); + + if (trackNo == 0) + { + if (mc3470.is13Sector ()) + diskBuffer = new byte[35 * 13 * 256]; + else if (mc3470.is16Sector ()) + diskBuffer = new byte[35 * 16 * 256]; + else + { + System.out.println ("unknown disk format"); + break read; + } + } + + mc3470.storeSectors (diskBuffer); } + catch (Exception e) + { + e.printStackTrace (); + } + ptr += TRK_SIZE; - if (track == 0) - sectorsPerTrack = nibbler.sectorsPerTrack; } } else if ("META".equals (chunkId)) { System.out.printf ("[%s] %08X%n", chunkId, chunkSize); + System.out.println (HexFormatter.format (buffer, ptr, chunkSize)); ptr += chunkSize; } else @@ -125,6 +142,15 @@ class WozDisk } } + // ---------------------------------------------------------------------------------// + // getSectorsPerTrack + // ---------------------------------------------------------------------------------// + + int getSectorsPerTrack () + { + return mc3470.is13Sector () ? 13 : 16; + } + // ---------------------------------------------------------------------------------// // readInt // ---------------------------------------------------------------------------------// @@ -141,48 +167,6 @@ class WozDisk return value; } - // ---------------------------------------------------------------------------------// - // readTrack - // ---------------------------------------------------------------------------------// - - private byte[] readTrack (byte[] buffer, int offset, int bytesUsed, int bitCount) - { - byte[] trackData = new byte[bytesUsed]; - int value = 0; - int ptr = 0; - final int max = offset + bytesUsed; - int count = 0; - - for (int i = offset; i < max; i++) - { - int b = buffer[i] & 0xFF; - for (int mask = 0x80; mask > 0; mask >>>= 1) - { - value <<= 1; - if ((b & mask) != 0) - value |= 1; - - ++count; - - if ((value & 0x80) != 0) // is hi-bit set? - { - trackData[ptr++] = (byte) value; - value = 0; - } - } - } - - if (value != 0) - System.out.printf ("********** Value not used: %01X%n", value); - if (debug && bitCount != count) - { - System.out.printf ("BitCount: %,4d%n", bitCount); - System.out.printf ("Actual : %,4d%n", count); - } - - return trackData; - } - // ---------------------------------------------------------------------------------// // readFile // ---------------------------------------------------------------------------------//